哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:掘金/C站/腾讯云/阿里云/华为云/51CTO(全网同号);欢迎大家常来逛逛,互相学习。
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在日常Java开发中,我们都知道Set 是 Collection 接口的一个子接口,它表示一个不允许重复元素的集合。Set接口的常见实现类有 HashSet、LinkedHashSet 和 TreeSet。而在Java 8 起,引入了 Stream API,使得对集合的操作更加简洁和高效。对于 Set 集合,可以利用 Stream API 提供的各种方法来进行数据过滤、转换、排序等操作。
下面是一些常用的 Set 集合与 Stream 方法的示例和用法,看看你们都有用过那几种?
正文
1. 将 Set 转换为 Stream
首先,您需要将 Set 转换为 Stream,然后才能使用 Stream 提供的各种操作。
java
/**
* @Author 喵手
*/
public class SetStreamExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));
// 将 Set 转换为 Stream
set.stream().forEach(System.out::println);
}
}
输出结果:
json
Java
Python
JavaScript
Ruby
实际运行结果展示如下:

2. filter():过滤元素
filter() 方法用于过滤集合中的元素,可以根据指定的条件进行筛选。
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamFilterExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));
// 使用 filter 过滤包含 "Java" 的元素
set.stream()
.filter(e -> e.contains("Java"))
.forEach(System.out::println);
}
}
输出结果:
json
Java
JavaScript
实际运行结果展示如下:

3. map():转换元素
map() 方法用于将集合中的元素转换为其他类型或修改元素的内容。
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamMapExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("java", "python", "javascript", "ruby"));
// 将所有元素转换为大写
set.stream()
.map(String::toUpperCase) // 使用 map 转换为大写
.forEach(System.out::println);
}
}
输出结果:
json
JAVA
PYTHON
JAVASCRIPT
RUBY
实际运行结果展示如下:

4. distinct():去重
虽然 Set 本身保证元素唯一,但在某些情况下,您可能在流操作中希望去除重复的元素。distinct() 方法用于返回流中不重复的元素。
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamDistinctExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "Java", "Ruby", "Python"));
// 使用 distinct 去除重复元素
set.stream()
.distinct()
.forEach(System.out::println);
}
}
输出结果:
json
Java
Python
Ruby
实际运行结果展示如下:

5. sorted():排序
sorted() 方法用于对集合中的元素进行排序。默认是按照元素的自然顺序进行排序,也可以使用自定义的比较器来排序。
普通排序
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamSortedExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));
// 使用 sorted() 进行排序(按字母升序)
set.stream()
.sorted() // 默认排序
.forEach(System.out::println);
}
}
输出结果:
json
Java
JavaScript
Python
Ruby
实际运行结果展示如下:

代码解析:
如上这段示例代码的目的是演示如何通过 Java 的流(Stream)API对集合进行排序,并输出排序后的元素。以下是详细的解析,仅供参考:
-
创建集合:
javaSet<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));这行代码创建了一个
HashSet集合,并用Arrays.asList()方法初始化了几个字符串元素。这里的元素是 "Java", "Python", "JavaScript", "Ruby"。HashSet是一个无序集合,元素的顺序是不确定的。 -
流的操作:
javaset.stream() .sorted() // 默认排序 .forEach(System.out::println);-
set.stream():将集合set转换为流。流(Stream)是 Java 8 引入的一种新方式,它可以更简洁、声明性地处理集合数据。 -
sorted():这是一个中间操作,用于对流中的元素进行排序。默认情况下,sorted()方法会按元素的自然顺序(即字母顺序,对于字符串来说就是字典序)对元素进行升序排序。 -
forEach(System.out::println):这是一个终止操作,用于遍历流中的每个元素,并执行System.out::println方法来输出每个元素。
-
-
注意事项:
HashSet本身是不保证元素顺序的,但流(Stream)可以对元素进行排序,因此这里使用stream()和sorted()来实现排序功能。- 由于
sorted()是一个返回新流的操作,因此它不会修改原始的set,而是返回一个排序后的新流。
总结来说,这段代码演示了如何使用 Java 8 的流式操作对集合中的元素进行排序并输出,使用的是默认的字母升序排序。
自定义排序
如果你想按照自定义规则进行排序,可以使用 Comparator。
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamSortedCustomExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));
// 使用自定义的 Comparator 进行排序(按字符串长度升序)
set.stream()
.sorted(Comparator.comparingInt(String::length))
.forEach(System.out::println);
}
}
输出结果:
json
Ruby
Java
Python
JavaScript
实际运行结果展示如下:

