Java Set接口的用法(附带实例)
java.util 包中提供了一些集合类,这些集合类又被称为容器。提到容器不难想到数组。集合类与数组的不同之处是:
常用的集合有 List 集合、Set 集合和 Map 集合,其中 List 集合与 Set 集合继承了 Collection 接口,各接口还提供了不同的实现类。上述集合类的继承关系如下图所示。

图 1 常用集合类的继承关系
Set 集合通常不能记住元素的添加顺序,集合中的元素不按特定的方式进行排序,只是简单地把元素添加到集合中,且 Set 集合中不能包含重复的元素。
Set 集合由 Set 接口和 Set 接口的实现类组成。Set 接口继承了 Collection 接口,因此它包含了 Collection 接口中的所有方法。Set 接口常用的实现类有 HashSet 类与 TreeSet 类,下面分别对其进行讲解。
Set 集合的构造有一个约束条件,传入的 Collection 对象不能有重复值,必须小心操作可变对象(mutable object)。如果一个 Set 集合中的可变元素改变了自身状态而导致 Object.equals(Object) =true,则会出现一些问题。
使用 Set 接口时通常被声明为 Set 类型,通过 HashSet 类可以实例化 Set 接口。代码如下:
【实例】使用 HashSet 类实例化 Set 接口,向集合中添加“Java基本教程”、“Python基础教程”、“C语言入门教程”、“C++基础教程”,使用 foreach 循环遍历集合中的元素,并把它们输出到控制台上。代码如下:
TreeSet 类新增的方法如下表所示:
【实例】使用 TreeSet 类实现自然(升序)排序。在项目中创建 TreeSetTest 类,首先使用 TreeSet 类创建一个 Set 集合对象,然后使用 add() 方法向 Set 集合中添加 5 个元素,即 -5、-7、10、6 和 3,最后使用 Iterator 迭代器遍历并输出 Set 集合中的元素。实例代码如下:
分享一个小技巧,headSet()、subSet()、tailSet() 方法截取对象生成新集合时是否包含指定的参数,可通过如下方法来判别:
- 数组的长度是固定的,集合的长度是可变的;
- 数组用来存储基本类型的数据,集合用来存储对象的引用。
常用的集合有 List 集合、Set 集合和 Map 集合,其中 List 集合与 Set 集合继承了 Collection 接口,各接口还提供了不同的实现类。上述集合类的继承关系如下图所示。

图 1 常用集合类的继承关系
Set 集合通常不能记住元素的添加顺序,集合中的元素不按特定的方式进行排序,只是简单地把元素添加到集合中,且 Set 集合中不能包含重复的元素。
Set 集合由 Set 接口和 Set 接口的实现类组成。Set 接口继承了 Collection 接口,因此它包含了 Collection 接口中的所有方法。Set 接口常用的实现类有 HashSet 类与 TreeSet 类,下面分别对其进行讲解。
Set 集合的构造有一个约束条件,传入的 Collection 对象不能有重复值,必须小心操作可变对象(mutable object)。如果一个 Set 集合中的可变元素改变了自身状态而导致 Object.equals(Object) =true,则会出现一些问题。
Java HashSet类
HashSet 类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 Set 集合的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用 null 元素。使用 Set 接口时通常被声明为 Set 类型,通过 HashSet 类可以实例化 Set 接口。代码如下:
Set<E> set = new HashSet<>();
【实例】使用 HashSet 类实例化 Set 接口,向集合中添加“Java基本教程”、“Python基础教程”、“C语言入门教程”、“C++基础教程”,使用 foreach 循环遍历集合中的元素,并把它们输出到控制台上。代码如下:
import java.util.HashSet; import java.util.Set; public class IteratorTest { public static void main(String[] args) { Set<String> set = new HashSet<String>(); // 定义一个 Set 集合 String str1 = new String("Java基本教程"); String str2 = new String("Python基础教程"); String str3 = new String("C语言入门教程"); String str4 = new String("C++基础教程"); set.add(str1); // 将 str1 存储到 Set 集合中 set.add(str2); // 将 str2 存储到 Set 集合中 set.add(str3); // 将 str3 存储到 Set 集合中 set.add(str4); // 将 str4 存储到 Set 集合中 System.out.println("编程入门系列的教程有:"); for (String string : set) { String value = string; System.out.println(value); } } }运行结果如下:
编程入门系列的教程有: Java基本教程 Python基础教程 C++基础教程 C语言入门教程
Java TreeSet类
通过 TreeSet 类可以实例化 Set 接口。代码如下:Set<E> set = new TreeSet<>();TreeSet 类不仅实现了 Set 接口,还实现了 java.util.SortedSet 接口,因此在遍历集合时,TreeSet 类实现的 Set 集合可以按照自然顺序进行递增排序,也可以按照指定比较器进行递增排序,即可以通过比较器对用 TreeSet 类实现的 Set 集合中的对象进行排序。
TreeSet 类新增的方法如下表所示:
方法 | 功能描述 |
---|---|
first() | 返回此 Set 集合中当前第一个(最低)元素 |
last() | 返回此 Set 集合中当前最后一个(最高)元素 |
comparator() | 返回对此 Set 集合中的元素进行排序的比较器。如果此 Set 集合使用自然顺序,则返回 null |
headSet(E toElement) | 返回一个新的 Set 集合,这个新集合包含 toElement 对象(不包含)之前的所有对象 |
subSet(E fromElement, E fromElement) | 返回一个新的 Set 集合,这个新集合包含 fromElement 对象(包含)与 fromElement 对象(不包含)之间的所有对象 |
tailSet(E fromElement) | 返回一个新的 Set 集合,这个新集合包含 fromElement 对象(包含)之后的所有对象 |
【实例】使用 TreeSet 类实现自然(升序)排序。在项目中创建 TreeSetTest 类,首先使用 TreeSet 类创建一个 Set 集合对象,然后使用 add() 方法向 Set 集合中添加 5 个元素,即 -5、-7、10、6 和 3,最后使用 Iterator 迭代器遍历并输出 Set 集合中的元素。实例代码如下:
import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class TreeSetTest { // 创建 TreeSetTest 类 public static void main(String[] args) { Set<Integer> set = new TreeSet<>(); // 使用 TreeSet 类创建 Set 集合对象 set.add(-5); // 以下几行代码负责向 Set 集合中添加元素 set.add(-7); set.add(10); set.add(6); set.add(3); Iterator<Integer> it = set.iterator(); // 创建 Iterator 迭代器对象 System.out.print("Set 集合中的元素:"); while (it.hasNext()) { // 遍历并输出 Set 集合中的元素 System.out.print(it.next() + " "); } } }运行结果为:
Set 集合中的元素:-7 -5 3 6 10
分享一个小技巧,headSet()、subSet()、tailSet() 方法截取对象生成新集合时是否包含指定的参数,可通过如下方法来判别:
- 如果指定参数位于新集合的起始位置处,则包含该对象,如 subSet() 方法的第一个参数和 tailSet() 方法的参数;
- 如果指定参数是新集合的终止位置处,则不包含该参数,如 headSet() 方法的入口参数和 subSet() 方法的第二个入口参数。