存储在HashMap中的重复值

时间:2013-07-10 15:27:51

标签: java hashmap

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

2 个答案:

答案 0 :(得分:5)

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

A simple example showing this

如果您希望重复项指向相同的对象,则必须在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}}以及使用其他地图以避免重复值。