以自然顺序存储集合中的唯一元素

在我解决Java测试时,我提出了以下问题:

您需要在集合中存储元素,以确保不存储重复项,并且可以按自然顺序访问所有元素。 哪个接口提供该function?

A. java.util.Map B. java.util.Set C. java.util.List D. java.util.Collection 

我不知道这里的正确案例是什么? 我们可以在任何这些集合中存储相同的元素,除非在Set ,但Set不提供自然顺序。 怎么了?

该测试的正确答案是Set Let记住它要求的接口可以提供该测试; 给定正确的实现Set接口可以提供它。

  • Map接口不会保证存储事物的顺序,因为它是特定于实现的。 但是,如果您使用正确的实现(即,由文档拼写的TreeMap ),那么您将保证自然顺序并且没有重复条目。

    但是,没有关键值对的要求。

  • Set接口也不保证存储的内容是什么,因为它是特定于实现的。 但是,与TreeMap一样, TreeSet是一个可用于以自然顺序存储事物而没有重复的集合。

    这是它的样子。

     Set values = new TreeSet<>(); 
  • List接口肯定会允许重复,立即排除它。

  • Collection接口没有任何直接实现它的东西,但它是整个集合层次结构的族长。 所以,从理论上讲,这样的代码是合法的:

     Collection values = new TreeSet<>(); 

    …但是你失去了关于它实际上是什么类型的收集的信息,所以我不鼓励它的用法。

TreeSet会给你排序(默认情况下自然排序通过比较器自定义排序)。

更一般地, SortedSet是提供唯一性和排序的更通用的接口。

一个集合,进一步提供其元素的总排序。 元素按照其自然顺序排序,或者通过在排序集创建时通常提供的比较器排序。 set的迭代器将按升序元素顺序遍历集合。 提供了几个额外的操作以利用订购。

如果按自然顺序表示插入顺序,则LinkedHashSet是您转到Set实现。

正确答案是: SortedSet提供关于元素的自然顺序的保证。 TreeSet是典型的实现

严格地说,从上面的List选择时,只有具有已定义迭代次序的接口,但它确实允许重复。

另一方面SetMap ,不允许重复( Map的键),但它们也没有定义迭代的顺序,默认情况下它们是无序的, HashSet / HashMap是反例。

Collection不允许。

因此,严格来说 – 建议的接口都没有提供所需的function。但是,正如其他人所建议的那样,接口的特定实现允许元素的自然顺序而没有重复,主要是SortedSet接口及其TreeSet实现


为了进一步说明为什么Set不是一个好选项,如果你有一个变量,让它成为mySet ,你想要它被订购,当你使用Set接口时,用户会感到惊讶,想象下面的代码:

 public int processMyDataStructure(Set set) { //some calculation that assumes set is ordered return result; } 

并且用户为您提供了一个HashSet作为参数 – 您将从您的方法中获得错误的行为,因为Set不保证排序。 为了避免它,你应该要求SortedSet而不是Set

我昨天在面试时遇到了这个问题,需要对此发表评论:问题(假设所列出的A,B,C或D答案之一必须正确)显然是错误的。 没有列出正确的答案。

Set接口中没有任何内容保证返回元素的顺序。 并且没有像Makoto在他接受的答案中所希望的那样, 正确的实现理论上可以完成这项工作,因为我们不会在这里要求任何实现,而是接口是否提供所请求的function。

因此,提供答案的测试问题是错误的。

再多说一下接受的答案 ,还有一个原因是错误的。 具体来说, Makoto认为, List接口肯定会允许重复,立即排除它。 这个论点可能会被List规范中的引用说明:

有人可能希望通过在用户尝试插入时抛出运行时exception来实现禁止重复的列表,但我们希望这种用法很少见,这是不可想象的。

所以在我看来,给出的任何答案都是同样错误的,或者,正如公认的答案所希望的那样,同样正确,因为我们可以自由地编写以我们希望的任何方式行事的List(或Map,或Collection)的实现(在边界内)由接口规范设置),但接口和它们的规范在这里保证一些合同,这个问题实际上是关于它们的,而不是关于可能的实现。