为什么需要使用Stream
Stream 的操作流程
- 获取一个数据源(source)
- 中间数据操作
执行中间操作,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道 - 终止操作,获得想要的结果
如下图所示:
Intermediate(中间数据操作):
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
Short-circuiting(短路操作):
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
获取一个数据源(source)
- Collection 和数组Arrays中的静态方法
Collection.stream();Collection.parallelStream()
Arrays.stream(T array) or Stream.of()
例如:
Stream<String> listStream = Arrays.asList("aa","bb","cc").stream();
String[] stringArray = {"aa","bb","cc"};
Stream<String> arrayStream = Arrays.stream(stringArray);
- 通过Stream类中的一些静态方法获取流
例如 Stream.of();Stream.iterate();Stream.generate()
Stream<String> stream = Stream.of("aa","bb","cc");
Stream<Integer> stream1 = Stream.iterate(2, (x) -> x * 2);
Stream<Double> stream2 = Stream.generate(() -> Math.random());
- 其它一些类,可以获取stream对象
java.nio.file.Files.walk()
Random.ints()
BitSet.stream()
Pattern.splitAsStream(java.lang.CharSequence)
JarFile.stream()
ava.io.BufferedReader.lines()
中间数据操作
即对数据的流进行一些需要的操作,在终止操作执行之前,中间操作可以不断执行。
如图:
中间操作主要用到strem类提供的一些可以返回Stream流的静态方法,主要示例一些常用的方法,其他可参考在线中文JDK1.8 http://www.matools.com/api/java8
filter(Predicate<? super T> predicate)
顾名思义,过滤输入流中的一些元素,只输出符合条件的一些元素,需要给定筛选条件(Predicate<? super T> predicate)
举例说明:
Stream<String> listStream = Arrays.asList("aa","bb","cc").stream();
Stream<String> handledStream = listStream.filter(a -> "aa".equals(a));
System.err.println("filter after:" + handledStream.collect(Collectors.toList()));
输出结果为:
从结果中可以看出来,原有数组中[“aa”,“bb”,“cc”],经过过滤条件 “aa”.equals(a) 的筛选以后,新输出的数组,只剩下了符合条件的[“aa”]。
此处可能会产生两个疑问:
- 此时如果执行
System.err.println("before:" + listStream.collect(Collectors.toList()));
会报错,为什么呢?
流只能被读一遍,详细见后文 handledStream.collect(Collectors.toList())
是什么意思呢?
将流转换为List,方便输出查看结果,详细见后文
按照上面的思路,把Stream中的一些静态方法都执行一遍,看每个静态方法都有什么作用。
distinct()
返回由该流的不同元素(根据 Object.equals(Object) )组成的流。即去重的意思
@Test
public void streamDistinctTest() {
Stream<String> listStream = Arrays.asList("aa","aa", "bb", "cc", "eee", "cc").stream();
Stream<String> handledStream = listStream.distinct();
System.err.println("distinct after:" + handledStream.collect(Collectors.toList()));
}
结果如下:
从结果中看,原数组为[“aa”,“aa”, “bb”, “cc”, “eee”, “cc”],distinct之后,重复的"aa","cc"被去除掉了。
上文中的 “根据 Object.equals(Object)” 又是什么意思呢,即如果传入是一个Object对象,判断是否重复的办法是调用equels方法去重,如果需要实现自己的去重规则,需要重写对象中的equels方法。
limit(long maxSize)
返回由此流的元素组成的流,截短长度不能超过 maxSize。即截取maxSize长度的数据。
@Test
public void streamLimitTest() {
Stream<String> listStream = Arrays.asList("aa","aa", "bb", "cc", "eee", "cc").stream();
Stream<String> handledStream = listStream.limit(3);
System.err.println("limit after:" + handledStream.collect(Collectors.toList()));
}
结果如下:
skip(long n)
丢弃前n个元素,只保留后面的元素
@Test
public void streamSkipTest() {
Stream<String> listStream = Arrays.asList("aa", "bb", "cc", "eee", "cc").stream();
Stream<String> handledStream = listStream.skip(2);
System.err.println("skip after:" + handledStream.collect(Collectors.toList()));
}
结果如下:
从结果中可以看出来,skip跳过了前两个元素,只返回了后三个元素
sorted()
返回由此流的元素组成的流,根据自然顺序排序。
@Test
public void streamSortTest() {
Stream<String> listStream = Arrays.asList("hh", "gg", "ee", "dd", "cc").stream();
Stream<String> handledStream = listStream.sorted();
System.err.println("sorted after:" + handledStream.collect(Collectors.toList()));
}
结果如下:
从结果中可以看到,对原数组[“hh”, “gg”, “ee”, “dd”, “cc”],进行了一个字符串的排序
map
map()方法为流中的每个输入值生成一个输出值。
因此,如果流中有n个元素,则map()操作将生成n个输出元素的流。
@Test
public void streamMapTest() {
List<String> listOfStrings = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> listOfIntegers = listOfStrings.stream()
.map(Integer::valueOf)
.collect(Collectors.toList());
System.err.println(listOfIntegers);
}
flatMap
flatMap()是两步过程,即map()+ Flattening。
它有助于将Collection <Collection >转换为Collection 。
@Test
public void streamFlatMapTest() {
List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = Arrays.asList(4,5,6);
List<Integer> list3 = Arrays.asList(7,8,9);
List<List<Integer>> listOfLists = Arrays.asList(list1, list2, list3);
List<Integer> listOfAllIntegers = listOfLists.stream()
.flatMap(x -> x.stream())
.collect(Collectors.toList());
System.err.println(listOfAllIntegers);
}
终止操作
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator、collect