Why don’t you use a Stream? 😶 (helpless)

Learning generics

Stream learning can’t be done without generics.

An in-depth understanding of Java generics

Overview of Generics in Java – this is definitely the most detailed overview of generic methods out there

In Java? And extends T? Super T understanding

PECS principles in Java generics

Translation: Moved to tears, trying to summarize common Stream operations, only to be tortured by generics all afternoon. Good things to learn to share, link on 😯😯😯

(1) To get a value, you must cast it; ArrayList [] = ArrayList [] = ArrayList [] = ArrayList [] When compiling, the compiler should first check the type, then erase the type, and insert the instruction implementation of the cast in the type parameter (IDEA contains Java class bytecode View tool: click Java class /View/ShowBatecode) -> use of generics: Generic classes, Generic interfaces, and Generic methods -> Why Generic wildcards are introduced (Generic

cannot pass parameters to Generic

classes) -> Upper and lower bounds of Generic wildcards (PECE)

(Suddenly came to mind: Every technology appears to solve a difficult problem.)


Stream Specifies the base operation of a Stream

The set of elements that Stream will process is considered a Stream, and the Stream API is used to perform operations on the elements in the Stream, such as filtering, sorting, aggregating, and so on.

Streams can be created from arrays or collections, and Stream operations can be intermediate and terminal. A stream has features that do not store data, do not change the data source, and delay execution.

Cute new class, for testing:

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
class Person {
    private String name;
    private int salary;
    private int age;
    private String sex;
    private String area;
}
Copy the code

1. Traverse /match (foreach/find/match)

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

A Stream also supports traversal and matching elements of a similar collection, except that the elements in the Stream are of type Optional. Stream traversal and matching is very simple.

