Loading...

# filter

这是一个 Stream 的过滤转换,此方法会生成一个新的流,其中包含符合某个特定条件的所有元素。

// 过滤出大于 25 的数据
List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
List<Integer> after = before.stream().filter(i -> i > 25).collect(Collectors.toList());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:[30, 40]

# Map

map 方法指对一个流中的值进行某种形式的转换。需要传递给它一个转换的函数作为参数。

// User(String name,int age)
// 将 user 中的 age 转为 list
List<User> before = new ArrayList<>();
before.add(new User("zhangsan", 10));
before.add(new User("lisi", 20));
before.add(new User("zhangsan", 30));
before.add(new User("wangwu", 40));
before.add(new User("zhaoliu", 50));
System.out.println("运行之前:" + before);
// 与下面写法相同
// List<Integer> after = before.stream().map(user -> user.getAge()).collect(Collectors.toList());
List<Integer> after = before.stream().map(User::getAge).collect(Collectors.toList());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[zhangsan:10, lisi:20, zhangsan:30, wangwu:40, zhaoliu:50]
运行之后:[10, 20, 30, 40, 50]

# fiatMap

上面用 map 方法进行流转换的时候,是对每个元素应用一个函数,并将返回的值收集到一个新的流中。但是如果有一个函数,它返回的不是一个值,而是一个包含多个值的流。但是你需要的是一个包含多个流中的元素的集合

List<Integer> oneBefore = new ArrayList<>();
 List<Integer> twoBefore = new ArrayList<>();
 oneBefore.add(1);
 oneBefore.add(2);
 oneBefore.add(3);
 twoBefore.add(4);
 twoBefore.add(5);
 twoBefore.add(6);
 System.out.println("运行之前:" + oneBefore);
 System.out.println("运行之前:" + twoBefore);
 Map<String,List<Integer>> map = new HashMap<>();
 map.put("1",oneBefore);
 map.put("2",twoBefore);
// 返回的是一个流的集合,但是我需要的是 List<Integer > 这样一个集合
 List<Stream<Integer>> oneAfter = map.values().stream().map(Collection::stream).collect(Collectors.toList());
// 这个时候就应该使用 flatMap 将多个流进行合并,然后再收集到一个集合中
 List<Integer> twoAfter = map.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
 System.out.println("运行之后:" + twoAfter);

运行结果:

运行之前:[1, 2, 3]
运行之前:[4, 5, 6]
运行之后:[1, 2, 3, 4, 5, 6]

# Limit

limit (n) 方法会返回一个包含 n 个元素的新的流(若总长小于 n 则返回原始流)。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
List<Integer> after = before.stream().limit(3).collect(Collectors.toList());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:[10, 20, 30]

# Skip

skip (n) 方法正好相反,它会丢弃掉前面的 n 个元素。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
List<Integer> after = before.stream().skip(3).collect(Collectors.toList());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:[40, 5]

用 limit 和 skip 方法一起使用就可以实现日常的分页功能

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
// 当前页号
int page = 1;
// 每页大小
int pageSize = 2;
System.out.println("运行之前:" + before);
List<Integer> after = before.stream().skip(page * pageSize).limit(pageSize).collect(Collectors.toList());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:[30, 40]

# Distinct

根据原始流中的元素返回一个具有相同顺序、去除了重复元素的流,这个操作显然是需要记住之前读取的元素。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(30);
System.out.println("运行之前:" + before);
List<Integer> after = before.stream().distinct().collect(Collectors.toList());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 30]
运行之后:[10, 20, 30, 40]

# Sort

需要遍历整个流的,并在产生任何元素之前对它进行排序。因为有可能排序后集合的第一个元素会在未排序集合的最后一位。

List<Integer> before = new ArrayList<>();
before.add(20);
before.add(10);
before.add(40);
before.add(50);
before.add(30);
System.out.println("------升序------");
System.out.println("运行之前:" + before);
List<Integer> after = before.stream().sorted().collect(Collectors.toList());
System.out.println("运行之后:" + after);
System.out.println("------降序------");
System.out.println("运行之前:" + before);
Comparator<Integer> comparator = (o1, o2) -> o2 - o1;
List<Integer> after_2 = before.stream().sorted(comparator).collect(Collectors.toList());
System.out.println("运行之后:" + after_2);

运行结果:

