我有一个字典作为从2M
字到50k
字的映射文本文件。我通过逐行读取文件,在分隔符上拆分并调用HashMap<String, String>
,将此文件作为myMap.put(line[0], line[1])
加载到内存中。文本文件的大小为45MB
,而HashMap使用堆的350MB
。我的目标是在不损害查找速度的情况下减少内存使用。
myMap.values().size()
返回2M
而非50k
,表示值存储为重复值。有没有办法让相同的值指向同一个String对象?
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();
}
答案 0 :(得分:5)
无论重复是否指向相同的对象,仍然需要引用这些对象,因此size
仍应返回包含重复项的大小。
如果您希望重复项指向相同的对象,则必须在HashMap
之外执行此操作,或希望优化程序处理它。
String.intern()
作为joe776 suggested的备选方案可能会使用自编写的集合,扩展一些Set
(因为Set
没有Object get(Object)
方法)或另一个HashMap
(具有指向自身的对象),允许您获取对公共对象的引用。
答案 1 :(得分:2)
您可以对值使用String.intern()
,使它们都指向同一个实例。但是这有其他问题,例如使用PermGenSpace,它不是Java 1.7之前的垃圾收集。
您可以这样称呼它:myMap.put(line[0], line[1].intern())
。
也许基于trie的地图效率更高,但我还没有用过它。还取决于你的字符串的性质。你的钥匙越相似,特里可以节省的空间越多。
http://code.google.com/p/trie-map/
另请参阅有关keys().size()
和values().size()
的{{3}}以及使用其他地图以避免重复值。