Java Set接口如何保证不重复
今天面试官问我:Set如何保证不重复?Set是一种抽象数据类型,可以通过多种方式实现。就其本身而言,它是一个合同的规范;因此,它不能保证任何事情。由接口的实现来保证合同的履行 因此,了解这些实现是如何工作的以及为什么工作更有趣。一些常见的实现是:Java Set接口如何保证不重复,java,set,Java,Set,今天面试官问我:Set如何保证不重复?Set是一种抽象数据类型,可以通过多种方式实现。就其本身而言,它是一个合同的规范;因此,它不能保证任何事情。由接口的实现来保证合同的履行 因此,了解这些实现是如何工作的以及为什么工作更有趣。一些常见的实现是: 哈希表,由HashSetJava实现 平衡树,由TreeSetJava实现 位集(用于特殊类型),由EnumSet和BitSet在Java中实现 跳过列表,由ConcurrentSkipListSet实现 朴素数组:在添加元素之前扫描数组;不经常使用
- 哈希表,由
Java实现HashSet
- 平衡树,由
Java实现TreeSet
- 位集(用于特殊类型),由
和EnumSet
在Java中实现BitSet
- 跳过列表,由ConcurrentSkipListSet实现
- 朴素数组:在添加元素之前扫描数组;不经常使用。在Java中实现为
CopyOnWriteArraySet
在工作面试中,你会回答上述问题,并提出解释任何一项实施的细节。面试官应该已经知道其中的一些,除非被问到,否则开始漫无目的地谈论这些内容对你没有好处。集合是一种抽象数据类型,可以通过多种方式实现。就其本身而言,它是一个合同的规范;因此,它不能保证任何事情。由接口的实现来保证合同的履行 因此,了解这些实现是如何工作的以及为什么工作更有趣。一些常见的实现是:
- 哈希表,由
Java实现HashSet
- 平衡树,由
Java实现TreeSet
- 位集(用于特殊类型),由
和EnumSet
在Java中实现BitSet
- 跳过列表,由ConcurrentSkipListSet实现
- 朴素数组:在添加元素之前扫描数组;不经常使用。在Java中实现为
CopyOnWriteArraySet
在工作面试中,你会回答上述问题,并提出解释任何一项实施的细节。面试官应该已经知道其中的一些,除非被问到,否则开始漫无目的地谈论这些内容对你没有好处。从规范的角度来看,它是通过指定如果你尝试添加一个副本,
add
方法必须做什么来实现的。add
方法的文档说明如下,例如:
如果指定的元素尚未存在,则将其添加到此集合
(可选操作)。更正式地说,将指定的元素e添加到
如果集合中不包含元素e2,那么该集合将被设置为(e==null?
e2==null:e.equals(e2))。如果此集合已包含该元素,
该调用保持集合不变,并返回false。结合
由于对构造函数的限制,这确保了
包含重复的元素
从同一页():
构造函数的附加规定是,所有构造函数都必须创建一个不包含重复元素的集合(如上所述)
(为了完整性,也有关于
equals
和hashCode
的规定,确保Set
正确地建模集合抽象。)从规范的角度来看,它通过指定add
方法在尝试添加副本时必须执行的操作来实现。add
方法的文档说明如下,例如:
如果指定的元素尚未存在,则将其添加到此集合
(可选操作)。更正式地说,将指定的元素e添加到
如果集合中不包含元素e2,那么该集合将被设置为(e==null?
e2==null:e.equals(e2))。如果此集合已包含该元素,
该调用保持集合不变,并返回false。结合
由于对构造函数的限制,这确保了
包含重复的元素
从同一页():
构造函数的附加规定是,所有构造函数都必须创建一个不包含重复元素的集合(如上所述)
(为了完整性,还有关于
equals
和hashCode
的规定,确保Set
对集合抽象进行正确建模。)答案在于add
方法的源代码。例如,在TreeSet
的源代码中,add方法实现如下:
public boolean add(E e)
{
return m.put(e, PRESENT)==null;
}
其中,PRESENT
是object
类的对象。而m
是NavigableMap
的对象。此NavigableMap
m
用于将元素e
存储为键
,并将作为其值
呈现给给定键e
。因此,m
中的每个键都有相同的对象PRESENT
。oracle文档中定义的put
映射方法是:
将指定的值与此映射中的指定键相关联。如果映射以前包含键的映射,则替换旧值
…
…
返回:与键关联的上一个值,如果键没有映射,则返回null。(null返回值也可以表示映射以前与null键关联。)
因此,当您将重复元素放入集合中时,该元素将作为键放入NavigableMap
中,并具有值PRESENT
。如果此键不在NavigableMap
中,则put
方法返回null
,因此
m.put(e,PRESENT)=null返回true,我们知道元素被添加了。如果键已存在于NavigableMap
中,则put
方法将覆盖