1 从迭代到流的操作
处理集合时,我们通常会用迭代遍历他的元素再进行某项运算,如求和、统计、获取元素等。当使用stream流时,我们不必扫描整个代码去查找或者过滤操作,方法名就可以直接告诉我们其代码完成什么操作。而且,循环需要非常详细地制定操作的顺序,而流却能够以其想要的任何方式来调用这些操作。
简单来说,流遵循了“想做什么而非怎么做”的原则。同时,仅将stream改为parallelStream就可以让流库以并行的方式进行过滤和技术。
1.1 流和集合的差异
1 流并不存储元素,这些元素可能存储在底层的集合中,或者是按需生成的。
2 流的操作不会修改其源数据。例如,filter方法不会将流中的数据移除,而是会生成一个新的流,且新的流中不包含过滤掉的元素。
1.2 简单示例
import java. util. List ;
import java. util. stream. Collectors ;
import java. util. stream. Stream ;
public class StreamTest {
public static void main ( String [ ] args) {
String str = "1,2,3,4,5" ;
List < Integer > arrInt = Stream . of ( str. split ( "," ) ) . map ( r -> Integer . parseInt ( r) ) . collect ( Collectors . toList ( ) ) ;
long count = arrInt. stream ( ) . count ( ) ;
System . out. println ( count) ;
}
}
2 流的创建
2.1 使用Collection接口的stream方法创建
Stream<String> stringStream1 = arrStr.stream();
2.2 如果是数组,则可以使用Stream.of()方法创建
直接传入一个数组对象 Stream<String> stringStream2 = Stream.of(str.split(","));
直接构建一个数组传入 Stream<String> stringStream3 = Stream.of("A","B","C");
2.3 可以选择数组的任意部分创建流
Stream<String> stringStream4 = Arrays.stream(str.split(","), 0, 2);
2.4 其他创建流的方式
1 创建一个元素为定值的流
Stream<String> stringStream5 = Stream.of("s");
2 创建一个不包含任何元素的流
Stream<String> stringStream6 = Stream.empty();
3 创建一个无限流,它的值可以通过反复调用函数来产生
Stream<Double> stringStream7 = Stream.generate(Math::random);
。。。(挺多的)
3 filter、map和flatMap方法
3.1 filter
filter转换会产生一个新的流,它的元素与某种条件匹配,则会过滤。
使用方式:
List<Integer> newIntList = arrInt.stream().filter(element -> element > 2).collect(Collectors.toList());
element是指代流中的元素,可以任意命名,该filter()方法中,作为过滤的条件是element>2,即大于2的元素才会被添加到新的流中,最后被转换成list。
3.2 map
通常,我们想要按照某种方式来转换流中的值,此时,可以使用map方法并且传递执行该转换的函数,
使用方式:
List<Integer> newIntList = arrStr.stream().map(element -> Integer.parseInt(element)).collect(Collectors.toList());
3.3 flatMap
假设有一个函数返回值是一个包含了众多值的流
public Stream < String > getStream ( String s) {
return Stream . of ( s. split ( "" ) ) ;
}
现在需要将其多个流合并成一个,即合并后的效果 ["A","B","C","D","E","F","G","H"],此时用map的话,就会变成 [["A","B","C","D"], ["E","F","G","H"]]
List < String > arrStr1 = Arrays . asList ( "ABCD" , "EFGH" ) ;
Stream < Stream < String > > mapStream = arrStr1. stream ( ) . map ( s -> getStream ( s) ) ;
List < String > arrStr1 = Arrays . asList ( "ABCD" , "EFGH" ) ;
Stream < String > flatMapStream = arrStr1. stream ( ) . flatMap ( s -> getStream ( s) ) ;
4 抽取子流和组合流
1 调用stream.limit(n)会返回一个新的流,它在n个元素之后结束(若n比流元素个数大,则该流结束时会结束)。
Stream<String> flatMapStream = arrStr1.stream().flatMap(s -> getStream(s)).limit(5);
2 调用stream.skip(n)会返回一个新的流,它会跳过n个元素之后开始执行。
Stream<String> flatMapStream = arrStr1.stream().flatMap(s -> getStream(s)).skip(2);
3 调用Stream的静态方法concat(streamA, streamB),会两个流组合并返回。
Stream<String> flatMapStream = Stream.concat(streamA, streamB);
5 其他的流转换
5.1 stream.distinct()
产生一个流,包含当前流中所有不同的元素,如下,使用distinct方法后,会把重复的"JJ"元素过滤只留一个。
Stream<String> uniqueStr = Stream.of("JJ","JJ","JC").distinct();
5.2 stream.sorted()或stream.sorted(Comparator<? super T> comparator)
List<String> sortedStr = Stream.of("CCCC","BC","efg").sorted(); //该方法要求元素是实现了Comparable的类的实例
List<String> sortedStr = Stream.of("CCCC","BC","efg").sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
6 简单约简
约简是一种终结操作,它会将流约简为可以在程序中使用的非流值。如count方法,最终返回流中元素的数量。其他的还有min,max等方法。
package com. trip. demo ;
import java. util. Comparator ;
import java. util. List ;
import java. util. Optional ;
import java. util. stream. Collectors ;
import java. util. stream. Stream ;
public class StreamTest {
public static void main ( String [ ] args) {
List < Integer > list = Stream . of ( 1 , 3 , 5 , 7 , 0 ) . collect ( Collectors . toList ( ) ) ;
long count = list. stream ( ) . count ( ) ;
System . out. println ( "元素个数:" + count) ;
Optional < Integer > min = list. stream ( ) . min ( Comparator . comparing ( Integer :: valueOf ) ) ;
System . out. println ( "最小值:" + min. get ( ) ) ;
Optional < Integer > max = list. stream ( ) . max ( Comparator . comparing ( Integer :: valueOf ) ) ;
System . out. println ( "最大值:" + max. get ( ) ) ;
}
}
输出
Connected to the target VM, address: '127.0.0.1:31627', transport: 'socket'
元素个数:5
最小值:0
最大值:7
Disconnected from the target VM, address: '127.0.0.1:31627', transport: 'socket'
Process finished with exit code 0
7 Optional类型
7.1 获取Optional的值
package com. trip. demo ;
import java. util. Comparator ;
import java. util. Optional ;
import java. util. stream. Stream ;
public class OptionalTest {
public static void main ( String [ ] args) {
Optional < Integer > optional1 = Stream . of ( 1 , 3 , 5 , 7 , 0 ) . min ( Comparator . comparing ( Integer :: valueOf ) ) ;
Integer result1 = optional1. orElse ( 2 ) ;
System . out. println ( "返回值:" + result1) ;
Integer result2 = optional1. orElseGet ( ( ) -> getValue ( ) ) ;
System . out. println ( "返回值:" + result2) ;
try {
Integer result3 = optional1. orElseThrow ( Exception :: new ) ;
System . out. println ( "返回值:" + result3) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
static int getValue ( ) {
return 2 ;
}
}
8 收集结果
package com. trip. demo ;
import java. util. List ;
import java. util. Set ;
import java. util. stream. Collectors ;
import java. util. stream. Stream ;
public class StreamCollectorsTest {
public static void main ( String [ ] args) {
List < Integer > list = Stream . of ( 1 , 3 , 5 , 7 , 0 ) . collect ( Collectors . toList ( ) ) ;
Set < Integer > set = Stream . of ( 1 , 3 , 5 , 7 , 0 ) . collect ( Collectors . toSet ( ) ) ;
String str1 = Stream . of ( "1" , "3" , "0" ) . collect ( Collectors . joining ( ) ) ;
String str2 = Stream . of ( "1" , "3" , "0" ) . collect ( Collectors . joining ( "," ) ) ;
String str3 = Stream . of ( 1 , 2 , 0 ) . map ( Object :: toString ) . collect ( Collectors . joining ( "," ) ) ;
List < User > list = new ArrayList < > ( ) ;
list. add ( new User ( "Java" , 1 ) ) ;
list. add ( new User ( "Python" , 2 ) ) ;
Map < Integer , String > map = list. stream ( ) . collect ( Collectors . toMap ( User :: getId , User :: getName ) ) ;
}
}