Set和List有何不同?

511
Set<E>List<E> 接口之间的根本区别是什么?

1
请参见https://dev59.com/H3RA5IYBdhLWcg3w9ivq。 - Michael Myers
5
如果您想了解性能方面的信息,请查看此问题:https://dev59.com/K2gv5IYBdhLWcg3wKtvj - vsingh
26个回答

571

List是一个有序元素的序列,而Set是一个无序的不重复元素列表(感谢Quinn Taylor)。

List<E>:

有序集合,用户可以精确控制每个元素在列表中的插入位置。用户可以通过它们在列表中的整数索引(位置)访问元素,并搜索列表中的元素。

Set<E>:

不包含重复元素的集合。更正式地说,集合不包含任何一对元素e1和e2使得e1.equals(e2),并且最多只有一个空元素。顾名思义,该接口模拟了数学集合抽象。


8
在SortedSet中,如果compareTo() == 0,则没有两个元素被视为相等,因为不会调用equals方法。 - Peter Lawrey
39
集合(Set)可以被排序,因此这个答案的第一个陈述是有误导性的,即使当然必须选择列表(List)来强制集合顺序。 - Samuel EUSTACHI
30
错误!Java中的set可以被排序,具体取决于实现方式;例如,Java中的TreeSet是有序的。在Java的语境下,List和Set之间唯一的区别是Set包含唯一的项。而在数学的语境下,集合的项是唯一且无序的。 - stackoverflowuser2010
54
是的,Java中的Set可以是无序的,但不一定是有序的。如果你有一个TreeSet,那么你可以确信它是有序的。但是你必须知道你有一个TreeSet而不仅仅是一个Set。如果返回的是一个Set,你不能依赖于它的顺序。另一方面,List天生就是有序的,任何实现List的类都必须是有序的。因此,从接口定义来看,说Set是无序的并没有特别错误,但也许更准确的说法是Set不能保证元素的顺序。 - Spanky Quigman
18
不要混淆“有序”和“排序”。同样,不要混淆接口的契约和接口的实现。说某些东西是“无序”的也是错误的,它只是意味着没有关于排序实现的保证(并且排序可能在调用之间不稳定,不像有序列表)。 - lilbyrdie
显示剩余5条评论

289
列表 集合
重复元素
顺序 有序 取决于实现方式
位置访问

4
需要注意的一点是:位置访问性能在底层实现上有很大的差别,数组与链表 https://dev59.com/Y3RC5IYBdhLWcg3wW_tk - Christophe Roussy
2
如果不是通过位置访问,集合如何进行索引?(ASCII表加1) - tplive
我不喜欢阅读。这使得它非常简洁和简单。 - Rishav

84

元素的有序列表(唯一或非唯一)
符合Java命名为List的接口
可以通过索引进行访问

使用以下方式实现

  • LinkedList
  • ArrayList

唯一元素的列表:
符合Java命名为Set的接口
无法通过索引进行访问

使用以下方式实现

  • HashSet(无序)
  • LinkedHashSet(有序)
  • TreeSet(按自然顺序或提供的比较器排序)

这两个接口SetList都符合Java命名为Collection的接口


35

一个Set不能包含重复元素,而List可以。在Java中,List还意味着有序。


19
  • 列表(List)是一组有序的物品
  • 集合(Set)是一组无序的物品,通常不允许重复项

在概念上,我们通常将允许重复的无序分组称为Bag,不允许重复的则称为Set。


2
一个集合不能有重复。 - karim79
一些集合实现是有序的(例如LinkedHashSet,它在后台维护一个LinkedList)。但Set ADT没有顺序。 - Michael Myers

13

列表:

列表一般允许重复的对象。 列表必须按顺序排列,因此可以通过索引进行访问。

实现类包括:ArrayListLinkedListVector

集合:

集合不允许有重复的对象。 大多数实现是无序的,但具体取决于实现。

实现类包括: HashSet(无序), LinkedHashSet(按添加顺序排序), TreeSet(按自然顺序或提供的比较器排序)


12

列表

  1. 是一个有序的元素组合。
  2. 列表用于包含有重复元素的集合。
  3. 在 List 接口中定义了新的方法。

集合

  1. 是一个无序的元素组合。
  2. 集合用于包含无重复元素的集合。
  3. 在 Set 接口中没有定义新的方法,因此我们必须仅使用 Collection 接口方法与 Set 的子类一起使用。

