如何维护Java中的唯一列表?

如何在Java中创build唯一列表

现在我正在使用HashMap<String, Integer>来完成这个操作,因为关键字被覆盖了,所以最后我们可以得到HashMap.getKeySet() ,这将是唯一的。 但是我相信应该有更好的办法来做到这一点,因为这里浪费了价值部分。

你可以使用Set实现:

来自JAVADoc的一些信息:

包含重复元素的集合 。 更正式地,集合不包含e1和e2这样的元素,使得e1.equals(e2)和至多一个null元素。 正如其名称所暗示的,这个接口模拟了math集抽象。

注意:如果使用可变对象作为集合元素,必须非常小心。 如果对象的值以影响等于比较的方式更改,而对象是集合中的元素,则不会指定集合的​​行为。 这种禁止的一个特例就是不允许一套把自己作为一个要素

这些是实现:

  • HashSet的

    这个类为基本操作(添加,删除,包含和大小)提供了恒定的时间性能,假设散列函数在桶之间正确地分散元素。 遍历这个集合需要的时间与HashSet实例的大小(元素数量)加上支持HashMap实例的“容量”(桶的数量)的总和成正比。 因此,如果迭代性能很重要,不要将初始容量设置得太高(或者负载因子太低)。

    当迭代一个HashSet ,元素的顺序是未定义的。

  • LinkedHashSet

    Set接口的哈希表和链表实现,具有可预测的迭代顺序。 这个实现与HashSet的不同之处在于,它维护一个双向链表,并在其所有条目中运行。 这个链表定义了迭代sorting,这是元素插入到集合(插入顺序)的顺序。 请注意,如果将元素重新插入到集合中,则插入顺序不受影响。 (如果s.contains(e)在调用之前立即返回true,则调用s.add(e)时,将元素e重新插入到集合s中。

    所以,上面的代码的输出…

      Set<Integer> linkedHashSet = new LinkedHashSet<>(); linkedHashSet.add(3); linkedHashSet.add(1); linkedHashSet.add(2); for (int i : linkedHashSet) { System.out.println(i); } 

    …一定会的

     3 1 2 
  • TreeSet中

    这个实现为基本操作(添加,移除和包含)提供了保证的log(n)时间成本。 默认情况下,迭代返回的元素按“ 自然顺序 ”进行sorting ,所以上面的代码…

      Set<Integer> treeSet = new TreeSet<>(); treeSet.add(3); treeSet.add(1); treeSet.add(2); for (int i : treeSet) { System.out.println(i); } 

    …会输出这个:

     1 2 3 

    (您也可以将Comparator实例传递给TreeSet构造函数,使其按照不同的顺序对元素进行sorting。)

    请注意,如果要正确实现Set接口,则由集合(不论是否提供显式比较器)维护的sorting必须与equals保持一致。 (请参阅Comparable或Comparator以获得与equals一致的精确定义)。这是因为Set接口是根据equals操作定义的,但TreeSet实例使用其compareTo(或compare)方法执行所有元素比较,因此两个从这个方法看,被这个方法认为是相等的元素是相等的。 即使sorting与等号不一致,集合的行为也是明确的。 它只是不服从Set接口的总体合同。

使用new HashSet<String>一个例子:

 import java.util.HashSet; import java.util.Set; public class MainClass { public static void main(String args[]) { String[] name1 = { "Amy", "Jose", "Jeremy", "Alice", "Patrick" }; String[] name2 = { "Alan", "Amy", "Jeremy", "Helen", "Alexi" }; String[] name3 = { "Adel", "Aaron", "Amy", "James", "Alice" }; Set<String> letter = new HashSet<String>(); for (int i = 0; i < name1.length; i++) letter.add(name1[i]); for (int j = 0; j < name2.length; j++) letter.add(name2[j]); for (int k = 0; k < name3.length; k++) letter.add(name3[k]); System.out.println(letter.size() + " letters must be sent to: " + letter); } } 

我想在这里澄清一些其他人提到的原始海报,但没有明确说明的东西。 当你说你想要一个唯一的列表,这是一个有序集的定义。 Set Interface和List接口之间的一些其他关键区别在于,List允许您指定插入索引。 所以问题是你真的需要列表界面(即与第三方库的兼容性等),还是可以重新devise你的软件来使用Set界面? 你也必须考虑你正在做的接口。 按索引查找元素是否重要? 你期望有多less元素? 如果你要有很多元素,是否重要?

如果你真的需要一个只有一个唯一约束的List,那么Apache Common Utils类org.apache.commons.collections.list.SetUniqueList将为你提供List接口和唯一约束。 请注意,这会打破List界面。 但是,如果您需要按索引查找列表,您将会获得更好的性能。 如果你可以处理Set接口,并且你有一个较小的数据集,那么LinkedHashSet可能是一个好的方法。 这只取决于软件的devise和意图。

同样,每个系列都有一定的优点和缺点。 一些快速插入,但读取速度慢,一些读取速度快,但插入速度慢等等。在集合文档中花费相当多的时间来充分了解每个类和接口的细节。

您可以使用HashSet<String>来维护唯一对象的集合。 如果地图中的Integer数值很重要,则可以使用containsKey方法来testing您的密钥是否已经在地图中。

HashSet<String> (或)任何Set实现可能为你做这项工作。 Set不允许重复。

这里是HashSet的javadoc 。

您可能希望使用java.util.Set<E>接口的实现类之一,例如java.util.HashSet<String>集合类。

不包含重复元素的集合。 更正式地,集合不包含e1和e2这样的元素,使得e1.equals(e2)和至多一个null元素。 正如其名称所暗示的,这个接口模拟了math集抽象。

HashSet不是大尺寸数组的最佳解决scheme。 你可以看看这里(仅供参考): https : //www.hackerrank.com/challenges/java-dequeue

如果Set使用这个问题给出一个超时,如果Map使用它将变得相当快(cuz ContainsKey函数的Map是足够快的)

所以,我会build议手动创build唯一值容器与地图(HashMap)