------升序------
运行之前:[20, 10, 40, 50, 30]
运行之后:[10, 20, 30, 40, 50]
------降序------
运行之前:[20, 10, 40, 50, 30]
运行之后:[50, 40, 30, 20, 10]

# Max 和 Min

返回流中最大值和最小值。

List<Integer> before = new ArrayList<>();
before.add(20);
before.add(10);
before.add(40);
before.add(50);
before.add(30);
System.out.println("运行之前:" + before);
Integer max = before.stream().max(Integer::compareTo).get();
Integer min = before.stream().min(Integer::compareTo).get();
System.out.println("最大值:" + max);
System.out.println("最大值:" + min);

运行结果:

运行之前:[20, 10, 40, 50, 30]
最大值:50
最大值:10

# FindFirst

返回非空集合中的第一个值,它通常与 filter 方法结合起来使用。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
Integer after = before.stream().filter(o -> o > 20).findFirst().get();
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:30

# FindAny

可以在集合中只要找到任何一个所匹配的元素,就返回,此方法在对流并行执行时十分有效(任何片段中发现第一个匹配元素都会结束计算,串行流中和 findFirst 返回一样)。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
Integer after = before.stream().filter(o -> o > 20).findAny().get();
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:30

# AnyMatch

可以判定集合中是否还有匹配的元素。返回结果是一个 boolean 类型值。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
boolean after_1 = before.stream().anyMatch(o -> o > 20);
boolean after_2 = before.stream().anyMatch(o -> o > 40);
System.out.println("运行之后:" + after_1);
System.out.println("运行之后:" + after_2);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:true
运行之后:false

# AllMatch 和 NonoMatch

分别在所有元素匹配和没有元素匹配时返回 true。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(5);
System.out.println("运行之前:" + before);
boolean after_1 = before.stream().allMatch(o -> o > 20);
boolean after_2 = before.stream().noneMatch(o -> o > 40);
System.out.println("运行之后:" + after_1);
System.out.println("运行之后:" + after_2);

运行结果:

运行之前:[10, 20, 30, 40, 5]
运行之后:false
运行之后:true

# Reduce

将流中的元素进行进一步计算的方法。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(50);
// 求和
System.out.println("运行之前:" + before);
Integer after_1 = before.stream().reduce((x, y) -> x + y).get();
System.out.println("运行之后:" + after_1);
// 优化
Integer after_2 = before.stream().reduce(Integer::sum).get();
System.out.println("运行之后:" + after_2);
// 含有初始标识的,求和
Integer after_3 = before.stream().reduce(10, Integer::sum);
System.out.println("运行之后:" + after_3);
// 对元素的长度进行求和 ((total,y)->total+y.toString ().length (),类似于一个累加器,会被重复调用)
Integer after_4 = before.stream().reduce(0, (o, x) -> o + x.toString().length(), (x, y) -> x + y);
System.out.println("运行之后:" + after_4);
// 优化
Integer after_5 = before.stream().map(Objects::toString).mapToInt(String::length).sum();
System.out.println("运行之后:" + after_5);

运行结果:

运行之前:[10, 20, 30, 40, 50]
运行之后:150
运行之后:150
运行之后:160
运行之后:10
运行之后:10

# 收集结果(Collectors)

将一个流收集到一个 List 中。

List<Integer> thereList = before.stream().collect(Collectors.toList());

收集到 Set 中。

Set<Integer> thereSet = before.stream().collect(Collectors.toSet());

收集到 Set 时,控制 Set 的类型。

TreeSet<Integer> treeSet = before.stream().collect(Collectors.toCollection(TreeSet::new));

# 拼接(joining)

将字流中的字符串连接并收集起来。

List<String> before = new ArrayList<>();
before.add("10");
before.add("20");
before.add("30");
before.add("40");
before.add("50");
System.out.println("运行之前:" + before);
String after = before.stream().collect(Collectors.joining());
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 50]
运行之后:1020304050

在将流中的字符串连接并收集起来时,想在元素中介添加分隔符,传递个 joining 方法即可。

String after = before.stream().collect(Collectors.joining(","));

运行结果:

运行之前:[10, 20, 30, 40, 50]
运行之后:10,20,30,40,50

当流中的元素不是字符串时,需要先将流转成字符串流再进行拼接。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(50);
System.out.println("运行之前:" + before);
String after = before.stream().map(Objects::toString).collect(Collectors.joining());
// 同理
// String after_2 = before.stream().map(String::valueOf).collect(Collectors.joining(","));
System.out.println("运行之后:" + after);

