哈希表存储重复值的方式是什么?

3

Java中的HashMap是否将重复值保存为唯一值,还是单独保存它们?

假设我有以下键值对:

A -> "a very long string...."
B -> "another very long string...."
C -> "the same very long string from A key.... (but not same string instance)"

它会保存为3个键和3个值,还是作为3个键和2个值(因为A的值与C的值完全相同)

我的担忧在于尺寸,因为我要保存的值非常大,并且重复它们没有意义。


你可以考虑使用 StringBuilder 来创建字符串实例并存储它们。这样,你只需要存储引用。 - prasad_
4个回答

3

HashMap可以包含重复的值,因此在您的示例中,Map中将有3个键和3个值。

但是,如果您担心大型实例作为值多次存储在Map中,您应该存储对同一实例的引用。

例如:

String val = "a very long String............";
String val2 = "a second long String.........";
map.put(1,val);
map.put(2,val2);
map.put(3,val);

只有两个大的String实例。该Map包含对这些String的3个引用(对第一个String的两个引用和对第二个String的一个引用),但是引用占用了很少的存储空间。


2
它不会保留值,而是保存对值的引用,所以问题归结为一个问题:““a very long string....”“the same very long string from A key....”在内存中是否是同一个对象?”
如果它们不是编译时常量,并且是在运行时获取/构造的,则它们是不同的对象。字符串池化(String interning)以及与之相关的String#intern方法可以帮助您解决此问题,但其限制由@bratkartoffel提到。 什么是Java字符串池化?
何时应该在字符串字面值上使用String.intern方法?
String.intern()的性能惩罚

1
请勿在非常大的字符串上使用intern()。这将很快导致问题,因为实例保存在单独的空间(永久代,而不是堆)中。该空间有限且旨在用于类、方法和内部JVM内容。 - bratkartoffel

2
但是这并不涉及HashMap,也就是说它不特定于HashMap。将值作为字符串意味着另外两个不同的事情 - 例如字符串内部化或者字符串是不可变的事实。此外,HashMap不会复制值(无论那是什么),它只存储对其他对象的引用 - 如何处理这些对象完全取决于您。如果您在HashMap之外更改了一个对象,然后针对该特定关联键查询该Map,您将看到更新。"最初的回答"

1
Java的HashMap不允许重复的键,但允许重复的值。所以它会将它们保存为3个键和3个值。
为了避免重复保存值,您需要检查它(例如使用.containsValue()方法)。

我想在Map中没有声明contains()方法。 - Gyro Gearless
1
containsKey()containsValue()中选择一个。 - user10762593

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接