- 土耳其欧鲁旦尼斯
无论你是喜欢浮潜、深潜、游泳、滑翔,还是仅仅喜欢晒太阳,土耳其绿松石海岸的欧鲁旦尼斯,都能满足你的要求。这个村庄及村内的海滩度假村均因紧邻着海滩的蓝色潟湖而得名。“欧鲁旦尼斯”一词直译应该是“死海”,突出其海水的平静,但为了吸引人们的目光,最终的译名选择了突出其蓝色。欧鲁旦尼斯的大部分地区在一个国家公园范围内,这里的海滩拥有高质量的环境和生态,是环境教育基金会认可的蓝旗海滩。
▚ 01 Set概述
- 在本质上,Set是一种不允许包含重复元素的集和类型;也即每个元素在Set中仅能存在一次。Set模拟了数学中的抽象集和。
1.1 Set集合的特征
- 在Java Collections框架中,Set集合与其他集合的区别如下:
- 不允许重复元素。
- 元素不是按顺序存储的。这意味着在迭代Set的元素时,不能期望元素以任何顺序排序。
1.2 为什么&何时使用Set?
- 根据特征,在以下情况下考虑使用Set集合:
- 希望清楚地存储元素,而不需要重复或唯一的元素。
- 不关心元素的顺序。
▚ 02 Set实现
- Java集合框架提供了Set接口的三种主要实现:HashSet、LinkedHashSet和TreeSet。Set API的描述如下图所示:
▚ 03 创建Set
👒注意:使用接口类型(Set)作为引用类型,以具体实现 (HashSet, LinkedHashSet, TreeSet等) 作为实际的对象类型:
3.1 使用泛型来声明一组特定类型Set
- Interger
Set<Integer> numbers = new HashSet<>();
- String
Set<String> numbers = new HashSet<>();
3.2 使用存在的集和创建Set
- 利用
List
变量num_list,来初始化Set变量num_set:
import java.io.IOException;
import java.util.Set;
import java.util.Arrays;
import java.util.List;
import java.util.HashSet;
public class set_list {
public static void main(String[] args) throws IOException {
List<Integer> num_list = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
Set<Integer> num_set = new HashSet<>(num_list);
System.out.println("num_list: " + num_list);
System.out.println("num_set: " + num_set);
}
}
- 输出:
num_list: [1, 2, 2, 3, 3, 4, 5]
num_set: [1, 2, 3, 4, 5]
- 利用
Stream API
来初始化Set变量num_set:
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Collectors;
public class set_stream {
public static void main(String[] args) throws IOException {
Set<Integer> num_set = new HashSet<>();
num_set.add(1);
num_set.add(2);
num_set.add(3);
num_set.add(4);
num_set.add(5);
num_set.add(6);
System.out.println("Before: " + num_set);
//输出num_set中大于3的元素集,并赋值给变量res
Set<Integer> res = num_set.stream().filter(e -> (e > 3)).collect(Collectors.toSet());
System.out.println("After: " + res);
}
}
- 输出:
Before: [1, 2, 3, 4, 5, 6]
After: [4, 5, 6]
📢关于Stream API的概念及运行,可参考博客【Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例】
▚ 04 Set基本操作
4.1 add(): 添加新元素
Set<Integer> num = new HashSet<>();
num.add(1);
4.2 remove(): 删除一个元素
num.remove(1);
4.3 isEmpty(): 判断是否为空
if(num.isEmpty()) {
System.out.println("Empty.");
} else {
System.out.println("Not empty.");
}
4.4 size(): 返回大小
num.size();
4.5 上述示例的可运行源码
- Set基本操作源代码:
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
public class set_basic_op {
public static void main(String[] args) throws IOException {
Set<Integer> num_set = new HashSet<>();
num_set.add(1);
num_set.add(2);
num_set.add(3);
num_set.add(4);
System.out.println("[Before remove] elements of num_set: " + num_set);
System.out.println("[Before remove] size of num_set: " + num_set.size());
num_set.remove(2);
System.out.println("[After remove] elements of num_set: " + num_set);
System.out.println("[After remove] size of num_set: " + num_set.size());
if(num_set.isEmpty()) {
System.out.println("num_set is empty");
} else {
System.out.println("num_set is not empty");
}
}
}
- 输出:
[Before remove] elements of num_set: [1, 2, 3, 4]
[Before remove] size of num_set: 4
[After remove] elements of num_set: [1, 3, 4]
[After remove] size of num_set: 3
num_set is not empty
▚ 05 遍历集合
5.1 使用iterator
Set<Integer> names = new HashSet<>();
num.add(2);
num.add(4);
Iterator<Integer> it = num.iterator();
while (it.hasNext()) {
Integer n = it.next();
System.out.println(n);
}
- 输出:
2
4
5.2 使用for
for (Integer n : num) {
System.out.println(n);
}
5.3 使用forEach:
- 在
Java 8
中用Lambda
表达式使用forEach()
方法:
num.forEach(System.out::println);
5.4 上述示例的可运行源码
- 遍历集合操作源代码:
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
public class set_traverse {
public static void main(String[] args) throws IOException {
Set<Integer> num_set = new HashSet<>();
num_set.add(1);
num_set.add(2);
num_set.add(3);
num_set.add(4);
System.out.println("Elements of num_set: " + num_set);
//Iterator
Iterator<Integer> it = num_set.iterator();
System.out.println("iterator: ");
while(it.hasNext()) {
Integer num = it.next();
System.out.println(num);
}
//for
System.out.println("for: ");
for(Integer num : num_set) {
System.out.println(num);
}
//forEach
System.out.println("forEach: ");
num_set.forEach(System.out::println);
}
}
- 输出:
Elements of num_set: [1, 2, 3, 4]
iterator:
1
2
3
4
for:
1
2
3
4
forEach:
1
2
3
4
▚ 06 搜索特定元素
- 对于
contains
方法,如果集合中包含指定的元素,则返回true
,否则返回false
。
if (num.contains(5)) {
System.out.println("Found 5");
}
▚ 07 两个Sets的块操作
7.1 子集操作(containsAll)
-
s1.containsAll(s2)
: 如果s2是s1的子集(如果s1包含s2中的所有元素,则s2是s1的子集),返回true。
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
public class set_containsAll {
public static void main(String[] args) throws IOException {
Set<Integer> num_set = new HashSet<>();
num_set.add(1);
num_set.add(2);
num_set.add(3);
num_set.add(4);
Set<Integer> sub_set1 = new HashSet<>();
sub_set1.add(2);
sub_set1.add(4);
Set<Integer> sub_set2 = new HashSet<>();
sub_set2.add(2);
sub_set2.add(5);
System.out.println("num_set: " + num_set);
System.out.println("sub_set1: " + sub_set1);
if(num_set.containsAll(sub_set1)) {
System.out.println("sub_set1 is a subset of num_set.");
} else {
System.out.println("sub_set1 is not a subset of num_set.");
}
System.out.println("\nnum_set: " + num_set);
System.out.println("sub_set2: " + sub_set2);
if(num_set.containsAll(sub_set2)) {
System.out.println("sub_set2 is a subset of num_set.");
} else {
System.out.println("sub_set2 is not a subset of num_set.");
}
}
}
- 输出:
num_set: [1, 2, 3, 4]
sub_set1: [2, 4]
sub_set1 is a subset of num_set.
num_set: [1, 2, 3, 4]
sub_set2: [2, 5]
sub_set2 is not a subset of num_set.
7.2 并集(Union)
-
s1.addAll(s2)
: 将s1转换为s1和s2的并集(两个集合的并集是一个集合中包含的所有元素的集合)。
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
public class set_union {
public static void main(String[] args) throws IOException {
Set<Integer> sub_set1 = new HashSet<>();
sub_set1.add(2);
sub_set1.add(4);
Set<Integer> sub_set2 = new HashSet<>();
sub_set2.add(2);
sub_set2.add(5);
System.out.println("sub_set1: " + sub_set1);
System.out.println("sub_set2: " + sub_set2);
sub_set1.addAll(sub_set2);
System.out.println("After union: " + sub_set1);
}
}
- 输出:
sub_set1: [2, 4]
sub_set2: [2, 5]
After union: [2, 4, 5]
7.3 交集(Intersection)
-
s1.retainAll(s2)
: 将s1转换为s1和s2的交集 (两个集合的交集是只包含两个集合共有的元素的集合)。
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
public class set_intersection {
public static void main(String[] args) throws IOException {
Set<Integer> sub_set1 = new HashSet<>();
sub_set1.add(2);
sub_set1.add(4);
Set<Integer> sub_set2 = new HashSet<>();
sub_set2.add(2);
sub_set2.add(5);
System.out.println("sub_set1: " + sub_set1);
System.out.println("sub_set2: " + sub_set2);
sub_set1.retainAll(sub_set2);
System.out.println("After intersection: " + sub_set1);
}
}
- 输出:
sub_set1: [2, 4]
sub_set2: [2, 5]
After intersection: [2]
7.4 差集(Difference)
-
s1.removeAll(s2)
: 将s1转换为s1和s2的(非对称)差集 (例如,s1 - s2的差集是包含s1中找到但s2中没有的所有元素的集合)。
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
public class set_difference {
public static void main(String[] args) throws IOException {
Set<Integer> sub_set1 = new HashSet<>();
sub_set1.add(2);
sub_set1.add(4);
Set<Integer> sub_set2 = new HashSet<>();
sub_set2.add(2);
sub_set2.add(5);
System.out.println("sub_set1: " + sub_set1);
System.out.println("sub_set2: " + sub_set2);
sub_set1.removeAll(sub_set2);
System.out.println("After difference: " + sub_set1);
}
}
- 输出:
sub_set1: [2, 4]
sub_set2: [2, 5]
After difference: [4]
参考文献
- Java Set Collection Tutorial and Examples
- What are Generics in Java?
- Set in Java
- Java Set – Set in Java