2014-11-24 1 views
3

"HashMap"을 확장하는 Subscriber라는 클래스가 있습니다. 이 클래스의 많은 인스턴스가 목록에 있으며 각 인스턴스에는지도에 설정된 항목 집합이 있으며 그 중 하나는 '상태'입니다.어떻게 내 HashMap에 중복 키가 있습니까?

우리 프로그램은 구독자의 메서드를 호출하여 "상태"값을 업데이트합니다.이 메서드는 HashMap에 단순하게 넣습니다.

우리 프로그램은 아무런 문제없이 여러 날 (주) 동안 실행될 수 있지만, HashMap의 데이터를 사용하는 시스템의 다른 부분에서는 이상한 동작을 보았을 수 있습니다. 하나 이상의 Subscriber 인스턴스에 중복 키가있는 것 같습니다.

우리는 jmap 덤프를 만들었고 덤프를 기반으로 VisualVM에서 덤프를 볼 때 "상태"가 두 번 설정되어 있는지 찾습니다.

Screenshot of VisualVM

우리는 현재 Java 버전 실행 : 1.7.0_25 (오라클)

어떻게 이런 일이 가능를? 또는 VisualVM을 잘못 읽었습니까? 그들은지도에 추가 후가 변경 될 수 있습니다

class Key implements CharSequence { 

    private byte[] key; 

    public Key(String key) { 
     // Take a copy of the bytes of the string. 
     this.key = key.getBytes(); 
    } 

    @Override 
    public int length() { 
     return key.length; 
    } 

    @Override 
    public char charAt(int index) { 
     return (char) key[index]; 
    } 

    @Override 
    public CharSequence subSequence(int start, int end) { 
     return new Key(new String(key).substring(start, end)); 
    } 

    // Allow the key to change. 
    public void setKey(String newValue) { 
     key = newValue.getBytes(); 
    } 

    @Override 
    public String toString() { 
     return new String(key); 
    } 
} 

public void test() { 
    Map<CharSequence, String> testMap = new HashMap<>(); 
    Key aKey = new Key("a"); 
    Key bKey = new Key("b"); 
    testMap.put(aKey, "a"); 
    testMap.put(bKey, "b"); 
    bKey.setKey("a"); 
    System.out.println(testMap.keySet()); 
} 

이 본질적으로 변경 가능한지도의 열쇠를하고있다 :

+2

여러 스레드에서지도에 쓰고 있습니까? –

+0

지도의 열쇠로 사용되는 클래스는 무엇입니까? – AlexR

+1

@JonSkeet 예 전 – goddva

답변

1

외에도 문제를 스레딩에서이 결과에 대한 명확한 경로가있다.

이것은 문제가되지 않을 수도 있지만 (멀티 스레딩 문제가 훨씬 더 많습니다.) 이것은 질문에 대한 실제 답변입니다. 내 HashMap에 중복 키는 어떻게 생깁니 까?.

+0

질문의 제목에 대한 답변입니다. 스크린 샷에서 키가 문자열이라는 것을 알 수 있으므로 전체 질문에 대한 답변이 아닙니다 ;-) – cello

+0

스크린 샷을 제외하면 키 유형이 String임을 분명히 알 수 있습니다. –

관련 문제