Stream类全路径为:java.util.stream.Stream
对Stream的描述,引用其他文章中觉得比较好的介绍:
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
即Stream的原理:
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
集合有两种方式生成流:
- stream() − 为集合创建串行流。
- parallelStream() − 为集合创建并行流。
并发模式(parallelStream)能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。java中也提供了多种并行处理的方式,看到一片文章对各几种并行的方式性能进行了测试,可以参考下:java中几种并行方式的性能分析。
Stream的的中间操作(intermediate)和最终操作(terminal)都包含哪些方法可以从类结构中看到:
上面截图基本包含了Strram的所有方法。
中间操作(intermediate)主要有以下方法(此类型的方法返回的都是Stream对象):
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
终端操作(terminal)主要有以下方法:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
此处按照类结构(截图)中的方法的顺序(以下例子中使用了Lambda表达式及方法引用,不了解的请戳:Lambda介绍,方法引用),进行介绍:
List list = Arrays.asList("aaa","ddd","bbb","ccc","a2a","d2d","b2b","c2c","a3a","d3d","b3b","c3c");
list.stream()
.filter((s)->s.contains("a"))
.forEach(s -> System.out.println(s));
以上代码使用filter方法过滤出只包含”a”的元素,然后通过forEach将满足条件的元素遍历出来。输出如下:
aaa
a2a
a3a
list.stream()
.filter((s)->s.contains("a"))
.map((s)-> s + "---map")
.forEach(s -> System.out.println(s));
在filter的基础上,给每个元素后面添加字符串”—map”,输出如下:
aaa—map
a2a—map
a3a—map
list.stream()
.filter((s)->s.contains("a"))
.mapToInt((s)-> s.hashCode())
.forEach(s -> System.out.println(s));
在filter的基础上,将每个元素转换为其hashCode。输出为:
96321
94864
94895
Stream
转换为 Stream
Stream转换为 Stream
Stream转换为 Stream
Stream转换为 Stream
看下例子:
List setList = new ArrayList<>();
setList.add(new String[]{"aa","bb"});
setList.add(new String[]{"cc","dd"});
setList.add(new String[]{"ee","ff"});
//使用map方法
setList.stream()
.map(s->Arrays.stream(s))
.forEach(s-> System.out.println("map==" + s));
//使用flatMap方法
setList.stream()
.flatMap(s->Arrays.stream(s))
.forEach(s-> System.out.println("flatMap==" + s));
输出如下:
map==java.util.stream.ReferencePipeline&Head@50040f0c
map==java.util.stream.ReferencePipeline&Head@2dda6444
map==java.util.stream.ReferencePipeline&Head@5e9f23b4
flatMap==aa
flatMap==bb
flatMap==cc
flatMap==dd
flatMap==ee
flatMap==ff
可以看出map就是将数组流直接返回,flatMap是将数组流中的每个元素都返回。flatMapToInt,flatMapToLong,flatMapToDouble类似,只不过返回的是对应的类型的流,此处不做演示。
List disList = Arrays.asList("aaa","ddd","bbb","ddd","aaa");
disList.stream()
.distinct()
.forEach(s-> System.out.println(s));
输出如下:
aaa
ddd
bbb
List integerList = Arrays.asList(1,2,3,4);
integerList.stream()
.sorted()
.forEach(s-> System.out.println(s));
输出如下:
1
2
3
4
可以按照自定义排序:
integerList.stream()
.sorted((s1,s2)->s2.compareTo(s1))
.forEach(s-> System.out.println(s));
输出如下:
4
3
2
1
integerList.stream()
.peek(s-> System.out.println("peek = "+s));
此时没有输出,代码改为:
integerList.stream()
.peek(s-> System.out.println("peek = "+s))
.forEach(s-> System.out.println("forEach = "+s));
输出如下:
peek = 1
forEach = 1
peek = 2
forEach = 2
peek = 3
forEach = 3
peek = 4
forEach = 4
integerList.stream()
.limit(1)
.forEach(s-> System.out.println(s));
输出为:
1
integerList.stream()
.skip(1)
.forEach(s-> System.out.println(s));
输出如下:
2
3
4
看下使用forEach:
integerList.stream()
.forEach(s-> System.out.println(s));
输出(多次测试,每次结果都不一样):
3
1
4
2
再看使用forEachOrdered:
integerList.parallelStream()
.forEachOrdered(s-> System.out.println(s));
输出(测试多次,每次都是这个结果,与integerList中的元素顺序一致):
2
1
3
4
Object[] array = integerList.stream().toArray();
String[] strArr = integerList.stream().toArray(String[]::new);
Optional reduce = integerList.stream().reduce((a, b) -> a + b);
int integer = integerList.stream().reduce(5,(a, b) -> a + b);
System.out.println(integer);
输出为:
15
此例中使用起始值为5,对集合中每个元素求和,可以理解为:5+2+1+3+4=15。
List collects = integerList.stream()
.filter(a -> a > 1)
.collect(Collectors.toList());
System.out.println(collects);
此处统计集合中大于1的元素并最终返回list。输出如下:
[2, 3, 4]
Integer min = integerList.stream()
.filter(a -> a > 1)
.min((Integer a, Integer b) -> a.compareTo(b))
.get();
System.out.println(min);
输出为:
2
Integer max = integerList.stream()
.filter(a -> a > 1)
.max((Integer a, Integer b) -> a.compareTo(b))
.get();
System.out.println(max);
输出为:
4
long count = integerList.stream()
.filter(a -> a > 1)
.count();
System.out.println(count);
输出为:
3
boolean b = integerList.stream()
.anyMatch(s -> s > 0);
boolean b1 = integerList.stream()
.allMatch(s -> s > 0);
boolean b2 = integerList.stream()
.noneMatch(s -> s > 0);
System.out.println("anyMatch = " + b);
System.out.println("allMatch = " + b1);
System.out.println("noneMatch = " + b2);
输出:
anyMatch = true
allMatch = true
noneMatch = false
Integer first = integerList.stream()
.findFirst()
.get();
System.out.println(first);
输出为:
2
Integer any = integerList.stream()
.findAny()
.get();
System.out.println(any);
输出为:
2
Stream还有几个静态方法,返回都是Stream对象。
静态方法如下:builder(返回Builder对象)、empty、of、iterate、generate、concat。
builder:返回一个Builder对象,Builder对象在调用build()返回Stream对象。
empty:返回一个空的有序的Stream对象。
of:返回包含单个元素的有序的Stream对象。
iterate:返回一个无限元素的有序的Stream对象。需要两个参数,第一个参数为初始值,第二个参数为要引用的方法,然后会通过递归循环调用引用的方法。
Stream.iterate(2,s->s+s)
.limit(10)
.forEach(s-> System.out.println(s));
输出为:
2
4
8
16
32
64
128
256
512
1024
generate:返回一个无限元素的无序的的Stream对象。需要一个参数,参数为引用的方法,然后会通过循环调用引用的方法来生成元素,常用于生成常量Stream和随机元素Stream。
concat:将两个Stream连接成一个Stream。需要两个Stream作为参数,如果两个Stream都是有序的并且无论参数Stream是否是并行Stream,得到的都是有序的Stream。输出元素顺序为先输出第一个Stream的元素,然后输出第二个Stream的元素。当结果Stream关闭时候,两个参数Stream同时关闭。
Stream.concat(integerList.stream(),disList.stream())
.forEach(s-> System.out.println(s));
输出为:
2
1
3
4
11
aaa
ddd
33
bbb
ddd
aaa