哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:掘金/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的优势
- 简洁性 : 使用
Stream
API可以将原本繁琐的集合操作(如遍历、过滤、转换等)通过链式调用简洁地表达出来,代码更加清晰。 - 并行化支持 :
Stream
API支持并行操作,只需要调用parallelStream()
,即可通过多核处理器并行处理集合中的元素。 - 函数式编程支持 :
Stream
API的操作方法大多数都是基于函数式编程思想设计的,使得代码更加模块化、灵活。
应用场景
Stream
API非常适用于大规模数据处理、集合数据转换和复杂的条件筛选等场景。在现代开发中,尤其是处理API、数据库查询结果、文件流等数据源时,Stream
API能够显著提升代码的可读性和执行效率。
总结
通过熟练掌握Stream
API及其各种方法,相信大家可以更高效地处理Java集合中的数据,简化常见的数据操作,并且提升代码的可维护性。结合Lambda表达式,Stream
API提供了强大的函数式编程能力,可以让你用更少的代码完成更多的任务。如果你还没有完全掌握Stream
API,不妨通过实际的编程练习,深入理解每个方法的使用场景和底层原理,进一步提高你的Java编程水平。
... ...
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
... ...
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!