Java 哈希集实现中的Null对象
在Java API中,HashSet的实现使用对象作为内部HashMap的值Java 哈希集实现中的Null对象,java,hashset,Java,Hashset,在Java API中,HashSet的实现使用对象作为内部HashMap的值 // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); public boolean add(E e) { return map.put(e, PRESENT)==null; } 但是HashMap允许其值为null。我认为这不是填
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
但是HashMap允许其值为null。我认为这不是填充值的必要条件,那么为什么需要这样做呢
但是HashMap允许其值为null
当值完全由HashSet
控制时,这又有什么关系呢?这确保了与键关联的唯一值是PRESENT
。因此,如果map.put
返回null
,那可能只是因为以前没有该键的条目
该值之所以存在,是因为必须指定一些值,如果该值被指定为null
,那将是不好的-这将使在调用add
之前很难判断是否存在值。如果您要指定任何非null值,那么不妨强制它始终为相同的值——例如,您不希望它停止垃圾收集
现在,如果你问为什么
HashSet
是按照HashMap
实现的,而不是一个更高效的实现,根本不记录值,那是另一个问题,我没有答案。因为HashSet
契约指定remove()
如果指定的对象存在并已删除,则返回true
。为此,它使用包装的HashMap#remove()
,返回删除的值
如果要存储
null
而不是对象,那么对HashMap#remove()
的调用将返回null
,这与尝试删除不存在的对象的结果无法区分,并且无法实现HashSet.remove()
的约定,从对象到null的映射与映射中根本不存在的对象不同。考虑:
Object exists = new Object();
map.put(exists, null);
System.out.println(map.contains(exists)) // "true"
System.out.println(map.get(exists)) // "null"
Object notMapped = new Object();
System.out.println(map.contains(notMapped)) // "false"
System.out.println(map.get(notMapped)) // "null"
另外,HashMap.put()返回带有您放置的键的旧值,在您的情况下,该值为null(可能是因为该键不在映射中,或者它的值为null)。请注意,
==null
部分………..带有映射,如果调用put(key,null)
,则无法区分
密钥已存在,映射到null
没有该键的映射
由于HashSet
的add
委托给HashMap.put
,因此需要PRESENT
来履行Set.add
的契约,如果集中已经存在对象,则返回false
:
return map.put(e, PRESENT)==null;
我想补充一点:
同样,HashSet add()方法的工作原理如下:
公共布尔加法(E)
{
假设,如果PRESENT==null,那么当我们第一次在HashMap中添加项时,它返回null值
对象存在=新对象()
HashSet将返回->null==null->>true
第二次在hashMap中添加值为Null的相同键时
map.put(exists,null);
返回null==null->>true
它将允许hashSet中的重复项,这就是JDK开发人员编写当前对象的原因
嗯,现在我想起来了,我也想知道为什么HashSet
是用HashMap
实现的……我本以为会有更好的方法来实现它。我的理解是,他们想改变它……但从来没有考虑过。不过,公平地说,如果你只是从条目和kep中删除value字段如果不是实现的其余部分不变,那么出于对齐的原因,您实际上不会节省任何速度或内存。您需要一个明显不同的实现来开始真正击败HashMap包装器实现,我想他们从来没有做到过。对齐参数对x86和x64(有压缩和没有压缩)都适用吗哎呀?如果是的话,我想这就可以解释了……不过感觉还是很奇怪。
V value= map.put(exists,null);
value will be null here
map.put(exists,null);