2015-06-26 123 views
1

我想編寫一個Java類來根據關聯的時間戳計算一些規則(對於每個rueleId)的出現次數。Java hashmap - 基於不同類型的兩個對象的密鑰

例如,

輸入:

{"ruleId": "1", "timestamp":"Thu Jun 18 16:25:56 PDT 2015"} 
{"ruleId": "1", "timestamp":"Thu Jun 18 16:25:56 PDT 2015"} 
{"ruleId": "2", "timestamp":"Thu Jun 18 16:25:56 PDT 2015"} 
{"ruleId": "2", "timestamp":"Thu Jun 18 16:25:56 PDT 2015"} 
{"ruleId": "2", "timestamp":"Thu Jun 18 16:27:56 PDT 2015"} 

輸出:

timestamp: "Thu Jun 18 16:25:56 PDT 2015", ruleId: "1", count: 2 
timestamp: "Thu Jun 18 16:25:56 PDT 2015", ruleId: "2", count: 2 
timestamp: "Thu Jun 18 16:27:56 PDT 2015", ruleId: "2", count: 1 

我想我可以利用一個HashMap的。

這裏的關鍵我認爲是基於規則ID(類型:字符串)和時間戳(類型:日曆)與值是計數。

如何根據兩個不同的對象擁有一個鍵? 我的方法錯了嗎?

回答

3

你必須創建一個複合鍵

public final class CompositeKey { 
    private final String ruleType; 
    private final Calendar timeStamp; 

    public CompositeKey(String ruleType, Calendar timeStamp) { 
     this.ruleType = Objects.requireNonNull(ruleType); 
     this.timeStamp = (Calendar) Objects.requireNonNull(timeStamp).clone(); 
    } 

    public String ruleType() { return ruleType; } 
    public Calendar timeStamp() { return (Calendar) timeStamp.clone(); } 

    @Override public boolean equals(Object obj) { 
     if (this == obj) return true; 
     if (obj == null) return false; 
     if (getClass() != obj.getClass()) return false; 
     CompositeKey other = (CompositeKey) obj; 
     return Objects.equals(ruleType, other.ruleType) && Objects.equals(timeStamp, other.timeStamp); 
    } 

    @Override public int hashCode() { return Objects.hash(ruleType, timeStamp); } 
} 

重要的是,當被用作在HashMap的關鍵對象不能被修改。因此它必須是不可變的。上面的類通過最終實現這個目標,不提供setter和克隆時間戳(因爲Calendar不是不可變的)。

另一個非常重要的事情是,關鍵類必須提供適當的方法equalshashCode

有了這個類,你可以在HashMap使用它:

String ruleType = ... 
Calendar timeStamp = ... 
CompositeKey key = new CompositeKey(ruleType, timeStamp); 
Object value = ... 

Map<CompositeKey, Object> map = new HashMap<>(); 
map.put(key, value); 
2

一個HashMap只有一點鍵式。這就是它的方式。

所以你有兩個選擇。

生成充當HashMap的Key的密鑰字符串。在你的情況下,這是可以輕鬆完成的事情,它可能只是你所需要的。你可以生成類似"time:" + timeStamp.toString() + "-rule:" + ruleId的東西,並將其用作關鍵字。它會在你的情況下做到這一點。

第二種方法稍微複雜一點,但如果您想要再次分開您在密鑰中使用的值或者您有更復雜的值作爲密鑰,則更適合。這個想法是創建一個新的類,作爲您的關鍵價值的載體。

第二個想法的重要之處在於,您可以覆蓋載體對象的hashCodeequals函數,使其與HashMap正常工作。

基本上你需要這樣的事:

public class Carrier { 
    private final Calendar timestamp; 
    private final String ruleId; 

    public Carrier(Calendar timestamp, String ruleId) { 
     this.timestamp = timestamp; 
     this.ruleId = ruleId; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 1; 
     hash = hash * 17 + timestamp.hashCode(); 
     hash = hash * 17 + ruleId.hashCode(); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (!(obj instanceOf Carrier) { 
      return false; 
     } 

     Carrier other = (Carrier) obj; 
     return Objects.equals(ruleId, other.ruleId) && Objects.equals(timestamp, other.timestamp); 
    } 
}