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

97 java list distinct-values

如何在Java中创建唯一/不同对象(没有重复)的列表?

现在我正在使用HashMap<String, Integer>这个,因为密钥被覆盖,因此最后我们可以得到HashMap.getKeySet()哪个是唯一的.但我确信应该有更好的方法来实现这一点,因为这里浪费了价值部分.

Fra*_*ank 152

您可以使用Set实现:

来自JAVADoc的一些信息:

包含重复元素的集合.更正式地说,集合不包含元素对e1和e2,使得e1.equals(e2)和至多一个null元素.正如其名称所暗示的,该界面模拟数学集抽象.

注意:如果将可变对象用作set元素,则必须非常小心.如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的​​行为.这种禁令的一个特例是,不允许将一个集合作为一个元素包含在内

这些是实现:

  • HashSet的

    该类为基本操作(添加,删除,包含和大小)提供恒定的时间性能,假设散列函数在桶之间正确地分散元素.迭代此集合需要的时间与HashSet实例的大小(元素数量)加上后备HashMap实例的"容量"(桶数)之和成比例.因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低)非常重要.

    迭代时HashSet,生成元素的顺序是未定义的.

  • LinkedHashSet

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

    那么,上面代码的输出......

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

    ......必将是

    3
    1
    2
    
    Run Code Online (Sandbox Code Playgroud)
  • TreeSet中

    此实现为基本操作(添加,删除和包含)提供了有保证的log(n)时间成本.默认情况下,迭代返回的元素按其" 自然顺序 " 排序,因此上面的代码......

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

    ...将输出:

    1
    2
    3
    
    Run Code Online (Sandbox Code Playgroud)

    (您还可以将Comparator实例传递给TreeSet构造函数,使其按不同顺序对元素进行排序.)

    请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致.(有关与equals一致的精确定义,请参阅Comparable或Comparator.)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的.集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同.

  • 这不是LIST ...因此,并非所有LIST接口方法都可用. (3认同)
  • 选择是你的...HashSet 是通用的和快速的,树集是有序的,LinkedHashset 保持插入顺序...... (2认同)
  • 集合不是列表,我无法在 O(1) 时间内(随机访问)通过集合中的索引查找元素。 (2认同)

Pau*_*lly 9

我想澄清其他人提到的原始海报的一些内容,但没有明确说明.当你说你想要一个唯一列表时,这就是有序集的定义.Set Interface和List接口之间的一些其他关键差异是List允许您指定插入索引.所以,问题是你真正需要的列表界面(即可以兼容第三方库等),或者你可以重新设计你的软件使用Set接口?您还必须考虑使用界面执行的操作.按指数查找元素是否重要?你在集合中有多少元素?如果你有很多元素,订购重要吗?

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

同样,每个集合都有一些优点和缺点.一些快速插入但读取速度慢,一些具有快速读取但插入速度慢等.使用集合文档花费大量时间来充分了解每个类和接口的更精细细节是有意义的.

  • 这并没有提供问题的答案.要批评或要求作者澄清,请在帖子下方留言 - 您可以随时评论自己的帖子,一旦您有足够的[声誉](http://stackoverflow.com/help/whats-reputation),您将能够[评论任何帖子](http://stackoverflow.com/help/privileges/comment). (2认同)
  • 实际上,它确实提供了答案。如果他只是想要一个像 Set 一样的列表,使用 org.apache.commons.collections.list.SetUniqueList,但作为程序员,他/我们应该比这更小心,应该更多地考虑问题。如果这能让我的回答更好,“如何在 Java 中创建唯一列表?” List uniqueList = new SetUniqueList();,就是这样.... (2认同)
  • 还有Zach,我不是想成为一个混蛋,但你在评论之前是否还读过我的答案?或者你只是不明白吗?如果你不理解它,那没关系 - 让我知道,我会扩展这个主题.我认为我不应该写一篇关于数据结构的论文,以便对某人的问题给出友好的答案.当我知道答案并且没有其他人真正提供答案时,我也不会在建立我的评论声誉时采取一些温和的方式. (2认同)
  • 顺便说一句,我既没有批评也没有要求作者澄清,我只是说他可以 A) 快速使用我给他的课程,或者 B) 花时间真正了解这些课程之间的差异并联系他们的需要。B 显然需要更长的时间,但从长远来看会产生更好的代码。 (2认同)

tim*_*m_a 8

使用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);

  }
}
Run Code Online (Sandbox Code Playgroud)

  • 只需添加上述程序 - > 11封信必须发送至:[Aaron,Alice,James,Adel,Jose,Jeremy,Amy,Alan,Patrick,Helen,Alexi] (2认同)

Zap*_*ica 6

我不知道这有多有效,但是在简单的上下文中对我有用。

List<int> uniqueNumbers = new ArrayList<>();

   public void AddNumberToList(int num)
    {
        if(!uniqueNumbers .contains(num)) {
            uniqueNumbers .add(num);
        }
    }
Run Code Online (Sandbox Code Playgroud)