1

我有一个字典作为从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();
}
4

2 回答 2

5

无论重复项是否指向相同的对象,仍然需要对这些对象的引用,因此size仍应返回包含重复项的大小。

一个简单的例子来说明这一点

如果您希望重复项指向相同的对象,则必须在外部执行此操作,HashMap或者希望优化器处理它。

joe776 建议String.intern()的替代方案可能是使用自写的集合扩展一些(因为没有方法)或另一个(让对象指向自己),允许您获取对公共对象的引用。SetSetObject get(Object)HashMap

于 2013-07-10T15:39:21.110 回答
2

您可以使用String.intern()这些值使它们都指向同一个实例。但这还有其他问题,例如使用 PermGenSpace,它不是 Java 1.7 之前的垃圾收集器。你会这样称呼它:myMap.put(line[0], line[1].intern()).

也许基于trie的地图更有效,但我还没有使用过。还取决于您的字符串的性质。您的密钥越相似,trie 可以节省的空间就越多。

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

另请参阅杜克林关于keys().size()values().size()使用另一张地图以避免重复值的回答。

于 2013-07-10T15:35:08.337 回答