Java8 Stream
使用方法。
Java8
引入了一个包java.util.stream
,它是由支持元素流上进行函数式操作的类组成。
这个包包含的基本类分别是Stream
用于objects
,以及IntStream
, LongStream
, DoubleStream
分别用于原始数据类型integer
、long
和double
。
java.util.stream.Stream
是表示元素序列的接口。
它支持顺序和聚合操作。
计算过程由源操作、中间操作和终端操作组成流管道。
流是惰性的,流上的操作仅在终端操作启动时执行,源元素仅在需要时才被消耗。
在大多数流操作中,我们需要传递lambda
表达式,该表达式必须是无干扰和无状态的。
无干扰意味着计算操作不修改源流,无状态意味着结果不应该依赖于流管道执行中可以改变的任何状态。
在流操作中传递的参数可以是java 8
函数的实例或lambda
表达式。
当调用中间或终端操作时,流应该只被操作一次,如果它被重用,它将抛出illeglastateException
。
流实现自动关闭,使用后不需要关闭,但如果流源是IO通道,则需要关闭它。
流由集合、数组或生成函数支持。
流可以顺序执行,也可以并行执行,这个选择是在最初创建流时做出的。
流和集合有一些相似之处,但它们在许多方面有所不同。
Parallel
)流和顺序(Sequential
)流Java8流可以并行和顺序地计算。一个一个顺序地执行。在并行处理中,计算是同时进行的。
流内并行处理计算作为聚合操作的管道执行,而顺序流操作作为命令操作执行。
为了处理并行流和序列流,我们需要将流实例化为并行流和序列流,两者在编码上都是相同的。
我们可以实例化如下。
List<String> list = Arrays.asList("A", "B", "C");
list.stream(); //Sequential Stream
list.parallelStream(); //Parallel stream
Collection
还引入了新方法,即Collection.stream()
和Collection.parallelStream()
,用于在我们的代码中获取顺序流和并行流。
Stream
)对于原始数据类型的流,java8
提供IntStream
、LongStream
和DoubleStream
类;
对于对象流,java8
提供Stream
类。有很多方法可以获得这些流的实例。
Collection
的stream()
和parallelStream()
方法,这些方法通过List
、Queue
、Set
等进行扩展。例如在List
的情况下可以使用List.stream()
和List.parallelStream()
方法Map
的情况下使用Map.entrySet().stream()
和Map.entrySet().parallelStream()
方法Arrays.stream
方法。我们可以将原始数据类型或对象的数组传递给这个方法,例如Arrays.stream(int[] array)
或Arrays.stream(Object[] array)
等。Stream.of(Object[] array)
.这里的of()
是Stream
的静态方法。IntStream.range(int, int)
等。Stream.iterate(T seed, UnaryOperator f)
,其中T是元素的类型,f是应用于前一个元素以获取新元素的函数。BufferedReader.lines()
.它返回字符串流。Java8的
Files方法,如
find()、
lines()、
walk()`。这些方法返回流。Random
类可以得到原始数据类型的随机数流。Random
类的ints()
、longs()
和doubles()
方法分别返回IntStream
、LongStream
和DoubleStream
。BitSet.stream()
,我们得到索引流为IntStream
。Pattern.splitAsStream(CharSequence input)
,我们得到字符串流。此方法为模式匹配项周围的给定输入序列创建流。JarFile.stream()
返回ZIP文件项上的有序流。现在我们将在这里讨论java.util.stream.Stream
接口。Stream
类的方法接受函数实例或lambda
表达式作为参数。
流的计算可以按顺序执行,也可以并行执行。
在一行代码中,我们可以对元素流执行聚合操作。
Stream
方法的示例。
Stream.allMatch()
, Stream.anyMatch()
和Stream.noneMatch()
allMatch()
:如果流的所有元素都与给定的Predicate
匹配,则返回true
。
anyMatch()
:如果流的任何元素与给定Predicate
匹配,则返回true
。
noneMatch()
:如果流中没有任何元素与给定Predicate
匹配,则返回true
。
下面是示例代码
MatchElement.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class MatchElement {
public static void main(String[] args) {
Predicate<Integer> p = num -> num % 2 == 0;
List<Integer> list = Arrays.asList(3,5,6);
System.out.println("allMatch:" + list.stream().allMatch(p));
System.out.println("anyMatch:" + list.stream().anyMatch(p));
System.out.println("noneMatch:" + list.stream().noneMatch(p));
}
}
输出
allMatch:false
anyMatch:true
noneMatch:false
Stream.collect()
java 8 Collector
使用可使操作变得简单,下面是计算列表中整数和的例子。
StreamCollect.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamCollect {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(3,5,6);
int sum = list.stream().collect(Collectors.summingInt(i->i));
System.out.println("Sum: "+ sum);
}
}
输出
Sum: 14
Stream.concat()
它创建一个懒连接的流,包括第一个流的和下一个流的所有元素。
StreamConcat.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamConcat {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = Arrays.asList(4,5,6);
Stream<Integer> resStream = Stream.concat(list1.stream(), list2.stream());
resStream.forEach(s->System.out.print(s+" "));
}
}
输出
1 2 3 4 5 6
Stream.count()
它返回流中元素的数量。
StreamCount.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class StreamCount {
public static void main(String[] args) {
Predicate<Integer> p = num -> num % 2 == 0;
List<Integer> list = Arrays.asList(3,4,6);
System.out.println("Count: " + list.stream().filter(p).count());
}
}
输出
Count: 2
Stream.distinct()
它返回具有不同元素的流。
StreamDistinct.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class StreamDistinct {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(3,4,6,6,4);
System.out.println("Distinct Count: " + list.stream().distinct().count());
}
}
输出
Distinct Count: 3
Stream.filter()
它返回包含与给定Predicate
匹配的元素的流。
StreamFilter.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class StreamFilter {
public static void main(String[] args) {
Predicate<Integer> p = num -> num % 2 == 0;
List<Integer> list = Arrays.asList(3,4,6);
list.stream().filter(p).forEach(e -> System.out.print(e+" "));
}
}
输出
4 6
Stream.findAny()
和Stream.findFirst()
Stream.findAny()
:它可能返回流的任何元素。
Stream.findFirst()
:它返回流的第一个元素,如果流没有定义遇到顺序,那么它可以返回任何元素。
StreamFindAnyFindFirst.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class StreamFindAnyFindFirst {
public static void main(String[] args) {
List<String> list = Arrays.asList("G","B","F","E");
String any = list.stream().findAny().get();
System.out.println("FindAny: "+ any);
String first = list.stream().findFirst().get();
System.out.println("FindFirst: "+ first);
}
}
输出
FindAny: G
FindFirst: G
Stream.flatMap()
它在对每个元素应用映射函数后返回一个对象流,然后将结果展开。
StreamFlatMap.java
package com.concretepage;
import java.util.Arrays;
public class StreamFlatMap {
public static void main(String[] args) {
Integer[][] data = {
{
1,2},{
3,4},{
5,6}};
Arrays.stream(data).flatMap(row -> Arrays.stream(row)).filter(num -> num%2 == 1)
.forEach(s -> System.out.print(s+" "));
}
输出
1 3 5
flatMapToInt()
:它与原始数据类型int
一起使用并返回IntStream
。
flatMapToLong()
:它与基元数据类型long
一起使用并返回LongStream
。
flatMapToDouble()
:它与基本数据类型double
一起使用并返回DoubleStream
。
Stream.forEach()
和Stream.forEachOrdered()
forEach()
:它对流的每个元素执行一个操作。
forEachOrdered()
:它对流的每个元素执行一个操作,但如果定义了流,则按遇到的顺执行。
StreamForEach.java
package com.concretepage;
import java.util.Arrays;
public class StreamForEach {
public static void main(String[] args) {
Integer[] data = {
1,2,3,4,5,6,7};
System.out.println("---forEach Demo---");
Arrays.stream(data).filter(num -> num%2 == 1)
.forEach(s -> System.out.print(s+" "));
System.out.println("\n---forEachOrdered Demo---");
Arrays.stream(data).filter(num -> num%2 == 1)
.forEachOrdered(s -> System.out.print(s+" "));
}
}
输出
---forEach Demo---
1 3 5 7
---forEachOrdered Demo---
1 3 5 7
Stream.generate()
和Stream.limit()
generate()
:我们需要将Supplier传递给这个方法,它将返回一个无限连续的无序流。
limit()
:我们需要传递一个max值,它将返回最大元素数的流。
StreamGenerate.java
package com.concretepage;
import java.util.stream.Stream;
public class StreamGenerate {
public static void main(String[] args) {
String str = "Hello World!";
Stream<String> stream = Stream.generate(str::toString).limit(5);
stream.forEach(s->System.out.println(s));
}
}
输出
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Stream.iterate()
我们需要将初始值和UnaryOperator
传递给这个方法,它将返回一个无限连续的无序流。
StreamIterate.java
package com.concretepage;
import java.util.stream.Stream;
public class StreamIterate {
public static void main(String[] args) {
Stream<Integer> stream = Stream.iterate(1, n -> n * 2).limit(5);
stream.forEach(s->System.out.print(s+" "));
}
}
输出
1 2 4 8 16
Stream.map()
它在对流的每个元素应用给定函数后返回一个流。
StreamMap.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class StreamMap {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4);
list.stream().map(i -> i*i)
.forEach(s->System.out.print(s+" "));
}
}
输出
1 4 9 16
mapToInt()
: 它在应用给定函数后返回IntStream
。
mapToLong()
:它在应用给定函数后返回LongStream
。
mapToDouble()
:它在应用给定函数后返回DoubleStream
。
Stream.max()
和Stream.min()
max()
:它为给定的比较器(Comparator
)查找最大元素。.
min()
:它为给定的比较器(Comparator
)查找最小元素。
StreamMaxMin.java
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class StreamMaxMin {
public static void main(String[] args) {
List<String> list = Arrays.asList("G","B","F","E");
String max = list.stream().max(Comparator.comparing(String::valueOf)).get();
System.out.println("Max:"+ max);
String min = list.stream().min(Comparator.comparing(String::valueOf)).get();
System.out.println("Min:"+ min);
}
}
输出
Max:G
Min:B
Stream.peek()
这是一个中间操作。在应用使用者(Consumer
)之后,它返回一个新的流,其中包含流的所有元素。
StreamPeek.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamPeek {
public static void main(String[] args) {
List<String> list = Arrays.asList("A","B","C");
list.stream().peek(s->System.out.println(s+s)).collect(Collectors.toList());
}
}
输出
AA
BB
CC
Stream.reduce()
它使用起始值和累加函数对流元素执行缩减。
StreamReduce.java
package com.concretepage;
import java.util.Arrays;
public class StreamReduce {
public static void main(String[] args) {
int[] array = {
3,5,10,15};
int sum = Arrays.stream(array).reduce(0, (x,y) -> x+y);
System.out.println("Sum:"+ sum);
}
}
输出
Sum:33
Stream.skip()
它返回一个跳过给定数量元素的流。
StreamSkip.java
package com.concretepage;
import java.util.Arrays;
public class StreamSkip {
public static void main(String[] args) {
int[] array = {
3,5,10,15};
Arrays.stream(array).skip(2)
.forEach(s -> System.out.println(s+ " "));
}
}
输出
10
15
Stream.sorted()
它返回一个用给定的比较器(Comparator
)排序的流。
StreamSorted.java
package com.concretepage;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
public class StreamSorted {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "BBBB");
map.put(2, "AAAA");
map.put(3, "CCCC");
System.out.println("---Sort by Map Value---");
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue))
.forEach(e -> System.out.println("Key: "+ e.getKey() +", Value: "+ e.getValue()));
}
}
输出
---Sort by Map Value---
Key: 2, Value: AAAA
Key: 1, Value: BBBB
Key: 3, Value: CCCC
Stream.toArray()
它返回一个包含流元素的数组。
StreamToArray.java
package com.concretepage;
import java.util.Arrays;
import java.util.List;
public class StreamToArray {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C", "D");
Object[] array = list.stream().toArray();
System.out.println("Length of array: "+array.length);
}
}
输出
Length of array: 4
【1】Java Doc: Stream
【2】Java 8 Tutorials
【3】Java 8 Stream Tutorial with Example