2013-07-10 2 views
1

2M 단어에서 50k 개의 단어로 매핑되는 텍스트 파일로 사전이 있습니다. 파일을 한 줄씩 읽고 구분 기호로 나누어 myMap.put(line[0], line[1])을 호출하여이 파일을 HashMap<String, String>으로 메모리에로드합니다. 텍스트 파일의 크기는 45MB이고 HashMap은 350MB의 힙을 사용합니다. 내 목표는 조회 속도를 손상시키지 않고 메모리 사용을 줄이는 것입니다. myMap.values().size()50k 대신 2M을 반환하며 값이 중복 된 것으로 저장되어 있음을 나타냅니다. 동일한 값을 동일한 String 객체를 가리키는 방법이 있습니까?중복 된 값이 HashMap에 저장 됨

Map<String, String> dict = new HashMap<>(); 
try (FileReader fr = new FileReader(FILE); 
     BufferedReader br = new BufferedReader(fr)) { 
    String line; 
    while ((line = br.readLine()) != null) { 
     String key_value[] = line.split(":"); 
     dict.put(key_value[0], key_value[1].intern()); 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
+5

고유 한 단어가 50 만 개가 아닌 2M 개의 고유 단어가있는 경우 해시 맵의 크기는 2M이됩니다. – assylias

+1

해시 맵 크기는 항목 수에 따라 달라 지므로 키 수입니다. 중복 값에 관하여 : JVM은 문자열 값으로 최적화를 수행합니다. 문자열은 불변이므로 동일한 문자열에 대해 동일한 객체를 사용하는 경우가 많습니다. 당신은 그 것에 의지 할 수는 없지만 아마도 당신의 문자열은 이미 복제되지 않았을 것입니다. –

+0

@assylias 알아. 내 질문은 중복 값을 저장하지 않는 방법입니다. 여러 개의 키가 동일한 객체 값에 매핑되도록 가리키는 것입니다. – mossaab

답변

2

값에 String.intern()을 사용하면 모두 동일한 인스턴스를 가리킬 수 있습니다. 그러나 이것은 Java 이전의 가비지 수집 1.7이 아닌 PermGenSpace 사용과 같은 다른 문제점을 가지고 있습니다. 다음과 같이 호출하십시오 : myMap.put(line[0], line[1].intern()).

어쩌면 trie을 기반으로 한지도가 더 효율적 일지 모르지만 나는 아직 사용하지 않았습니다. 또한 문자열의 특성에 따라 다릅니다. 키가 비슷할수록 트리가 저장할 수있는 공간이 넓어집니다.

http://code.google.com/p/trie-map/

또한 Dukeling's answerkeys().size()values().size() 관련된 다른지도의 사용이 중복 값을 방지하기 위해 참조하십시오.

+0

나는 자바 1.7에 있고,'line [ 1] .intern()'. myMap.values ​​(). size()'는 여전히 2M을 반환하고 메모리 사용량은 동일하게 유지됩니다. 표준 솔루션이 제공되지 않으면'trie'를 시도 할 것입니다. – mossaab

+2

+1 다른 방법은 키와 값이 같은 'Map '을 사용하는 것입니다. 값을 검색하여 이전에 사용되었는지 확인하고 동일한 String 객체를 다시 사용할 수 있습니다. 이 "interner"지도는 끝나면 버려 질 수 있습니다. –

+1

@mossaab'myMap.values ​​(). size()'는 2M 키가있는 경우 항상 2M을 반환합니다. – assylias

5

복제본이 동일한 개체를 가리키는 지 여부에 관계없이 여전히 이러한 개체에 대한 참조가 있어야하므로 size은 중복 된 값으로 여전히 크기를 반환해야합니다.

A simple example showing this.

동일한 개체를 가리 키도록 복제본을 만들려면 HashMap 외부에서이 작업을 수행하거나 최적화 프로그램에서 처리해야합니다. 연장 된 자기 기록 컬렉션 가능성이 있습니다 String.intern()joe776 suggested

대안 일부 Set (Set 이후 Object get(Object) 방법이 없음) 또는 다른 HashMap (가진 객체가 자신을 가리) 당신이에 대한 참조를 얻을 수 있습니다 그 공통된 대상.

+0

이 답변에 투표하십시오. 그가 joe776에게 첫 걸음을 내 주면서 크레딧을주었습니다. – mossaab