6. collect():收集结果
collect() 方法用于将流的元素收集到一个容器中,如集合或列表。它是 Stream API 中最常用的方法之一。
java
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamCollectExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));
// 将流的结果收集到一个 List 中
List<String> list = set.stream()
.collect(Collectors.toList());
System.out.println(list);
}
}
输出结果:
json
[Java, Python, JavaScript, Ruby]
实际运行结果展示如下:

7. reduce():聚合元素
reduce() 方法用于对流中的元素进行聚合。你可以使用它来做加法、乘法等聚合操作。
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamReduceExample {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
// 使用 reduce() 计算所有元素的总和
int sum = set.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("Sum: " + sum);
}
}
输出结果:
json
Sum: 15
实际运行结果展示如下:

8. anyMatch()、allMatch()、noneMatch():匹配操作
这几个方法用于检查流中是否有元素满足给定条件。
anyMatch():检查是否有任何元素满足条件。allMatch():检查是否所有元素都满足条件。noneMatch():检查是否没有任何元素满足条件。
java
import java.util.*;
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SetStreamMatchExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("Java", "Python", "JavaScript", "Ruby"));
// 使用 anyMatch 判断是否有元素包含 'Java'
boolean anyMatch = set.stream()
.anyMatch(e -> e.contains("Java"));
System.out.println("Contains 'Java': " + anyMatch);
// 使用 allMatch 判断是否所有元素包含 'a'
boolean allMatch = set.stream()
.allMatch(e -> e.contains("a"));
System.out.println("All contain 'a': " + allMatch);
}
}
输出结果:
json
Contains 'Java': true
All contain 'a': false
实际运行结果展示如下:

