掌握Java 8 Stream API的艺术:详解流式编程(二)https://developer.aliyun.com/article/1480490
分组(partitioningBy/groupingBy)
- 分区:将stream按条件分为两个Map,比如员工按薪资是否高于8000分为两部分。
- 分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。
案例:将员工按薪资是否高于8000分为两部分;将员工按性别和地区分组
public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, "male", "New York")); personList.add(new Person("Jack", 7000, "male", "Washington")); personList.add(new Person("Lily", 7800, "female", "Washington")); personList.add(new Person("Anni", 8200, "female", "New York")); personList.add(new Person("Owen", 9500, "male", "New York")); personList.add(new Person("Alisa", 7900, "female", "New York")); // 将员工按薪资是否高于8000分组 Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000)); // 将员工按性别分组 Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex)); // 将员工先按性别分组,再按地区分组 Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea))); System.out.println("员工按薪资是否大于8000分组情况:" + part); System.out.println("员工按性别分组情况:" + group); System.out.println("员工按性别、地区:" + group2); } }
输出结果:
员工按薪资是否大于8000分组情况:{false=[mutest.Person@2d98a335, mutest.Person@16b98e56, mutest.Person@7ef20235], true=[mutest.Person@27d6c5e0, mutest.Person@4f3f5b24, mutest.Person@15aeb7ab]} 员工按性别分组情况:{female=[mutest.Person@16b98e56, mutest.Person@4f3f5b24, mutest.Person@7ef20235], male=[mutest.Person@27d6c5e0, mutest.Person@2d98a335, mutest.Person@15aeb7ab]} 员工按性别、地区:{female={New York=[mutest.Person@4f3f5b24, mutest.Person@7ef20235], Washington=[mutest.Person@16b98e56]}, male={New York=[mutest.Person@27d6c5e0, mutest.Person@15aeb7ab], Washington=[mutest.Person@2d98a335]}}
接合(joining)
joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(",")); System.out.println("所有员工的姓名:" + names); List<String> list = Arrays.asList("A", "B", "C"); String string = list.stream().collect(Collectors.joining("-")); System.out.println("拼接后的字符串:" + string); } }
运行结果:
所有员工的姓名:Tom,Jack,Lily 拼接后的字符串:A-B-C
归约(reducing)
Collectors类提供的reducing方法,相比于stream本身的reduce方法,增加了对自定义归约的支持。
public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Tom", 8900, 23, "male", "New York")); personList.add(new Person("Jack", 7000, 25, "male", "Washington")); personList.add(new Person("Lily", 7800, 21, "female", "Washington")); // 每个员工减去起征点后的薪资之和(这个例子并不严谨,但一时没想到好的例子) Integer sum = personList.stream().collect(Collectors.reducing(0, Person::getSalary, (i, j) -> (i + j - 5000))); System.out.println("员工扣税薪资总和:" + sum); // stream的reduce Optional<Integer> sum2 = personList.stream().map(Person::getSalary).reduce(Integer::sum); System.out.println("员工薪资总和:" + sum2.get()); } }
运行结果:
员工扣税薪资总和:8700 员工薪资总和:23700
排序(sorted)
sorted,中间操作。有两种排序:
- sorted():自然排序,流中元素需实现Comparable接口
- sorted(Comparator com):Comparator排序器自定义排序
案例:将员工按工资由高到低(工资一样则按年龄由大到小)排序
public class StreamTest { public static void main(String[] args) { List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Sherry", 9000, 24, "female", "New York")); personList.add(new Person("Tom", 8900, 22, "male", "Washington")); personList.add(new Person("Jack", 9000, 25, "male", "Washington")); personList.add(new Person("Lily", 8800, 26, "male", "New York")); personList.add(new Person("Alisa", 9000, 26, "female", "New York")); // 按工资升序排序(自然排序) List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName) .collect(Collectors.toList()); // 按工资倒序排序 List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed()) .map(Person::getName).collect(Collectors.toList()); // 先按工资再按年龄升序排序 List<String> newList3 = personList.stream() .sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName) .collect(Collectors.toList()); // 先按工资再按年龄自定义排序(降序) List<String> newList4 = personList.stream().sorted((p1, p2) -> { if (p1.getSalary() == p2.getSalary()) { return p2.getAge() - p1.getAge(); } else { return p2.getSalary() - p1.getSalary(); } }).map(Person::getName).collect(Collectors.toList()); System.out.println("按工资升序排序:" + newList); System.out.println("按工资降序排序:" + newList2); System.out.println("先按工资再按年龄升序排序:" + newList3); System.out.println("先按工资再按年龄自定义降序排序:" + newList4); } }
运行结果:
按工资升序排序:[Lily, Tom, Sherry, Jack, Alisa] 按工资降序排序:[Sherry, Jack, Alisa, Tom, Lily] 先按工资再按年龄升序排序:[Lily, Tom, Sherry, Jack, Alisa] 先按工资再按年龄自定义降序排序:[Alisa, Jack, Sherry, Tom, Lily]
提取/组合
流也可以进行合并、去重、限制、跳过等操作。
public class StreamTest { public static void main(String[] args) { String[] arr1 = { "a", "b", "c", "d" }; String[] arr2 = { "d", "e", "f", "g" }; Stream<String> stream1 = Stream.of(arr1); Stream<String> stream2 = Stream.of(arr2); // concat:合并两个流 distinct:去重 List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList()); // limit:限制从流中获得前n个数据 List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList()); // skip:跳过前n个数据 List<Integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList()); System.out.println("流合并:" + newList); System.out.println("limit:" + collect); System.out.println("skip:" + collect2); } }
运行结果:
流合并:[a, b, c, d, e, f, g] limit:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] skip:[3, 5, 7, 9, 11]
好,以上就是全部内容,能坚持看到这里,你一定很有收获,那么动一动拿offer的小手,点个赞再走吧,听说这么做的人2021年都交了好运!
原文链接:https://blog.csdn.net/mu_wind/article/details/109516995