Set接口如何保证不重复

时间:2013-07-02 18:03:26

标签: java set

今天面试官问我:Set如何保证不重复?

3 个答案:

答案 0 :(得分:2)

答案在于add方法的源代码。例如,在TreeSet的源代码中,add方法实现如下:

public boolean add(E e) 
{
    return m.put(e, PRESENT)==null;
}

其中,PRESENTObject类的对象。而mNavigableMap的对象。此NavigableMap m用于将e元素keyPRESENT作为value存储到给定键e 。因此m中的每个键都具有相同的对象PRESENT。 oracle doc中定义的put Map方法是:

  

将指定的值与此映射中的指定键相关联。如果映射先前包含键的映射,则替换旧值。
  ...
  ...
  返回:与键关联的上一个值,如果没有键的映射,则返回 null。 (null返回也可以指示映射先前将null与key关联。)

因此,当您将重复元素置于集合中时,此元素将作为值NavigableMap放入PRESENT作为键。如果NavigableMap中没有此密钥,则put方法返回null,因此 m.put(e,PRESENT)==null返回true,我们知道元素已添加。如果密钥已在NavigableMap中出现,则put方法会使用PRESENT覆盖value key内的e,并返回旧值(即PRESENT)因此 NavigableMap返回m.put(e,PRESENT)==null,我们知道该元素未添加。

答案 1 :(得分:1)

Set是一种抽象数据类型,可以通过多种方式实现。它本身就是合同的规范;因此它不保证任何东西。这取决于接口的实现,以保证合同得到履行。

因此,了解实现的工作方式和原因会更有趣。一些常见的实现是:

  • 哈希表,由HashSet
  • 在Java中实现
  • 平衡树,由TreeSet
  • 在Java中实现
  • 位集(针对特殊类型),由EnumSetBitSet
  • 在Java中实现
  • 跳过列表,由ConcurrentSkipListSet
  • 实施
  • 天真数组:在添加数据之前扫描数组中的元素;不经常使用。在Java中实现为CopyOnWriteArraySet

在求职面试中,你会回复上述内容并提出解释任何一项实施的细节。面试官应该已经知道其中的一些,除非被问到,否则开始对他们进行漫无操作对你不利。

答案 2 :(得分:1)

从规范的角度来看,它通过例如如果您尝试添加重复项,请指定add方法必须执行的操作。 add方法的文档说明了这一点,例如:

  

如果指定的元素尚不存在,则将其添加到此集合中   (可选操作)。更正式地,将指定的元素e添加到   如果集合中不包含元素e2(e == null?   e2 == null:e.equals(e2))。如果此集已包含元素,   调用使集合保持不变并返回false。结合   对构造函数的限制,这确保了永远不会   包含重复的元素。

来自同一页面(http://docs.oracle.com/javase/6/docs/api/java/util/Set.html):

  

对于构造函数的额外规定,毫不奇怪,所有构造函数都必须创建一个不包含重复元素的集合(如上所定义)。

(为了完整起见,还有关于equalshashCode的规定,以确保Set正确地模拟集合抽象。)