laitimes

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

author:Program Ape Mouth
20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

First post a few cases, and students with high level can challenge it:

1. Filter out the employees with a salary greater than 8000 from the employee collection and place them in a new collection.

2. Count the maximum salary, average salary, and sum of salary of employees.

3. Sort employees by salary from highest to lowest, with the same high salary being younger.

4. Classify employees by gender, employees by gender and region, and employees by salary above 8000 in two parts.

It's not hard to use traditional iterative processing, but the code is redundant, compared to Stream. Java 8 is a very successful version, and the new Stream in this version, together with lambda that appeared in the same version, provides great convenience for us to manipulate collections.

For more Java practical tutorials, you can pay attention to the WeChat public account "Java Backend" and search for Java keywords.

So what is Stream?

Stream treats the set of elements to be processed as a stream, and in the process of streaming, the Stream API uses the Stream API to perform operations on the elements in the stream, such as: filtering, sorting, aggregation, etc.

Streams can be created from arrays or collections, and there are two types of operations on streams:

1. Intermediate operations, each time returning a new process, there can be more than one.

2. Terminal operation, each stream can only perform one terminal operation, and the flow cannot be used again after the terminal operation is completed. Terminal operations produce a new set or value.

In addition, Stream has several features:

1. Stream does not store data, but evaluates the data according to specific rules, generally outputting results.

2. Stream does not change the data source, usually resulting in a new collection or a value.

3. Stream has a deferred execution feature, and intermediate operations are executed only when the terminal operation is called.

Streams can be created from collection arrays.

1. Create a stream with a collection through the java.util.Collection.stream() method

List<String> list = Arrays.asList("a", "b", "c");
// 创建一个顺序流
Stream<String> stream = list.stream();
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();           

2. Use the java.util.Arrays.stream(T[] array) method to create a stream with an array

int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);           

3, using Stream's static methods: of(), iterate(), generate()

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println);

Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);           

Output:

0 3 6 9

0.6796156909271994

0.1914314208854283

0.8116932592396652

A simple distinction between stream and parallelStream: stream is a sequential stream, where the main thread performs operations on the stream sequentially, while parallelStream is a parallel stream that operates on the stream internally in a multithreaded parallel execution manner, but only if there is no ordering requirement for data processing in the stream. For example, filtering the odd numbers in a collection, the handling of the two is different:

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

If the amount of data in the stream is large enough, parallel streams can speed up processing. In addition to creating parallel streams directly, you can also swap sequential streams for parallel streams via parallel():

Optional<Integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();           

Before using stream, understand a concept: Optional.

The Optional class is a container object that can be null. The isPresent() method returns true if the value is present, and calling the get() method returns the object.

For more detailed instructions, see: Rookie Tutorial Java 8 Optional Class

Next, a flood of code strikes you! I'm going to use Stream in 20 cases to make the use of Stream clear, and I'll be able to grasp it well by typing through the code.

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

The employee class used in the case

Here are the types of employees used in the later cases:

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"));

class Person {
  private String name; // 姓名
  private int salary; // 薪资
  private int age; // 年龄
  private String sex; //性别
  private String area; // 地区

  // 构造方法
  public Person(String name, int salary, int age,String sex,String area) {
    this.name = name;
    this.salary = salary;
    this.age = age;
    this.sex = sex;
    this.area = area;
  }
  // 省略了get和set,请自行添加

}           

3.1 Foreach/find/match

Stream also supports traversal and matching elements of similar sets, except that elements in Stream exist as Offline types. Stream traversal and matching is very simple.

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections
// import已省略,请自行添加,后面代码亦是

public class StreamTest {
  public static void main(String[] args) {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);

        // 遍历输出符合条件的元素
        list.stream().filter(x -> x > 6).forEach(System.out::println);
        // 匹配第一个
        Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
        // 匹配任意(适用于并行流)
        Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x < 6);
        System.out.println("匹配第一个值:" + findFirst.get());
        System.out.println("匹配任意一个值:" + findAny.get());
        System.out.println("是否存在大于6的值:" + anyMatch);
    }
}           

3.2 Filter

Filtering is the operation of checking the elements in the stream according to certain rules and extracting the elements that meet the conditions into a new stream.

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

Case 1: Filter out the elements greater than 7 in the Integer collection and print them out

public class StreamTest {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2, 9);
    Stream<Integer> stream = list.stream();
    stream.filter(x -> x > 7).forEach(System.out::println);
  }
}           

Expected Results:

8 9

Case two: Screening of employees with salaries above 8,000 and forming a new collection. Forming a new set depends on collect, which is described in more detail later.

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"));
    personList.add(new Person("Anni", 8200, 24, "female", "New York"));
    personList.add(new Person("Owen", 9500, 25, "male", "New York"));
    personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

    List<String> fiterList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName)
        .collect(Collectors.toList());
    System.out.print("高于8000的员工姓名:" + fiterList);
  }
}           

Running result:

Names of employees above 8000: [Tom, Anni, Owen]

3.3 Aggregation (max/min/count)

Max, min, count are familiar to you, yes, in mysql we often use them for data statistics. These concepts and usages are also introduced in Java stream, which greatly facilitates our statistical work on collections and arrays.

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

