![](/img/trans.png)
[英]Consistency behaviour of ConcurrentHashMap.keySet().stream()
[英]ConcurrentHashMap - Odd behaviour
誰能讓我知道這段代碼出了什么問題? 我把頭發拉出來!
如果我使用HashMap而不是ConcurrentHashMap沒有任何問題。 代碼使用JDK 5.0編譯
public class MapTest {
public Map<DummyKey, DummyValue> testMap = new ConcurrentHashMap<DummyKey, DummyValue>();
public MapTest() {
DummyKey k1 = new DummyKey("A");
DummyValue v1 = new DummyValue("1");
DummyKey k2 = new DummyKey("B");
DummyValue v2 = new DummyValue("2");
testMap.put(k1, v1);
testMap.put(k2, v2);
}
public void printMap() {
for(DummyKey key : testMap.keySet()){
System.out.println(key.getKeyName());
DummyValue val = testMap.get(key);
System.out.println(val.getValue());
}
}
public static void main(String[] args){
MapTest main = new MapTest();
main.printMap();
}
private static class DummyKey {
private String keyName = "";
public DummyKey(String keyName){
this.keyName = keyName;
}
public String getKeyName() {
return keyName;
}
@Override
public int hashCode() {
return keyName.hashCode();
}
@Override
public boolean equals(Object o) {
return keyName.equals(o);
}
}
private static class DummyValue {
private String value = "";
public DummyValue(String value){
this.value = value;
}
public String getValue() {
return value;
}
}
}
這是輸出:
B
Exception in thread "main" java.lang.NullPointerException
at test.MapTest.printMap(MapTest.java:27)
at test.MapTest.main(MapTest.java:34)
DummyKey.equals
方法實現不正確,因為testMap.get(key)
始終返回null。 嘗試這個
public boolean equals(Object o) {
if (o instanceof DummyKey) {
DummyKey other = (DummyKey) o;
return keyName == null ? other.keyName == null : keyName.equals(other.keyName);
}
return false;
}
hashCode也需要一點改變才能與equals保持一致
public int hashCode() {
return keyName == null ? 0 : keyName.hashCode();
}
這個問題是從equals
的DummyKey
。
當你調用DummyValue val = testMap.get(key);
中, hashcode
函數找到一個匹配(兩個keyname
的k1
和key
是相同的,所以他們的哈希碼)。 然而,equals返回false,因為k1.keyname
等於"A"
,它不等於key
本身,實際上是DummyValue
類型:你沒有正確比較!
因此,您需要修改您的equals函數:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}
請注意,如果更改hashCode(),則還必須更改equals()。 否則,你會遇到問題。 如果equals()為兩個項返回true,那么它們的hashCode()值必須相等! 相反的不是必需的,但更好的散列性能。 這是equals()和hashCode()的實現。
提示:如果您使用的是eclipse,則可以利用其源代碼生成功能為您創建正確的hashCode()和equals()方法。 您唯一需要做的就是選擇標識對象的實例變量。 要在eclipse中執行此操作,請在源代碼打開時,轉到頂部的選項卡並選擇“source”,然后選擇“Generate hashCode()and equals()...”
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());
return result;
}
Override
public boolean equals(Object other) {
if(this == other) return true; //for optimization
if(! other instanceof this) return false; //also covers for when other == null
return this.keyName == null ? other.keyName == null : this.keyName.equals(other.keyName);
}
正如其他人指出的那樣,問題在於你覆蓋hashcode和equals的方式。 兩個選項:1)只需刪除哈希碼和等號,它工作正常2)我讓eclipse生成哈希碼和等號的源,它工作正常。 這就是我的日食對我而言:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((keyName == null) ? 0 : keyName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.