目录
1.概述
2.流的创建
3.中间操作
3.1.清单
3.2.filter
3.3.map
3.4.flatMap
3.5.distinct
3.6.sorted
3.7.peek
3.8.limit
3.9.skip
4.中止操作
4.1.清单
4.2.非短路操作
4.2.1.forEach
4.2.2.count
4.2.3.reduce
4.2.4.collect
4.2.5.max、min
4.3.短路操作
4.3.1.findFrist
4.3.2.findAny
4.3.3.allMatch
4.3.4.anyMatch
4.3.5.noneMatch
5.并行流
Java Stream是Java 8引入的一种新特性,用于简化集合类的数据处理和操作。Stream API提供了一种流式处理的方式,可以对数据进行过滤、映射、聚合等操作,使得数据处理更加简洁、高效和易于理解。
stream中对数据的操作分为两类:
两种操作的代码示例:
int[] nums={1,2,3};
//map,中间操作,返回的是流
//sum,中止操作,返回的是最终结果
int sum= IntStream.of(nums).map(i->i*2).sum();
System.out.println(sum);
需要注意的一点是:中间操作都是惰性的,中止操作出现,才会真正执行中间操作。
以上面的例子来说,map操作虽然被率先调用了,但是在sum操作调用之前map操作其实是没有被执行的,sum操作调用后map才会执行。
JDK8开始,JDK中带有多种创建stream的API:
//从集合中创建
List list=new ArrayList<>();
list.stream();
list.parallelStream();
//从数组创建
Arrays.stream(new int[]{1,2,3});
//创建数字流
IntStream.of(1,2,3);
//创建无限流(根据传入的参数,截取指定长度)
new Random().ints().limit(10);
stream的中间操作,本质上就是对流进行加工,返回的是操作后的stream。
中间操作分为两种:
filter(Predicate
List list = Arrays.asList(1,2,3,4,5);
List result = list.stream().filter(x -> x%2==0).collect(Collectors.toList());
// 输出结果为[2, 4]
map(Function
List list = Arrays.asList("apple", "banana", "orange");
List result = list.stream().map(x -> x.length()).collect(Collectors.toList());
// 输出结果为[5, 6, 6]
flatMap(Function
List> list = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));
List result = list.stream().flatMap(x -> x.stream()).collect(Collectors.toList());
// 输出结果为[1, 2, 3, 4, 5, 6]
distinct():去除Stream中的重复元素。
List list = Arrays.asList(1, 2, 2, 3, 3, 4, 4, 5);
List result = list.stream().distinct().collect(Collectors.toList());
// 输出结果为[1, 2, 3, 4, 5]
sorted():对Stream中的元素进行排序。
List list = Arrays.asList(4, 2, 1, 3, 5);
List result = list.stream().sorted().collect(Collectors.toList());
// 输出结果为[1, 2, 3, 4, 5]
peek(Consumer
List list = Arrays.asList(1, 2, 3);
List result = list.stream().peek(x -> x = x + 1).collect(Collectors.toList());
// 输出结果为[1, 2, 3]
limit(long maxSize):截取Stream中的前maxSize个元素。
List list = Arrays.asList(1, 2, 3, 4, 5);
List result = list.stream().limit(3).collect(Collectors.toList());
// 输出结果为[1, 2, 3]
skip(long n):跳过Stream中的前n个元素。
List list = Arrays.asList(1, 2, 3, 4, 5);
List result = list.stream().skip(3).collect(Collectors.toList());
// 输出结果为[4, 5]
在Java Stream API中,中止操作可以分为短路操作和非短路操作,它们的区别在于短路操作是最后一个操作,后面无法再跟任何操作,非短路操作后面还可以跟其他操作。
此操作可以迭代Stream中的每个元素,并对其进行操作。
List list = Arrays.asList("Java", "is", "cool");
list.stream()
.forEach(System.out::println);
此操作可以返回Stream中元素的数量。
List list = Arrays.asList("Java", "is", "cool");
long count = list.stream()
.filter(s -> s.length() > 2)
.count();
System.out.println(count);
此操作可以将Stream中的所有元素合并到一个结果中。
List list = Arrays.asList(1, 2, 3, 4, 5);
Optional result = list.stream()
.reduce((a, b) -> a + b);
System.out.println(result.get());
此操作可以将Stream中的元素收集到一个集合中。
List list = Arrays.asList("Java", "is", "cool");
List result = list.stream()
.collect(Collectors.toList());
System.out.println(result);
此操作可以返回Stream中的最大或最小元素。
List list = Arrays.asList(1, 2, 3, 4, 5);
Optional max = list.stream()
.max(Integer::compareTo);
System.out.println(max.get());
返回Stream中的第一个元素。
List numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional firstEven = numbers.stream()
.filter(n -> n % 2 == 0)
.findFirst();
if (firstEven.isPresent()) {
System.out.println("The first even number is " + firstEven.get());
} else {
System.out.println("No even numbers found.");
}
与findFirst()
相似,findAny()
也返回Stream中的一个元素,但是这个元素可以是任意一个,而不一定是第一个。在并行Stream中,findAny()
可能会返回任何一个符合条件的元素。与findFirst()
不同的是,findAny()
不保证返回的元素是Stream中的第一个符合条件的元素。
List numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional anyEven = numbers.stream()
.filter(n -> n % 2 == 0)
.findAny();
if (anyEven.isPresent()) {
System.out.println("An even number is " + anyEven.get());
} else {
System.out.println("No even numbers found.");
}
allMatch(Predicate
:判断Stream中的所有元素是否都满足给定的Predicate条件。
List numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream()
.allMatch(n -> n % 2 == 0);
if (allEven) {
System.out.println("All numbers are even.");
} else {
System.out.println("Some numbers are not even.");
}
anyMatch(Predicate
:判断Stream中是否存在任意一个元素满足给定的Predicate条件。
List numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean anyEven = numbers.stream()
.anyMatch(n -> n % 2 == 0);
if (anyEven) {
System.out.println("At least one number is even.");
} else {
System.out.println("No even numbers found.");
}
noneMatch(Predicate
:判断Stream中是否没有任何元素满足给定的Predicate条件。
List numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noneNegative = numbers.stream()
.noneMatch(n -> n < 0);
if (noneNegative) {
System.out.println("All numbers are non-negative.");
} else {
System.out.println("Some numbers are negative.");
}
Java Stream提供了一种流式处理的方式,可以快速、方便地对集合、数组等数据进行处理和操作。而并行流则是Java Stream中的一种特殊类型的流,它可以自动将Stream中的数据分成多个小块,并在多个处理器上并行处理这些小块,以提高处理效率。
在Java 8之前,Java只能使用线程来实现并发编程。使用线程编程虽然可以实现并发执行,但是需要程序员自己管理线程的创建、调度和同步等问题,很容易引入死锁、竞争条件等问题。而在Java 8中引入了Stream API和并行流,使得并发编程变得更加容易和高效。
使用并行流的方式非常简单,只需要在创建Stream时调用parallel()
方法,就可以将Stream转换为并行流,如下所示:
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List result = numbers.parallelStream() // 创建并行流
.map(n -> n * n) // 对每个元素进行平方运算
.collect(Collectors.toList()); // 将结果收集到列表中
System.out.println(result);
在上面的示例中,使用parallelStream()
方法创建一个并行流,并使用map()
方法对每个元素进行平方运算,最后使用collect()
方法将结果收集到一个列表中。
当列表中的元素数量很大时,使用并行流可以显著提高运行效率,因为并行流可以在多个处理器上并行处理元素。同时,Java Stream API的设计也保证了在并行执行时,Stream的操作是线程安全的,不需要程序员自己进行线程同步。