2011-01-06 6 views
21

등호()를 호출하지 않습니다자바 HashMap.containsKey는() 나는 해시 맵이

Map<LotWaferBean, File> hm = new HashMap<LotWaferBean, File>(); 

LotWaferBean lw = new LotWaferBean(); 
... //populate lw 
if (!hm.containsKey((LotWaferBean) lw)) { 
    hm.put(lw, triggerFiles[l]); 
} 

LotWaferBean의 코드 : 나는 equals()에 중단 점을 넣어하지만 내 IDE에서

@Override 
public boolean equals(Object o) { 
     if (!(o instanceof LotWaferBean)) { 
       return false; 
     } 
     if (((LotWaferBean) o).getLotId().equals(lotId) 
        && ((LotWaferBean) o).getWaferNo() == waferNo) { 
       return true; 
     } 
     return false; 
    } 

절대로 실행되지 않습니다. 왜?

답변

38

hashCode()에 중단 점을 넣으십시오.

지도에있는 두 객체의 hashCode()가 동일한 숫자를 반환하면 equals가 호출되어 실제로 같는지 확인합니다.

+14

보다 구체적으로, 만약 당신이'equals' 메쏘드를 구현한다면, 수동으로 작성된대로 hashcode를 구현해야합니다 :) –

+7

쉬운 방법은 이클립스에서 마법사를 사용하는 것입니다. | hashCode() 및 equals()를 생성합니다. –

3

JVM은 해당 해시 코드의 해시 코드 버킷을 검사합니다. 동일한 해시 코드를 가진 더 많은 객체가있는 경우에만 equals() 메소드가 실행됩니다. 그리고 개발자는 hashCode()와 equals() 메소드 사이의 올바른 계약을 따라야합니다.

5

2 개의 해시 코드가 동일한 경우에만 루프 키 중에 equals()이 호출됩니다.

3

2 개의 해시 코드가 같은 경우에만 루프 키 중에 equals()가 호출됩니다.

정답 ... 또는 거의. 정확히 말하면 2 개의 해시 코드가 충돌하면 (같은 해시 맵이 올바른 해시 맵 impl에서 충돌하도록 보장됨) 평등 확인 만 수행됩니다.

1

알아두기, 동일한 방법이 잘못되었을 가능성이 큽니다. LotWaferBean이 재정의되는 경우 equals 메서드는 하위 클래스 인스턴스를 허용하지만 하위 클래스도 사용합니까?

이 더 읽어야 Abimaran Kugathasan가 언급 한 바와 같이

@Override 
public boolean equals(Object o) { 
    if (o == null || o.getClass() != getClass()) { // << this is important 
     return false; 
    } 

    final LotWaferBean other = (LotWaferBean)o; 
    return other.getLotId().equals(lotId) 
       && other.getWaferNo() == waferNo); 
} 
0

가, HashMap의 구현이 효율적으로 키를 찾기 위해 해시 버킷을 사용하고, 단지 등호()를 사용하여 일치하는 해시 버킷의 키를 비교하는 주어진 키에 대해 키가 HashMap에 추가 될 때 해시 - 버킷 에 할당된다는 점에 유의할 필요가 없습니다. HashMap에서 키를 변경 한 후 해시 코드를 변경하는 방식으로 키를 변경하면 적절한 해시 - 버킷에 들어 가지 않습니다. 일치하는 키를 사용하여 맵에 액세스하려고하면 올바른 해시 - 버킷을 찾을 수 있지만 변경된 키는 포함되지 않습니다.

class aMutableType { 
    private int value; 
    public aMutableType(int originalValue) { 
    this.value = originalValue; 
    } 
    public int getValue() { 
    return this.value; 
    } 
    public void setValue(int newValue) { 
    this.value = newValue; 
    } 
    @Override 
    public boolean equals(Object o) { 
     // ... all the normal tests ... 
     return this.value == ((aMutableType) o).value; 
    } 
    @Override 
    public int hashCode() { 
     return Integer.hashCode(this.value); 
    } 
} 
... 
Map<aMutableType, Integer> aMap = new HashMap<>(); 
aMap.put(new aMutableType(5), 3); // puts key in bucket for hash(5) 
for (aMutableType key : new HashSet<>(aMap.keySet())) 
    key.setValue(key.getValue()+1); // key 5 => 6 
if (aMap.containsKey(new aMutableType(6)) 
    doSomething(); // won't get here, even though 
        // there's a key == 6 in the Map, 
        // because that key is in the hash-bucket for 5 

이로 인해 다소 이상하게 보일 수 있습니다. theMap.containsKey (theKey) 바로 전에 중단 점을 설정하고 theKey의 값이 Map의 키와 일치하는지 확인하고 키의 equals()는 호출되지 않으며 containsKey()는 false를 반환합니다.

여기에 언급 된 것처럼 https://stackoverflow.com/a/21601013 실제로 키에 대해 변경 가능한 유형 사용과 관련하여 Map for JavaDoc에 경고가 표시됩니다. 해시가 아닌 유형의지도에는이 특별한 문제가 없지만 키가 변경되면 다른 문제가 발생할 수 있습니다.