运行结果:

运行之前:[10, 20, 30, 40, 50]
运行之后:1020304050

# 收集聚合(summingInt、averagingInt、maxBy、minBy)

分别收集流的总和、平均值、最大值或者最小值。

List<Integer> before = new ArrayList<>();
before.add(10);
before.add(20);
before.add(30);
before.add(40);
before.add(50);
System.out.println("运行之前:" + before);
int sum = before.stream().collect(Collectors.summingInt(Integer::intValue));
// 另一种写法
// int sum = before.stream().mapToInt(Integer::intValue).sum();
System.out.println("求和:" + sum);
Double ave = before.stream().collect(Collectors.averagingInt(Integer::intValue));
System.out.println("平均值:" + ave);
Integer max = before.stream().collect(Collectors.maxBy(Integer::compare)).get();
// 另一种写法
// Integer max = before.stream().max(Integer::compare).get();
System.out.println("最大值:" + max);
Integer min = before.stream().collect(Collectors.minBy(Integer::compare)).get();
// 另一种写法
// Integer min = before.stream().min(Integer::compare).get();
System.out.println("最小值:" + min);

运行结果:

运行之前:[10, 20, 30, 40, 50]
求和:150
平均值:30.0
最大值:50
最小值:10

# 将结果集收集到 Map(toMap)

将集合中的元素收集到 Map 中时,可以使用 Collectors.toMap 方法。这个方法有两个参数,用来生成 Map 的 key 和 value。

List<Student> students = new ArrayList<>();
students.add(new Student("1","11", "zhangsan"));
students.add(new Student("2","22", "lisi"));
students.add(new Student("3","33", "wangwu"));
students.add(new Student("4","44", "zhaoliu"));
System.out.println("运行之前:" + students);
Map<String, String> after = students.stream().collect(Collectors.toMap(Student::getId, Student::getName));
System.out.println("运行之后:" + after);

运行结果:

运行之前:[{id = 1,code = 11,name = zhangsan}, {id = 2,code = 22,name = lisi}, {id = 3,code = 33,name = wangwu}, {id = 4,code = 44,name = zhaoliu}]
运行之后:{1=zhangsan, 2=lisi, 3=wangwu, 4=zhaoliu}

如果多个元素拥有相同的键,在收集结果时会抛出 java.lang.IllegalStateException 异常。可以使用第三个参数来解决,第三个参数用来确定当出现键冲突时,该如何处理结果,如果当出现键冲突时只保留一个并且是保留已经存在的值时,就是如下方式。

Map<String, String> after = students.stream().collect(Collectors.toMap(Student::getId, Student::getName, (l, r) -> l));

如果想指定生成的 Map 类型,则还需要第三个参数。

TreeMap<String, String> afte = students.stream().collect(Collectors.toMap(Student::getId, Student::getName, (l, r) -> l, TreeMap::new));

# 分组(groupingBy)

List<demo.toMap.Student> students = new ArrayList<>();
students.add(new demo.toMap.Student("1","11", "zhangsan"));
students.add(new demo.toMap.Student("2","22", "lisi"));
students.add(new demo.toMap.Student("3","22", "wangwu"));
students.add(new demo.toMap.Student("4","44", "zhaoliu"));
System.out.println("运行之前:" + students);
Map<String, List<Student>> after = students.stream().collect(Collectors.groupingBy(Student::getCode));
System.out.println("运行之后:" + after);

运行结果:

运行之前:[{id = 1,code = 11,name = zhangsan}, {id = 2,code = 22,name = lisi}, {id = 3,code = 22,name = wangwu}, {id = 4,code = 44,name = zhaoliu}]
运行之后:{44=[{id = 4,code = 44,name = zhaoliu}], 22=[{id = 2,code = 22,name = lisi}, {id = 3,code = 22,name = wangwu}], 11=[{id = 1,code = 11,name = zhangsan}]}

# 分片(partitioningBy)

当分类函数是一个返回布尔值的函数时,流元素会被分为两组列表:一组是返回 true 的元素集合,另一组是返回 false 的元素集合。这种情况适用 partitoningBy 方法会比 groupingBy 更有效率。

