Java 的 Set 接口 java.util.Set 表示一组唯一的对象,换句话说,同一个对象在 Set 中不能多次出现。 Set 接口是 java.util.Collection 接口的子类型,即 Set 继承自Collection。
可以将任何 Java 对象添加到 Java Set。如果 Set 没有使用 Java 泛型进行类型化,那么甚至可以在同一个 Set 中混合不同类型的对象,不过通常情况下我们不会这么使用 Set。
这篇文章我们详细地把 Set 在 Java 中的应用梳理一下,文章大纲如下:
Set 和 List 的区别
Set 和 List 接口彼此非常相似。两个接口都表示一个元素的集合。但是,存在一些显著差异。这些差异反映在 Set 和 List 接口包含的方法中。 Set 和 List 接口之间的第一个区别是,相同的元素在 Set 中不能出现多次,List 则是可以有重复元素。Set 和 List 接口之间的第二个区别是,Set 中的元素没有可保证的内部顺序。 List 中的元素具有内部顺序,并且元素可以按该顺序进行迭代。
初识 Set
首先来一个简单示例,让你了解 Set 是怎么工作的:
package com.example.learnset;
import java.util.HashSet;
public class SetExample {
public static void main(String[] args) {
Set setA = new HashSet();
String element = "demo element";
setA.add(element);
System.out.println( setA.contains(element) );
}
}
复制代码
此示例创建一个 HashSet,它是 Java 提供的 Set 接口实现类,紧接着向 Set 中添加一个字符串对象,最后检查 Set 是否包含刚刚添加的元素。
Java 提供的Set实现类
作为 Collection 的子类型,Collection 接口中的所有方法在 Set 接口中也包含。 由于 Set 是一个接口,需要实例化该接口的具体实现才能使用。不过 Java 的集合框架中的已经提供了一些非常优秀的实现,我们可以在以下 Set 实现中进行选择使用:
- java.util.HashSet
- java.util.LinkedHashSet
- java.util.TreeSet
- java.util.EnumSet
这些 Set 实现中的每一个在迭代 Set 时的元素顺序以及插入和访问 Set 中的元素的时间复杂度都略有不同。
HashSet 底层由 HashMap 实现。当对 HashSet 进行迭代时,它不保证元素的顺序。
LinkedHashSet 与 HashSet 的不同之处在于,它保证了迭代期间元素的顺序与它们插入 LinkedHashSet 的顺序相同。重新插入一个已经在 LinkedHashSet 中的元素不会改变这个顺序。
TreeSet 也保证了迭代时元素的顺序,但元素的排序顺序由它们的自然顺序(如果元素实现了Comparable接口)或由特定的 Comparator 实现确定。
创建 Set 实例
以下是如何创建 Set 实例的几个示例:
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetExample {
public static void main(String[] args) {
Set setA = new HashSet();
Set setB = new LinkedHashSet();
Set setC = new TreeSet();
}
}
复制代码
默认情况下,可以将任何对象放入 Set,但是从 Java 5 开始,Java 引入泛型后让限制可插入到 Set 中的对象