9

列表:
列表允许重复元素和空值。可以使用元素的相应索引轻松搜索,并按照插入顺序显示元素。 示例:(链表)

import java.util.*;

public class ListExample {

 public static void main(String[] args) {
    // TODO Auto-generated method stub

    List<Integer> l=new LinkedList<Integer>();
    l.add(001);
    l.add(555);
    l.add(333);
    l.add(888);
    l.add(555);
    l.add(null);
    l.add(null);

    Iterator<Integer> il=l.iterator();

    System.out.println(l.get(0));

    while(il.hasNext()){
        System.out.println(il.next());
    }

    for(Integer str : l){
        System.out.println("Value:"+str);
    }
 }

}

输出:

1
1
555
333
888
555
null
null
值: 1
值: 555
值: 333
值: 888
值: 555
值: null
值: null

集合:
集合不允许有重复的元素,但是允许单个空值。它不会维护任何顺序来显示元素。只有TreeSet会按升序显示。

示例:(TreeSet)

import java.util.TreeSet;

public class SetExample {

 public static void main(String[] args) {
    // TODO Auto-generated method stub

    TreeSet<String> set = new TreeSet<String>();
    try {
        set.add("hello");
        set.add("world");
        set.add("welcome");
        set.add("all");

        for (String num : set) {
            System.out.println( num);

        }
        set.add(null);
    } catch (NullPointerException e) {
        System.out.println(e);
        System.out.println("Set doesn't allow null value and duplicate value");
    }

 }

}

输出:

all
hello
welcome
world
java.lang.NullPointerException
集合不允许空值和重复值


这是最详细的内容。 - Omar Essam El-Din
设置允许空值,但是由于它无法存储重复的空值,因此有些人可能会对您在代码示例中的注释感到困惑。 - Gaj Julije

8

ListSet都是接口,它们都继承自Collection接口。Set和List之间的重要区别有:

  1. 重复对象

ListSet之间的主要区别是,List允许有重复元素,而Set不允许有重复元素。

  1. 顺序

List是一个有序的集合,它保持插入顺序,这意味着在显示列表内容时,它将按照元素插入列表的顺序显示元素。

Set是一个无序的集合,它不保持任何顺序。有一些Set实现可以保持顺序,例如LinkedHashSet(它按照插入顺序维护元素)。

  1. 空元素

List允许任意数量的空元素Set最多只能有一个空元素


1
欢迎来到Stack Overflow!请注意,您正在回答一个非常古老且已经有答案的问题。以下是如何回答问题的指南 - help-info.de
1
很好地总结了信息。太棒了! - fatimasajjad

8

既然我们正在谈论Java接口,为什么不看一下Javadoc呢?!

  • List是一个有序的集合(序列),通常允许重复元素
  • Set是一个不包含重复元素的集合,迭代顺序可以由实现保证

关于集合是否有序,Sets没有提到缺乏任何信息:这取决于具体实现。


2
正确。LinkedHashSet 按插入顺序包含元素。 - ggb667
这是一个接口,一切都取决于实现。在某些实现中,List.get() 可能会创建一个包含前 5 位小数的文件,并抛出 StackOverFlowException,但这并不意味着你可以说“列表是可以创建文件的东西”,因为这不是接口定义的一部分。文档声称 Set 是基于数学概念中的集合模型设计的,而根据定义,集合是无序的。如果在代码中使用了一个集合,你不能假设它是有序的,否则就违反了 SOLID 原则。 - sara
@kai,如果代码后续需要排序,我通常会将LinkedHashSet放在左侧。如果我真的像使用Set一样使用它,那么我只会使用Set,因为你不能假设底层实现是LinkedHashSet或类似的,今天可能是这样,但明天代码改变了就会失败。 - Christophe Roussy
如果您声明了一个LinkedHashSet,那么您并不是在处理一个Set,因此对于Set应该如何行为做出的任何声明都几乎没有意义。我会说,基于某些实现将有序性归因于集合类似于说“Runnable实例具有在某个线程上运行的run方法。此外,根据实现,它们会打开DB连接并读取客户数据。”当然,某些实现可能会这样做,但这并不是Runnable接口所暗示的含义。 - sara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接