List<demo.toMap.Student> students = new ArrayList<>();
students.add(new demo.toMap.Student("1","11", "zhangsan"));
students.add(new demo.toMap.Student("2","22", "lisi"));
students.add(new demo.toMap.Student("3","22", "wangwu"));
students.add(new demo.toMap.Student("4","44", "zhaoliu"));
System.out.println("运行之前:" + students);
Map<Boolean, List<demo.toMap.Student>> after = students.stream().collect(Collectors.partitioningBy(o -> "22".equals(o.getCode())));
System.out.println("运行之后:" + after);

运行结果:

运行之前:[{id = 1,code = 11,name = zhangsan}, {id = 2,code = 22,name = lisi}, {id = 3,code = 22,name = wangwu}, {id = 4,code = 44,name = zhaoliu}]
运行之后:{false=[{id = 1,code = 11,name = zhangsan}, {id = 4,code = 44,name = zhaoliu}], true=[{id = 2,code = 22,name = lisi}, {id = 3,code = 22,name = wangwu}]}

# 扩展功能

无论是 groupingBy 方法还是 partitioningBy 方法都是支持的。

List<Student> students = new ArrayList<>();
students.add(new Student("1","11", "zhangsan"));
students.add(new Student("2","22", "lisi"));
students.add(new Student("3","22", "wangwu"));
students.add(new Student("4","44", "zhaoliu"));

counting 方法会返回收集元素的总个数。

// 分组之后,每组的个数
Map<String, Long> after = students.stream().collect(Collectors.groupingBy(Student::getCode, Collectors.counting()));
System.out.println("运行之后:" + after);

运行结果:

运行之后:{44=1, 22=2, 11=1}

summing (Int|Long|Double) 方法接受一个取值函数作为参数,来计算总和。

// 分组之后,各组名字的长度总和
Map<String, Integer> after = students.stream().collect(Collectors.groupingBy(Student::getCode, Collectors.summingInt(o-> o.getName().length())));
System.out.println("运行之后:" + after_2);

运行结果:

运行之后:{44=7, 22=10, 11=8}

maxBy 方法和 minBy 方法接受比较器作为参数来计算最大值和最小值。

Map<String, Optional<Student>> after_1 = students.stream().collect(Collectors.groupingBy(Student::getCode, Collectors.maxBy(Comparator.comparing(Student::getCode))));
Map<String, Optional<Student>> after_2 = students.stream().collect(Collectors.groupingBy(Student::getCode, Collectors.minBy(Comparator.comparing(Student::getCode))));
System.out.println("运行之后:" + after_1);
System.out.println("运行之后:" + after_2);

运行结果:

运行之后:{44=Optional[{id = 4,code = 44,name = zhaoliu}], 22=Optional[{id = 2,code = 22,name = lisi}], 11=Optional[{id = 1,code = 11,name = zhangsan}]}
运行之后:{44=Optional[{id = 4,code = 44,name = zhaoliu}], 22=Optional[{id = 2,code = 22,name = lisi}], 11=Optional[{id = 1,code = 11,name = zhangsan}]}

mapping 方法会将结果应用到另一个收集器上。

Map<String, Optional<String>> after = students.stream().collect(Collectors.groupingBy(Student::getCode, Collectors.mapping(Student::getId, Collectors.maxBy(Comparator.comparing(Integer::valueOf)))));
System.out.println("运行之后:" + after);
System.out.println("运行之后:" + JSON.toJSONString(after));

运行结果:

运行之后:{44=Optional[4], 22=Optional[3], 11=Optional[1]}
运行之后:{44=4, 22=3, 11=1}

# 案例

# List<List<xxx>> 转化为 List<xxx>

将嵌套的 list 合并成一个 list

List<String> list1 = new ArrayList<>();
list1.add("111");
list1.add("222");
list1.add("333");
List<String> list2 = new ArrayList<>();
list2.add("444");
list2.add("555");
list2.add("666");
List<List<String>> before = List.of(list1, list2);
System.out.println("合并之前:" + Arrays.toString(before.toArray()));
// 合并
List<String> after = before.stream().collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
System.out.println("合并之后:" + Arrays.toString(after.toArray()));

运行结果

合并之前:[[111, 222, 333], [444, 555, 666]]
合并之后:[111, 222, 333, 444, 555, 666]

待补充...

更新于

请我喝[茶]~( ̄▽ ̄)~*

七音 微信支付

微信支付

七音 支付宝

支付宝