Case 1: Get the longest element in the String collection.

public class StreamTest {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");

    Optional<String> max = list.stream().max(Comparator.comparing(String::length));
    System.out.println("最长的字符串:" + max.get());
  }
}           
Longest string: weoujgsd

Case 2: Get the maximum value in the Integer collection.

public class StreamTest {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);

    // 自然排序
    Optional<Integer> max = list.stream().max(Integer::compareTo);
    // 自定义排序
    Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
      @Override
      public int compare(Integer o1, Integer o2) {
        return o1.compareTo(o2);
      }
    });
    System.out.println("自然排序的最大值:" + max.get());
    System.out.println("自定义排序的最大值:" + max2.get());
  }
}           

Maximum value for natural sorting: 11

Maximum value for custom sorting: 11

Case Three: The person who gets the highest salary from the employee.

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"));
    personList.add(new Person("Anni", 8200, 24, "female", "New York"));
    personList.add(new Person("Owen", 9500, 25, "male", "New York"));
    personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

    Optional<Person> max = personList.stream().max(Comparator.comparingInt(Person::getSalary));
    System.out.println("员工工资最大值:" + max.get().getSalary());
  }
}           
Maximum employee salary: 9500

Case 4: Calculate the number of elements greater than 6 in the Integer set.

import java.util.Arrays;
import java.util.List;

public class StreamTest {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);

    long count = list.stream().filter(x -> x > 6).count();
    System.out.println("list中大于6的元素个数:" + count);
  }
}           
Number of elements greater than 6 in the list: 4

3.4 Mapping (map/flatMap)

Mapping allows you to map elements of one stream to another stream according to certain mapping rules. Divided into map and flatMap:

  • map: Takes a function as an argument, which is applied to each element and mapped to a new element.
  • flatMap: Takes a function as an argument, swaps each value in the stream for another stream, and then concatenates all the streams into a single stream.
20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections
20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

Case 1: The elements of an English string array are all changed to uppercase. Integer array +3 per element.

public class StreamTest {
  public static void main(String[] args) {
    String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
    List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());

    List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
    List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());

    System.out.println("每个元素大写:" + strList);
    System.out.println("每个元素+3:" + intListNew);
  }
}           

Capitalization of each element: [ABCD, BCDD, DEFDE, FTR]

+3 per element: [4, 6, 8, 10, 12, 14]

Case 2: Increase the salary of employees by 1000.

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"));
    personList.add(new Person("Anni", 8200, 24, "female", "New York"));
    personList.add(new Person("Owen", 9500, 25, "male", "New York"));
    personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

    // 不改变原来员工集合的方式
    List<Person> personListNew = personList.stream().map(person -> {
      Person personNew = new Person(person.getName(), 0, 0, null, null);
      personNew.setSalary(person.getSalary() + 10000);
      return personNew;
    }).collect(Collectors.toList());
    System.out.println("一次改动前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary());
    System.out.println("一次改动后:" + personListNew.get(0).getName() + "-->" + personListNew.get(0).getSalary());

    // 改变原来员工集合的方式
    List<Person> personListNew2 = personList.stream().map(person -> {
      person.setSalary(person.getSalary() + 10000);
      return person;
    }).collect(Collectors.toList());
    System.out.println("二次改动前:" + personList.get(0).getName() + "-->" + personListNew.get(0).getSalary());
    System.out.println("二次改动后:" + personListNew2.get(0).getName() + "-->" + personListNew.get(0).getSalary());
  }
}           

Before one change: Tom–>8900

After one change: Tom–>18900

Before the second change: Tom–>18900

After secondary changes: Tom–>18900

Case Three: Merge two character arrays into a new character array.

public class StreamTest {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");
    List<String> listNew = list.stream().flatMap(s -> {
      // 将每个元素转换成一个stream
      String[] split = s.split(",");
      Stream<String> s2 = Arrays.stream(split);
      return s2;
    }).collect(Collectors.toList());

    System.out.println("处理前的集合:" + list);
    System.out.println("处理后的集合:" + listNew);
  }
}           

Set before processing: [m-k-l-a, 1-3-5]

Processed set: [m, k, l, a, 1, 3, 5]

3.5 Reduce

Reduction, also known as reduction, as the name suggests, is the reduction of a stream to a value that enables summation, product, and maximal operations on sets.

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

Case 1: Find the sum, product, and maximum value of the elements of the Integer set.

public class StreamTest {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
    // 求和方式1
    Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
    // 求和方式2
    Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
    // 求和方式3
    Integer sum3 = list.stream().reduce(0, Integer::sum);
    
    // 求乘积
    Optional<Integer> product = list.stream().reduce((x, y) -> x * y);

    // 求最大值方式1
    Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
    // 求最大值写法2
    Integer max2 = list.stream().reduce(1, Integer::max);

    System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);
    System.out.println("list求积:" + product.get());
    System.out.println("list求和:" + max.get() + "," + max2);
  }
}           

List sum: 29, 29, 29

List product: 2112

List sum: 11, 11

Case 2: Sum of all employees' salaries and maximum wages.

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"));
    personList.add(new Person("Anni", 8200, 24, "female", "New York"));
    personList.add(new Person("Owen", 9500, 25, "male", "New York"));
    personList.add(new Person("Alisa", 7900, 26, "female", "New York"));

    // 求工资之和方式1:
    Optional<Integer> sumSalary = personList.stream().map(Person::getSalary).reduce(Integer::sum);
    // 求工资之和方式2:
    Integer sumSalary2 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(),
        (sum1, sum2) -> sum1 + sum2);
    // 求工资之和方式3:
    Integer sumSalary3 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);

    // 求最高工资方式1:
    Integer maxSalary = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
        Integer::max);
    // 求最高工资方式2:
    Integer maxSalary2 = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
        (max1, max2) -> max1 > max2 ? max1 : max2);

    System.out.println("工资之和:" + sumSalary.get() + "," + sumSalary2 + "," + sumSalary3);
    System.out.println("最高工资:" + maxSalary + "," + maxSalary2);
  }
}           

Sum of wages: 49300, 49300, 49300

Maximum salary: 9500, 9500

3.6 Collect

Collect, collect, can be said to be the most content-rich and feature-rich part. Taken literally, a stream is collected, which can eventually be collected into a value or a new collection.

Collect mainly relies on the static methods built into the java.util.stream.Collectors class.

3.6.1 Aggregation (toList/toSet/toMap)

Because the stream does not store data, after the data in the stream is processed, the data in the stream needs to be reassembled into a new collection. ToList, toSet, and toMap are more commonly used, as well as more complex usages such as toCollection and toConcurrentMap.

Here's a case study of toList, toSet, and toMap:

public class StreamTest {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
    List<Integer> listNew = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
    Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());

    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"));
    personList.add(new Person("Anni", 8200, 24, "female", "New York"));
    
    Map<?, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
        .collect(Collectors.toMap(Person::getName, p -> p));
    System.out.println("toList:" + listNew);
    System.out.println("toSet:" + set);
    System.out.println("toMap:" + map);
  }
}           

toList:[6, 4, 6, 6, 20]

toSet:[4, 20, 6]

toMap:{Tom=mutest. Person@5fd0d5ae, Years=mutest. Person@2d98a335}

3.6.2 Count/averaging

Collectors provides a range of static methods for data statistics:

  • Count: count
  • Average: averagingInt, averagingLong, averagingDouble
  • Maximum: maxBy, minBy
  • Summing: summingInt, summing Long, summingDouble
  • Statistics all of the above: summarizingInt, summarizingLong, summarizingDouble

Case: Count the number of employees, average salary, total salary, maximum salary.

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"));

    // 求总数
    Long count = personList.stream().collect(Collectors.counting());
    // 求平均工资
    Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
    // 求最高工资
    Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
    // 求工资之和
    Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
    // 一次性统计所有信息
    DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

    System.out.println("员工总数:" + count);
    System.out.println("员工平均工资:" + average);
    System.out.println("员工工资总和:" + sum);
    System.out.println("员工工资所有统计:" + collect);
  }
}           

Total number of employees: 3

Average employee salary: 7900.0

Total salaries of employees: 23700

All statistics on employee wages: DoubleSummaryStatistics{count=3, sum=23700.000000,min=7000.000000, average=7900.000000, max=8900.000000}

3.6.3 PartitioningBy/groupingBy

  • Partition: Divide the stream into two Maps by criteria, such as whether the employee is paid more than 8000 or not.
  • Grouping: Divide the collection into multiple Maps, such as employees grouped by gender. There are single-level groupings and multi-level groupings.
20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections

Case: Divide employees into two parts by whether they are paid more than 8,000; group employees by gender and region

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]}}           

3.6.4 Joining

joining can concatenate elements in stream into a string with a specific connector (or directly if not).

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);
  }
}           

Names of all employees: Tom, Jack, Lily

Concatenated string: A-B-C

3.6.5 Reducing

The Reducing method provided by the Collectors class adds support for custom reductions compared to stream's own reduce method.

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());
  }
}           

Total employees' deducted salaries: 8700

Total employee salaries: 23700

3.7 Sorted

sorted, intermediate operation. There are two sorts:

  • sorted(): Naturally ordered, elements in the stream need to implement the Comparable interface
  • sorted(Comparator com): Comparator sequencer custom sorting

Case: Sort employees by salary from highest to lowest (or older to younger for the same salary).

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);
  }
}           

Sorted by salary as they go up: [Lily, Tom, Sherry, Jack, Alisa]

Sort by salary reduction: [Sherry, Jack, Alisa, Tom, Lily]

Sort by salary and then by age: [Lily, Tom, Sherry, Jack, Alisa]

Sort by salary and then by age: [Alisa, Jack, Sherry, Tom, Lily]

3.8 Extraction/Combination

Streams can also be merged, deduplication, throttling, skipping, and so on.

20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections
20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections
20 super-used Java 8 Streams, playing with the filtering, reduction, grouping, and aggregation of collections
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]

Well, that's all, and you'll be rewarded for sticking to it.

blog.csdn.net/mu_wind/article/details/109516995

Read on