@Test public void streamStudyTest1() { List<Integer> integerList = Lists.newArrayList(7, 6, 9, 3, 8, 2, 1); Integerlist.stream ().filter(num -> num > 6).foreach (system.out ::print); // Match first Optional<Integer> firstInteger = integerList.stream().filter(num -> num > 8).findFirst(); if (firstInteger.isPresent()) { System.out.printf("\n%d", firstInteger.get()); } / / match any (applicable to parallel flows, order flow meaningless) Optional < Integer > anyInteger = integerList. ParallelStream () filter (num - > num > 3). The findAny (); if (anyInteger.isPresent()) { System.out.printf("\n%d", anyInteger.get()); }}Copy the code

Output:

798 September 6Copy the code

2. Filter

Filtering is an operation that verifies the elements in the stream according to certain rules and extracts the elements that meet the conditions into the new stream.

① Screen the cute new employees whose salary is higher than 8000 and form a new set:

@Test
    public void streamStudyTest2() {
        List<Person> personList = Lists.newArrayList(
                new Person("Tom", 8900, 23, "male", "New York"),
                new Person("Jack", 7000, 25, "male", "Washington"),
                new Person("Lily", 7800, 21, "female", "Washington"),
                new Person("Anni", 8200, 24, "female", "New York"),
                new Person("Owen", 9500, 25, "male", "New York"),
                new Person("Alisa", 7900, 26, "female", "New York")
        );
        List<String> result = personList.stream().filter(person -> person.getSalary() > 8000)
                .map(Person::getName).collect(Collectors.toList());
        System.out.println(result);
    }
Copy the code

Output cute new:

[Tom, Anni, Owen]
Copy the code

3. Aggregate (Max /min/count)

Max, min, count you are familiar with these words, yes, in mysql we often use them for data statistics. These concepts and usages are also introduced in Java Stream, which greatly facilitates the statistical work of collections and arrays.

Get the longest element in the String collection

 @Test
    public void streamStudyTest3() {
        List<String> stringList = Lists.newArrayList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
        Optional<String> maxLengthString = stringList.stream().max(Comparator.comparingInt(String::length));
        System.out.println(maxLengthString.get());
    }
Copy the code

Output:

weoujgsd
Copy the code

② Get the maximum value in the Integer set

@Test public void streamStudyTest4() { List<Integer> integerList = Lists.newArrayList(7, 6, 9, 3, 8, 2, 1); // Natural sort Optional<Integer> maxInteger = integerlist.stream ().max(Integer::compareTo); System.out.println(maxInteger.get()); MaxInteger2 = integerlist.stream ().max(new Comparator<Integer>() {@override public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); }}); System.out.println(maxInteger2.get()); }Copy the code

Output:

September 1Copy the code

③ Get the best pay

@Test
    public void streamStudyTest5() {
        List<Person> personList = Lists.newArrayList(
                new Person("Tom", 8900, 23, "male", "New York"),
                new Person("Jack", 7000, 25, "male", "Washington"),
                new Person("Lily", 7800, 21, "female", "Washington"),
                new Person("Anni", 8200, 24, "female", "New York"),
                new Person("Owen", 9500, 25, "male", "New York"),
                new Person("Alisa", 7900, 26, "female", "New York")
        );
        Optional<Person> maxSalaryPerson = personList.stream().max(Comparator.comparingInt(Person::getSalary));
        System.out.println(maxSalaryPerson.get());
    }
Copy the code

Output cute new:

Person(name=Owen, salary=9500, age=25, sex=male, area=New York)
Copy the code

④ Count the number of elements in the Integer set greater than 6

@Test
    public void streamStudyTest6() {
        List<Integer> integerList = Lists.newArrayList(7, 6, 9, 3, 8, 2, 1);
        long result = integerList.stream().filter(num -> num > 6).count();
        System.out.println(result);
    }
Copy the code

Output:

3
Copy the code

4. Mapping (map/flatMap)

Mapping, you can map elements of one flow to another flow according to certain mapping rules. Divided into map and flatMap:

  • map: Takes a function as an argument that is applied to each element and mapped to a new element.
  • flatMap: Takes a function as an argument, replaces each value in the stream with another stream, and joins all streams into a single stream.

① English character array all uppercase, integer array all +3

@Test
    public void streamStudyTest7() {
        String[] stringList = {"abcd", "bcdd", "defde", "fTr"};
        List<String> stringResult = Arrays.stream(stringList).map(String::toUpperCase).collect(Collectors.toList());
        System.out.println(stringResult);
        List<Integer> integerList = Lists.newArrayList(7, 6, 9, 3, 8, 2, 1);
        List<Integer> resultInteger = integerList.stream().map(num -> num + 3).collect(Collectors.toList());
        System.out.println(resultInteger);
    }
Copy the code

Output:

[ABCD, BCDD, DEFDE, FTR]
[10, 9, 12, 6, 11, 5, 4]
Copy the code

② Give meng new people general tune 1000

@Test public void streamStudyTest8() { List<Person> personList = Lists.newArrayList( new Person("Tom", 8900, 23, "male", "New York"), new Person("Jack", 7000, 25, "male", "Washington"), new Person("Lily", 7800, 21, "female", "Washington"), new Person("Anni", 8200, 24, "female", "New York"), new Person("Owen", 9500, 25, "male", "New York"), new Person("Alisa", 7900, 26, "female", "New York") ); List<Person> newPersonResult = personlist.stream ().map(Person -> {Person newPerson = new Person(person.getName(), person.getSalary() + 1000, person.getAge(), person.getSex(), person.getArea()); return newPerson; }).collect(Collectors.toList()); System.out.println(newPersonResult); List<Person> personResult = personlist.stream ().map(Person -> {person.setsalary (person.getsalary () +) 1000); return person; }).collect(Collectors.toList()); System.out.println(personResult); }Copy the code

Output cute new:

[Person(name=Tom, salary=9900, age=23, sex=male, area=New York), Person(name=Jack, salary=8000, age=25, sex=male, area=Washington), Person(name=Lily, salary=8800, age=21, sex=female, area=Washington), Person(name=Anni, salary=9200, age=24, sex=female, area=New York), Person(name=Owen, salary=10500, age=25, sex=male, area=New York), Person(name=Alisa, salary=8900, age=26, sex=female, area=New York)]
[Person(name=Tom, salary=9900, age=23, sex=male, area=New York), Person(name=Jack, salary=8000, age=25, sex=male, area=Washington), Person(name=Lily, salary=8800, age=21, sex=female, area=Washington), Person(name=Anni, salary=9200, age=24, sex=female, area=New York), Person(name=Owen, salary=10500, age=25, sex=male, area=New York), Person(name=Alisa, salary=8900, age=26, sex=female, area=New York)]
Copy the code

③ Merge the two character arrays into a new character array

@test public void streamStudyTest9() {List<String> stringList = Lists. NewArrayList ("m,k,l,a", "1,3,5,7"); List<String> newStringList = stringlist.stream ().flatmap (String -> {// convert each element to a stream String[] split = string.split(","); Stream<String> stream = Arrays.stream(split); return stream; }).collect(Collectors.toList()); System.out.println(newStringList); }Copy the code

Output:

[m, k, l, a, 1, 3, 5, 7]
Copy the code

5. Reduce

Reduction, also known as reduction, as the name implies, is to reduce a stream to a value, can achieve the sum of sets, products and maximization operations.

① Find the sum, product and maximum value of the elements of the integer set

@Test public void streamStudyTest10() { List<Integer> integerList = Lists.newArrayList(1, 3, 2, 8, 11, 4); 1 Optional<Integer> result1 = integerlist.stream ().reduce((x, y) -> x + y); 2 Optional<Integer> result2 = integerlist.stream ().reduce(Integer::sum); // Sum method 3 Integer result3 = integerlist.stream ().reduce(0, Integer::sum); // Find the product Optional<Integer> result4 = integerlist.stream ().reduce((x, y) -> x * y); 1 Optional<Integer> result5 = integerlist.stream ().reduce((x, y) -> x > y? x : y); 2 Integer result6 = integerlist.stream ().reduce(integer.min_value, Integer:: Max); System.out.println("list summation: "+ result1.get() + "," + result2.get() + "," + result3); Result4.get (); system.out.println ("list multiply: "+ result4.get()); Result5.get () + "," + result6); system.out.println (" result5.get() + "," + result6); }Copy the code

Output:

List summation: 29,29,29 list product: 2112 list maximum: 11,11Copy the code

Ask for new sum and highest salary

@Test public void streamStudyTest11() { List<Person> personList = Lists.newArrayList( new Person("Tom", 8900, 23, "male", "New York"), new Person("Jack", 7000, 25, "male", "Washington"), new Person("Lily", 7800, 21, "female", "Washington"), new Person("Anni", 8200, 24, "female", "New York"), new Person("Owen", 9500, 25, "male", "New York"), new Person("Alisa", 7900, 26, "female", "New York") ); 1 Optional<Integer> result1 = personList.stream().map(Person::getSalary).reduce(Integer::sum); 2 Integer result2 = personList.stream().reduce(0, (sum, person) -> sum += person.getsalary (), (sum1, sum2) -> sum1 + sum2); Result3 = personlist.stream ().reduce(0, (sum, person) -> sum + person.getsalary (), Integer::sum); 1 Optional<Integer> result4 = personList.stream().map(Person::getSalary).reduce(Integer:: Max); Result5 = personlist.stream ().reduce(0, (Max, person) -> math.max (Max, person.getsalary ()), (max1, max2) -> Math.max(max1, max2)); System.out.println(" result1.get() + "," + result2 + "," + result3); System.out.println(" result4.get() + "," + result5); }Copy the code

Output:

Total salary: 49300,49300,49300 highest salary: 9,500, 9,500Copy the code

6. collect

It is arguably the most varied and feature-rich part of the collection. Literally, a stream is collected, either as a value or as a new collection.

Collect mainly depends on the Java. Util. Stream. Collectors class built-in static methods.

6.1 Collection (toList/toSet/toMap)

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

ToList, toSet and toMap cases:

@Test public void streamStudyTest12() { List<Integer> integerList = Lists.newArrayList(1, 6, 3, 4, 6, 7, 9, 6, 20); List<Integer> newList = integerList.stream().filter(x -> x % 2 == 0).collect(Collectors.toList()); Set<Integer> newSet = integerList.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet()); List<Person> personList = Lists.newArrayList( new Person("Anni", 8200, 24, "female", "New York"), new Person("Owen", 9500, 25, "male", "New York"), new Person("Alisa", 7900, 26, "female", "New York") ); Map<String, Person> newMap = personList.stream().filter(person -> person.getSalary() > 8000).collect(Collectors.toMap(Person::getName, p -> p)); System.out.println("toList: "+ newList); System.out.println("toSet: "+ newSet); System. The out. Print (" toMap: "); newMap.keySet().forEach(System.out::print); }Copy the code

Output:

ToList: [6, 4, 6, 6, 20] toSet: [4, 20, 6] toMap: Owen AnniCopy the code
6.2 statistics (count/averaging)

Collectors provides a series of static methods for collecting statistics:

  • Count:count
  • Average:averagingInt,averagingLong,averagingDouble
  • The most value:maxBy,minBy
  • Sum:summingInt,summingLong,summingDouble
  • Count all of the above:summarizingInt,summarizingLong,summarizingDouble

Number of new hires, average salary, total salary and highest salary:

@Test public void streamStudyTest13() { List<Person> personList = Lists.newArrayList( new Person("Anni", 8200, 24, "female", "New York"), new Person("Owen", 9500, 25, "male", "New York"), new Person("Alisa", 7900, 26, "female", "New York") ); Long count = personlist.stream ().collect(Collectors. Counting ()); Average salaries / / o Double business = personList. Stream () collect (Collectors. AveragingDouble (Person: : getSalary)); // Collectors Optional<Integer> Max = personlist.stream ().map(Person::getSalary).collect(Collectors. MaxBy (Integer::compare));  Integer sum = personlist.stream ().collect(Collectors. SummingInt (Person::getSalary)); // Collect all information at a time DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary)); System.out.println(" new count: "+ count); System.out.println(" average: "+ average); System.out. Println (" sum: "+ sum); System.out.println(" collect "); }Copy the code

Output:

Total number of adorable new salaries: 3 Average salary: 8533.333333333334 Total salary: 25600 DoubleSummaryStatistics{count=3, sum=25600.000000, min=7900.000000, average=8533.333333, Max =9500.000000}Copy the code
6.3 group (partitioningBy/groupingBy)
  • Partition: streamAccording to the conditionIt is divided into two maps. For example, employees are divided into two parts according to whether their salary is higher than 8000.
  • Group: StreamBy an attribute of the elementDivided into multiple maps, such as employees grouped by gender. There are single-level and multi-level grouping.

Whether the new salary is higher than 8K is divided into two parts, and the new salary is divided into gender and region:

@Test public void streamStudyTest14() { List<Person> personList = Lists.newArrayList( new Person("Tom", 8900, 23, "male", "New York"), new Person("Jack", 7000, 25, "male", "Washington"), new Person("Lily", 7800, 21, "female", "Washington"), new Person("Anni", 8200, 24, "female", "New York"), new Person("Owen", 9500, 25, "male", "New York"), new Person("Alisa", 7900, 26, "female", "New York") ); Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(person -> person.getSalary() > 8000)); // Group new Collectors by gender Map<String, List<Person>> group = personlist.stream ().collect(Person::getSex); // Group the children by gender, Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea))); System.out.println(" Split the cute new salary is higher than 8k into two parts: "); part.entrySet().forEach(System.out::println); System.out.println(" group cute new by gender: "); group.entrySet().forEach(System.out::println); System.out.println(" Group the kids by gender first and then by region: "); System.out.println(group2); }Copy the code

Output:

Whether the adorable new salary is higher than 8K is divided into two parts:  false=[Person(name=Jack, salary=7000, age=25, sex=male, area=Washington), Person(name=Lily, salary=7800, age=21, sex=female, area=Washington), Person(name=Alisa, salary=7900, age=26, sex=female, area=New York)] true=[Person(name=Tom, salary=8900, age=23, sex=male, area=New York), Person(name=Anni, salary=8200, Age =24, sex=female, area=New York), Person(name=Owen, salary=9500, age=25, sex=male, area=New York)]  female=[Person(name=Lily, salary=7800, age=21, sex=female, area=Washington), Person(name=Anni, salary=8200, age=24, sex=female, area=New York), Person(name=Alisa, salary=7900, age=26, sex=female, area=New York)] male=[Person(name=Tom, salary=8900, age=23, sex=male, area=New York), Person(name=Jack, salary=7000, age=25, sex=male, area=Washington), Person(name=Owen, salary=9500, age=25, sex=male, area=New York)] select Person(name=Owen, salary=9500, age=25, sex=male, area=New York)  {female={New York=[Person(name=Anni, salary=8200, age=24, sex=female, area=New York), Person(name=Alisa, salary=7900, age=26, sex=female, area=New York)], Washington=[Person(name=Lily, salary=7800, age=21, sex=female, area=Washington)]}, male={New York=[Person(name=Tom, salary=8900, age=23, sex=male, area=New York), Person(name=Owen, salary=9500, age=25, sex=male, area=New York)], Washington=[Person(name=Jack, salary=7000, age=25, sex=male, area=Washington)]}}Copy the code
6.4 Joining

Joining joins elements in a stream into a string using a specified concatenation (null, direct).

@Test
    public void streamStudyTest15() {
        List<Person> personList = Lists.newArrayList(
                new Person("Anni", 8200, 24, "female", "New York"),
                new Person("Owen", 9500, 25, "male", "New York"),
                new Person("Alisa", 7900, 26, "female", "New York")
        );
        String nameJoin = personList.stream().map(Person::getName).collect(Collectors.joining(","));
        System.out.println(nameJoin);
        List<String> charList = Lists.newArrayList("A", "B", "C");
        String english = charList.stream().collect(Collectors.joining());
        System.out.println(english);
    }
Copy the code

Output:

Anni,Owen,Alisa
ABC
Copy the code

6.5 Reducing

The Reducing method provided by the Collectors class adds support for custom reduction compared to the Reduce method of stream itself.

@Test public void streamStudyTest16() { List<Person> personList = Lists.newArrayList( new Person("Anni", 8200, 24, "female", "New York"), new Person("Owen", 8000, 25, "male", "New York"), new Person("Alisa", 4000, 26, "female", "New York") ); Integer sumSalary = personList.stream().collect(0, Person::getSalary, (sum, x) -> sum + (x > 5000 ? x - 5000 : 0))); System.out.println(sumSalary); // Stream reduce Integer sumSalary2 = personlist.stream ().map(Person::getSalary).reduce(0, (sum, x) -> sum + (x > 5000 ? x - 5000 : 0)); System.out.println(sumSalary2); }Copy the code

Output:

6200, 6200,Copy the code

7. Sort

Sorted, middle operation. There are two sorts:

  • sorted(): Natural ordering, elements in the stream need to implement the Comparable interface;
  • sorted(Comparator com): Comparator Specifies a custom sort.
@Test
    public void streamStudyTest17() {
        List<Person> personList = Lists.newArrayList(
                new Person("Tom", 9000, 23, "male", "New York"),
                new Person("Jack", 7000, 25, "male", "Washington"),
                new Person("Lily", 8200, 21, "female", "Washington"),
                new Person("Anni", 8200, 24, "female", "New York"),
                new Person("Owen", 9000, 25, "male", "New York"),
                new Person("Alisa", 7900, 26, "female", "New York")
        );
        // 按工资升序排序(自然排序)
        List<String> sort1 = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName).collect(Collectors.toList());
        // 按工资倒序排序
        List<String> sort2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed()).map(Person::getName).collect(Collectors.toList());
        // 先按工资再按年龄升序排序
        List<String> sort3 = personList.stream().sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName).collect(Collectors.toList());
        // 先按工资再按年龄自定义排序(降序)
        List<String> sort4 = personList.stream().sorted((p1, p2) -> {
            if (p1.getSalary() != p2.getSalary()) {
                return p2.getSalary() - p1.getSalary();
            } else {
                return p2.getAge() - p1.getAge();
            }
        }).map(Person::getName).collect(Collectors.toList());

        System.out.println("按工资升序排序:" + sort1);
        System.out.println("按工资降序排序:" + sort2);
        System.out.println("先按工资再按年龄升序排序:" + sort3);
        System.out.println("先按工资再按年龄自定义降序排序:" + sort4);
    }
Copy the code

Output:

In ascending order by salary: [Jack, Alisa, Lily, Anni, Tom, Owen] in descending order by salary: [Jack, Alisa, Lily, Anni, Tom, Owen] [Owen, Tom, Anni, Jack]Copy the code

8. Extraction/combination

Stream can also be merged, de-duplicated, restricted, or skipped.

@Test public void streamStudyTest18() { 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: Merge two streams distinct: Delete List<String> newList = stream.concat (stream1, stream2).distinct().collect(Collectors. ToList ()); List<Integer> collect = stream.iterate (1, x -> x * 2).limit(10).collect(Collectors. ToList ()); List<Integer> collect2 = stream.iterate (1, x -> x * 2).skip(1).limit(5).collect(Collectors. ToList ()); System.out.println(" stream merge: "+ newList); System.out.println("limit: "+ collect); System.out.println("skip: "+ collect2); }Copy the code

Output:

[a, B, C, D, E, F, g] limit: [1, 2, 4, 8, 16, 64, 128, 256, 512]Copy the code

9. The matched elements (anyMatch/allMatch/noneMatch) [supplementary]

  • Matches any element:anyMatch
  • Match all elements:allMatch
  • Whether all elements are not matched:noneMatch
@test public void streamStudyTest19() {List<Integer> List = array.asList (1, 2, 3, 4, 5, 6); boolean result1 = list.stream().anyMatch(x -> x > 5); Boolean result2 = list.stream(). AllMatch (x -> x >5); >5 Boolean result3 = list.stream(). NoneMatch (x -> x >5); System.out.println(result1); System.out.println(result2); System.out.println(result3); }Copy the code

The output

true
false
false
Copy the code

Deduplicate the set [supplement]

The Stream ofdistinctmethods

Distinct () is a method provided by Stream in Java 8 that returns a Stream composed of different elements from that Stream. Distinct () uses the hashCode() and eqauls() methods to get different elements.

1. Unduplicate the List<String>

@Test
    public void StringListDistinctTest() {
        List<String> stringList = Lists.newArrayList("ABC", "AB", "ABC", "B", "AB");
        List<String> result = stringList.stream().distinct().collect(Collectors.toList());
        result.forEach(System.out::println);
    }
Copy the code

Go after the heavy:

ABC
AB
B
Copy the code

2. Unduplicate the List<Object>

@Data
@AllArgsConstructor
class Student {
    private String stuNo;
    private String name;
}
Copy the code
@Test
    public void ObjectListDistinctTest() {
        List<Student> studentList = Lists.newArrayList(new Student("001", "Tom"), new Student("002", "Jerry"),
                new Student("003", "Tom"), new Student("002", "Jerry"));
        List<Student> result = studentList.stream().distinct().collect(Collectors.toList());
        result.forEach(System.out::println);
    }
Copy the code

Go after the heavy:

Student(stuNo=001, name=Tom)
Student(stuNo=002, name=Jerry)
Student(stuNo=003, name=Tom)
Copy the code

3. Delete an attribute of Object according to List<Object>

  • Collection:CollectionIs a collection class interface,List,SetandQueueIs its subinterface;
  • Collector: is the collector, which is also an interface. Its utility classCollectorsProvides collectors created by many factory methods;
  • Collectors.toCollecction()Method: Returns an element that collects the cumulative input into a new collectionCollector;
  • Collectors.collectingAndThen()Method: Put the element into a new collection and passFunctionDo something about it (e.glist).

The JDK8 Stream operation collectingAndThen– performs a de-redo operation based on an object’s properties

@Test
    public void ObjectListDistinctByProperty() {
        List<Student> studentList = Lists.newArrayList(new Student("001", "Tom"), new Student("002", "Jerry"),
                new Student("003", "Tom"), new Student("002", "Jerry"));
        List<Student> result = studentList.stream().collect(
                Collectors.collectingAndThen(
                        toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new)
        );
        result.forEach(System.out::println);
    }
Copy the code

Go after the heavy:

Student(stuNo=002, name=Jerry)
Student(stuNo=001, name=Tom)
Copy the code

The double colon (::) is the method reference operator, and the expression it is in is called a method reference. Method references can be used if Lambda is implementing a scheme that already exists in other methods.

Lambda expression — method reference (::)

Extract attributes of objects in a collection to list/map

1. Extract the name of the object to obtain a list of names

@Test
    public void getNameList() {
        List<Student> studentList = Lists.newArrayList(new Student("001", "Tom"), new Student("002", "Jerry"),
                new Student("003", "Tom"), new Student("002", "Jerry"));
        List<String> result = studentList.stream().map(Student::getName).collect(Collectors.toList());
        result.forEach(System.out::println);
    }
Copy the code

Print a list of names:

Tom
Jerry
Tom
Jerry
Copy the code

2. Extract stuNo of the object as key and transform name as value into map collection

  • filter()The NPE () method filters out objects whose names are null.
  • (k1,k2)->k2The second key is the same key;
  • (k1,k2)->k1Take the first value when encountering the same key;
  • If there is no(k1,k2)->k?When the same key is encountered, an IllegalStateException occurs!
@Test public void listToMap() { List<Student> studentList = Lists.newArrayList(new Student("001", "Tom"), new Student("002", "Jerry"), new Student("001", "Jerry"), new Student("003", null)); Map<String, String> result = studentList.stream() .filter(stu -> stu.getName() ! = null) .collect(Collectors.toMap(Student::getStuNo, Student::getName, (k1, k2) -> k1)); result.values().forEach(System.out::println); }Copy the code

Output value of map collection:

Tom
Jerry
Copy the code

3. Extract the attributes of the object to obtain the List/Map of the new object

@Test
    public void multListOper() {
        List<Person> personList = Lists.newArrayList(
                new Person("Tom", 9000, 23, "male", "New York"),
                new Person("Jack", 7000, 25, "male", "Washington"),
                new Person("Lily", 8200, 21, "female", "Washington"),
                new Person("Anni", 8200, 24, "female", "New York"),
                new Person("Owen", 9000, 25, "male", "New York"),
                new Person("Alisa", 7900, 26, "female", "New York")
        );
        List<LWPerson> lwList = personList.stream().map(person -> {
            LWPerson lw = new LWPerson();
            lw.setName(person.getName());
            lw.setSalary(person.getSalary());
            return lw;
        }).collect(Collectors.toList());
        lwList.forEach(System.out::println);

        Map<String, LWPerson> lwMap = personList.stream().collect(Collectors.toMap(Person::getName, person -> {
            LWPerson lw = new LWPerson();
            lw.setName(person.getName());
            lw.setSalary(person.getSalary());
            return lw;
        }, (k1, k2) -> k1));
        lwMap.entrySet().forEach(System.out::println);
    }
Copy the code

Output the list/map:

LWPerson(name=Tom, salary=9000)
LWPerson(name=Jack, salary=7000)
LWPerson(name=Lily, salary=8200)
LWPerson(name=Anni, salary=8200)
LWPerson(name=Owen, salary=9000)
LWPerson(name=Alisa, salary=7900)
Tom=LWPerson(name=Tom, salary=9000)
Owen=LWPerson(name=Owen, salary=9000)
Anni=LWPerson(name=Anni, salary=8200)
Alisa=LWPerson(name=Alisa, salary=7900)
Jack=LWPerson(name=Jack, salary=7000)
Lily=LWPerson(name=Lily, salary=8200)
Copy the code

Common Stream manipulation article references:

  1. Share several Java8 methods for de-duplicating lists via Stream
  2. Java8 Stream: 20,000-word 20 instances, play with collection filtering, reduction, grouping, aggregation
  3. JDK8 Stream detailed use