一、如何创建Stream?
1、 由集合创建流
list = list.stream()
.filter(str -> StringUtils.equals("3", str))
.collect(Collectors.toList());
2、 由数组创建流
Arrays.stream 方法:从数组创建一个流,接受一个数组作为参数。
int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();
3、由值创建流
Stream.of 静态方法:显式值 创建一个流,它可以接受任意数量的参数。可以接受数组、集合
Stream<String> stream = Stream.of("java 8", "lambdas", "in", "action");
stream.map(String::toUpperCase).forEach(System.out::println);
// 空流
Stream<String> emptyStream = Stream.empty();
4、 由文件生成流
java.nio.file.Files 中的很多静态方法都会返回一个流。
Files.lines 方法:会返回一个由指定文件中的各行构成的字符串流。
// 看一个文件中有多少各不相同的词
long uniqueWords = 0;
try(Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().count();
} catch (Exception e) {
}
5、 由函数生成流:创建无限流
Stream.iterate 静态方法:“迭代”,创建无限流,接受一个初始值,还有一个依次应用在每个产生的新值上的Lambda(UnaryOperator<t>类型)。
Stream.iterate(0, n -> n+2).limit(10).forEach(System.out::println);
Stream.generate 静态方法:“生成”,创建无限流。接受一个Supplier<T>类型的lambda提供新的值。
Stream.generate(Math::random).limit(5).forEach(System.out::println);
二、Stream中常用方法?短路操作
-
filter()
-
findAny()
findFirst()
-
map()
-
flatMap()
-
count
-
min
,max
-
allMatch
,noneMatch
-
distinct
,limit
-
sort
1、Filter & Predicate 过滤
names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
System.out.println(name + " ");
});
Predicate<String> startsWithJ = (n) -> n.startsWith("J");
Predicate<String> fourLetterLong = (n) -> n.length() == 3;
Stream<String> stringStream = names.stream().filter(startsWithJ.and(fourLetterLong));
Stream<String> stringStream1 = names.stream().filter((name) -> (startsWithJ.test(name)));
2、findAny findFirst
findAny方法:返回当前流中的任意一个元素。它可以与其他流操作集合使用。
findFirst方法:找出第一个
// 给定一个数字列表,找出第一个平方能被3整除的数
Integer integer = Arrays.asList(1, 2, 3, 4, 5).stream().filter(x -> x > 2).findFirst().orElse(0);
3、Map
针对管道流中的每一个数据元素进行转换操作。
List<String> thisGeminiSkuNo =
skuSaleChannels.stream().map(SkuSaleChannel::getSkuNoExternal)
.filter(StringUtils::isNotEmpty).collect(Collectors.toList());
List<String> upperString = Arrays.asList("aa", "bb").stream()
.map(String::toUpperCase).collect(Collectors.toList());
4、flatMap 将多个Stream连接成一个Stream
多个List合并成一个List
List<Integer> result= Stream.of(Arrays.asList(1,3),Arrays.asList(5,6))
.flatMap(a->a.stream()).collect(Collectors.toList());
List<Integer> level1 = Arrays.asList(1, 2);
List<List<Integer>> level0 = new ArrayList<>(); //[[1, 2], [1, 2]]
level0.add(level1);
level0.add(level1);
List<Integer> collect3 = level0.stream()
.flatMap(Collection::stream).collect(Collectors.toList());
5、Count 计总数
int countOfAdult=persons.stream()
.filter(p -> p.getAge() > 18)
.map(person -> new Adult(person))
.count();
6、Min 最小值
Stream.of(integers)
.filter(Objects::nonNull)
.min(Long::compareTo).orElse(0L);
}
7、Max 最大值
Stream.of(integers)
.filter(Objects::nonNull)
.max(Long::compareTo).orElse(0L);
8、 Match 检查流是否匹配所有元素
allMatch方法:检查流中元素是否都能匹配给定的元素
// 是否所有元素都大于0
boolean flag = Arrays.asList(1, 2, 3, 4, 5).stream().allMatch(d -> d > 0);
noneMatch方法:流中没有任何元素与给定的谓词匹配
// 是否所有元素都大于 1000
boolean flag = Arrays.asList(1, 2, 3, 4, 5).stream().noneMatch(d -> d > 1000);
9、Distinct 去重
List<Integer> distinctList = Arrays.asList(1, 2, 3, 4, 5, 5, 5).stream()
.distinct().collect(Collectors.toList());
10、 sort 排序
谨慎使用,sort操作会很昂贵,尤其对于大型流。
(1)一个无参的方法
Stream<T> sorted();
查看它的实现类,往里进,发现它默认使用的是自然排序compareTo
List<String> natualSort = Arrays.asList("b", "a", "g").stream()
.sorted().collect(Collectors.toList());
(2)一个有参的方法
Stream<T> sorted(Comparator<? super T> comparator);
该方法需要传一个比较器参数,你可以通过实现 java.util.Comparator定制一个比较器
list.stream().sorted((o1, o2) -> {
if((o1.getAge() - o2.getAge()) < 0){
return -1
}else if ((o1.getAge() - o2.getAge()) > 0){
return 1
}else {
return 0;
}
}
11、数组 转 List
String[] arr = {"aa", "bb"};
List<String> collect = Stream.of(arr).collect(Collectors.toList());
12、List 转 Map
key是Sudent对象的id,value是Sudent对象的某个属性
Map<String, String> map = list.stream()
.collect(Collectors.toMap(Student::getId,Student::getName));
将list转成以id为key的map,value是id对应的Sudent对象:
Map<String, Student> map = list.stream()
.collect(Collectors.toMap(Student::getId, Function.identity()));
三、collect Collector Collectors 结果收集
1、分组
1)groupingBy()操作需要指定一个关键输入,即分组函数
groupingBy(Function<? super T, ? extends K> classifier)
// 根据skuno分组
Map<String, List<SkuMetaRequest>> skuMetaRequestListMap = skuMetaRequestList.stream()
.collect(Collectors.groupingBy(SkuMetaRequest::getSkuNo));
2)groupingBy()操作需要指定两个关键输入,即分组函数和值收集器
groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
// 根据skuno分组,每组统计数量
Map<String, Long> skuMetaRequestCountMap = skuMetaRequestList.stream()
.collect(Collectors.groupingBy(SkuMetaRequest::getSkuNo, Collectors.counting()));
3)groupingBy()操作需要指定三个关键输入,即分组函数、收集容器和值收集器
groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream)
// 根据skuno分组,每组统计数量
Map<String, Long> collect5 = challist.stream()
.collect(Collectors.groupingBy(SkuSaleChannel::getSkuNo, HashMap::new, Collectors.counting()));
2、拼接
// 利用-作为连接符
String splitStr = Stream.of("1", "2", "3").collect(Collectors.joining("-"));
3、多参数
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
Supplier 新建对象, 用来返回的最终结果 BiConsumer accumulator 累加器直接取,将流中每个被遍历的元素添加到新建对象中 BiConsumer combiner 合并器, 在有并行流的时候才会有用, 一个流时代码不会走到这里
// list转为String
String concat = Stream.of("1", "2", "3")
.collect(StringBuilder::new, StringBuilder::append,
StringBuilder::append)
.toString();
四、Stream调试神器 Stream Trace(IDEA自带)
设置断点,然后以debug模式运行,然后点击如下所示“按钮”,就可以进入到StreamTrace可视化调试视图,分为Flat Mode 和 Split Mode两种视图,如下所示: