掌握Java 8 Stream API的艺术:详解流式编程(三)

简介: 掌握Java 8 Stream API的艺术:详解流式编程

掌握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
相关文章
|
6月前
|
Java API
详细解释一下Stream API中的sorted操作
详细解释一下Stream API中的sorted操作
416 1
|
6月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
358 1
|
6月前
|
Java 测试技术 API
Java Stream API:被低估的性能陷阱与优化技巧
Java Stream API:被低估的性能陷阱与优化技巧
487 114
|
6月前
|
Java API
深入理解Java Stream API:告别繁琐循环
深入理解Java Stream API:告别繁琐循环
328 104
|
6月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
265 6
|
Java
Java8中stream流处理数据21个小案例(学习使用)
Java8中stream流处理数据21个小案例(学习使用)
224 0
|
SQL 存储 前端开发
【Java技术指南】「Java8技术盲区」在奔向Java13的同时,也让我们仔细研究一下Stream的学习认知!
【Java技术指南】「Java8技术盲区」在奔向Java13的同时,也让我们仔细研究一下Stream的学习认知!
391 0
【Java技术指南】「Java8技术盲区」在奔向Java13的同时,也让我们仔细研究一下Stream的学习认知!
|
Java 程序员 API
Java 8 Stream API学习总结
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
1254 0
|
Java API 安全
JAVA8--Stream学习
Stream是什么 怎么使用Stream Stream的建立 Stream中的元素操作 Stream聚合操作 Stream结果处理 Stream分组操作 Stream注意事项 Stream是什么 书上说Stream是对JAVA中对集合处理的抽象,在我看来Stream更像是对java集合的一次扩展,因为Stream中的API都是我们对集合操作中可能遇
1950 0
|
6月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
299 2