为什么 HashSet 的内部实现会创建虚拟对象以作为值插入 HashMap 而不是插入空值?
Why the internal implementation of HashSet creates dummy objects to insert as values in HashMap rather than inserting nulls?
HashSet 是使用 HashMap 实现的,当我们向 HashSet 添加任何东西,例如 e1 时,如果集合中不存在 e1,它会在内部添加 (e1,new Object()) 到 HashMap 中。我的问题是为什么他们要插入 new Object(),而他们本可以像 (e1,null) 那样插入,这是更优化的方法,因为没有创建新的对象。在这里插入空值有什么缺点吗?
例如如果您将 HashSet 对象提供给 ConcurrentSkipListSet 构造函数,它不能包含任何空值。
刚看源码看到这段代码
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
如果使用 null
而不是 PRESENT
,这些将不起作用;在每种情况下,都需要一个额外的步骤。
A HashSet
不会在每次将新键 put
添加到地图时添加新的 Object
。它确实使用了 Object
,但每次都使用相同的 Object
。此值在 HashSet
源代码中被命名为 PRESENT
。
add
方法在内部 HashMap
上调用 put(key, PRESENT)
。 remove
方法在内部 HashMap
上调用 remove(key)
,但它必须 return 一个 boolean
指示密钥是否存在。如果 null
被存储为值,那么 HashSet
需要先调用 containsKey
,然后 remove
,以确定密钥是否存在——额外的开销。在这里,只有一个Object
的内存开销,非常小。
HashSet 是使用 HashMap 实现的,当我们向 HashSet 添加任何东西,例如 e1 时,如果集合中不存在 e1,它会在内部添加 (e1,new Object()) 到 HashMap 中。我的问题是为什么他们要插入 new Object(),而他们本可以像 (e1,null) 那样插入,这是更优化的方法,因为没有创建新的对象。在这里插入空值有什么缺点吗?
例如如果您将 HashSet 对象提供给 ConcurrentSkipListSet 构造函数,它不能包含任何空值。
刚看源码看到这段代码
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
如果使用 null
而不是 PRESENT
,这些将不起作用;在每种情况下,都需要一个额外的步骤。
A HashSet
不会在每次将新键 put
添加到地图时添加新的 Object
。它确实使用了 Object
,但每次都使用相同的 Object
。此值在 HashSet
源代码中被命名为 PRESENT
。
add
方法在内部 HashMap
上调用 put(key, PRESENT)
。 remove
方法在内部 HashMap
上调用 remove(key)
,但它必须 return 一个 boolean
指示密钥是否存在。如果 null
被存储为值,那么 HashSet
需要先调用 containsKey
,然后 remove
,以确定密钥是否存在——额外的开销。在这里,只有一个Object
的内存开销,非常小。