归纳:常用的Stream方法
| 方法 | 作用 | 示例应用 |
|---|---|---|
filter() |
过滤元素,根据条件筛选 | 过滤掉不符合条件的元素 |
map() |
转换元素,进行映射操作 | 将元素转换为另一种类型或值 |
distinct() |
去重 | 去掉集合中重复的元素 |
sorted() |
排序 | 按照自然顺序或自定义规则排序元素 |
collect() |
收集流中的元素到集合 | 将流收集到List、Set等集合中 |
reduce() |
聚合操作,通过二元操作合并流中的元素 | 计算集合元素的总和、最大值等 |
anyMatch() |
判断是否有元素符合条件 | 判断集合中是否有元素满足某条件 |
allMatch() |
判断是否所有元素符合条件 | 判断集合中是否所有元素满足某条件 |
noneMatch() |
判断是否没有元素符合条件 | 判断集合中是否没有元素满足某条件 |
forEach() |
遍历集合中的元素并执行操作 | 对集合中的每个元素执行操作 |
通过利用这些常用的Stream方法,我们可以简洁而高效地处理Java集合数据,完成常见的数据操作,如过滤、转换、排序和聚合等。
接下来,我们来扒拉下上述每个方法的源码,进行深度理解,学习其底层原理。
源码剖析
1. filter()
filter() 方法的源码是通过 AbstractStream 类实现的。其核心逻辑是通过 Predicate 过滤流中的元素。
java
@Override
public Stream<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
return new StreamSpliterators.FilterOp<>(this, predicate);
}
filter()方法会返回一个新的流,该流仅包含满足predicate条件的元素。FilterOp是StreamSpliterators的一个内部类,它会在迭代流时应用过滤条件。
2. map()
map() 方法用于转换流中的元素,同样是在 AbstractStream 中实现。
java
@Override
public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StreamSpliterators.MapOp<>(this, mapper);
}
map()方法通过传入的Function,将流中的每个元素映射为一个新的值。内部通过MapOp类完成具体操作,生成一个新的流。
3. distinct()
distinct() 用于去重,它通过 StreamSpliterators.DistinctOp 来完成去重操作。
java
@Override
public Stream<T> distinct() {
return new StreamSpliterators.DistinctOp<>(this);
}
- 该方法返回一个新的流,去除了流中的重复元素,内部使用
Set来记录已遇到的元素。DistinctOp负责实际的去重操作。
4. sorted()
sorted() 方法用来对流中的元素进行排序。
java
@Override
public Stream<T> sorted() {
return new StreamSpliterators.SortOp<>(this, null);
}
@Override
public Stream<T> sorted(Comparator<? super T> comparator) {
return new StreamSpliterators.SortOp<>(this, comparator);
}
sorted()方法有两个重载,一个使用自然顺序排序,另一个使用自定义Comparator排序。具体排序操作由SortOp类实现。
5. collect()
collect() 是流操作中的一个终结操作,它通过 Collector 来收集元素。
java
@Override
public <R, A> R collect(Collector<? super T, A, R> collector) {
Objects.requireNonNull(collector);
return collector.finisher().apply(collector.accumulator().apply(collector.supplier(), stream));
}
collect()方法调用Collector的方法来执行元素收集操作。它分为supplier(提供一个空的容器)、accumulator(收集数据)、combiner(并行时合并数据)以及finisher(最终转换成结果)。
6. reduce()
reduce() 方法用于将流中的元素合并成一个单一的结果。
java
@Override
public Optional<T> reduce(BinaryOperator<T> accumulator) {
Objects.requireNonNull(accumulator);
return reduce((a, b) -> accumulator.apply(a, b));
}
@Override
public T reduce(T identity, BinaryOperator<T> accumulator) {
Objects.requireNonNull(accumulator);
T result = identity;
for (T element : this) {
result = accumulator.apply(result, element);
}
return result;
}
reduce()方法依赖于二元操作BinaryOperator来将流中的元素逐步合并。第二个重载版本支持一个初始值。
7. anyMatch()
anyMatch() 判断流中是否有元素满足给定条件。
java
@Override
public boolean anyMatch(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
for (T t : this) {
if (predicate.test(t)) {
return true;
}
}
return false;
}
anyMatch()遍历流中的元素,只要有一个元素满足条件,就返回true,否则返回false。
8. allMatch()
allMatch() 判断流中所有元素是否都满足给定条件。
java
@Override
public boolean allMatch(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
for (T t : this) {
if (!predicate.test(t)) {
return false;
}
}
return true;
}
allMatch()方法会检查每一个元素,如果任何一个元素不符合条件,立即返回false。
9. noneMatch()
noneMatch() 判断流中是否没有元素符合给定条件。
java
@Override
public boolean noneMatch(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
for (T t : this) {
if (predicate.test(t)) {
return false;
}
}
return true;
}
noneMatch()遍历流中的元素,如果有任何元素满足条件,则返回false,否则返回true。
10. forEach()
forEach() 遍历流中的元素并对每个元素执行给定的操作。
java
@Override
public void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
forEach()方法遍历流中的每个元素,并对每个元素执行Consumer给定的操作。
小结
在本文中,我们深入探讨了Java 8的Stream API如何与Set集合结合使用,极大简化了集合操作的代码量,同时提升了开发效率。通过示例代码,我们展示了Stream API中的常用操作方法及其实际应用,包括:filter()、map()、distinct()、sorted()、collect()、reduce()、anyMatch()、allMatch()、noneMatch()、以及forEach()等。这些方法使得集合的操作更加简洁、声明性和高效,避免了传统的循环和条件判断,提供了一种更加函数式的编程风格。
关键点回顾
filter(): 用于过滤集合中的元素,基于给定的条件进行筛选。map(): 用于转换集合中的元素,常用于类型转换或内容修改。distinct(): 去除重复元素,尽管Set保证了唯一性,但流操作中可能需要显式去重。sorted(): 排序集合元素,可以使用自然顺序或者自定义的比较器。collect(): 用于将流收集到集合中,如List、Set等。reduce(): 进行聚合操作,将集合中的元素通过某种规则合并成一个结果,常用于求和、求最大值等。- 匹配操作 :
anyMatch()、allMatch()和noneMatch()用于判断流中的元素是否符合给定条件,提供了不同的匹配策略。
流的底层实现
在底层实现方面,Stream API的每个操作方法都通过中间操作和终止操作的组合来实现。例如,filter()会返回一个新的流,其中的元素经过Predicate筛选;map()会根据给定的Function对每个元素进行转换,形成新的流;sorted()会根据自然顺序或自定义比较器对流中的元素进行排序。
这些方法的实现往往涉及到流式迭代器(如StreamSpliterators.FilterOp、StreamSpliterators.MapOp等),它们负责在流的遍历过程中应用具体的操作,如过滤、转换、排序等。
Stream API的优势
- 简洁性 : 使用
StreamAPI可以将原本繁琐的集合操作(如遍历、过滤、转换等)通过链式调用简洁地表达出来,代码更加清晰。 - 并行化支持 :
StreamAPI支持并行操作,只需要调用parallelStream(),即可通过多核处理器并行处理集合中的元素。 - 函数式编程支持 :
StreamAPI的操作方法大多数都是基于函数式编程思想设计的,使得代码更加模块化、灵活。
应用场景
Stream API非常适用于大规模数据处理、集合数据转换和复杂的条件筛选等场景。在现代开发中,尤其是处理API、数据库查询结果、文件流等数据源时,Stream API能够显著提升代码的可读性和执行效率。
总结
通过熟练掌握Stream API及其各种方法,相信大家可以更高效地处理Java集合中的数据,简化常见的数据操作,并且提升代码的可维护性。结合Lambda表达式,Stream API提供了强大的函数式编程能力,可以让你用更少的代码完成更多的任务。如果你还没有完全掌握Stream API,不妨通过实际的编程练习,深入理解每个方法的使用场景和底层原理,进一步提高你的Java编程水平。
... ...
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
... ...
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!