java: detailed use of stream

java: detailed use of stream

1 case

1.1 foreach/find/match

Stream also supports traversal and matching elements of similar collections, but the elements in stream exist as Optional types.

package com.base;

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

public class Mstream {
    public static void main(String[] args) {
        List<Integer> i= Arrays.asList(1,5,8,7,9,10,13);
        //Traverse the elements whose output meets the criteria
        i.stream().filter(x->x>6).forEach(System.out::println);
        //Match first
        Optional<Integer> findFirst = i.stream().filter(x->x>6).findFirst();
        //Match any (for parallel streams)
        Optional<Integer> findAny = i.stream().filter(x->x>6).findAny();
        Optional<Integer> findAny2 = i.stream().parallel().filter(x->x>6).findAny();
        //Whether to include elements that meet specific conditions
        boolean anyMatch = i.parallelStream().anyMatch(x->x>6);
        System.out.println("Match first value:"+findFirst.get());
        System.out.println("Match any value:"+findAny.get());
        System.out.println("Match any value 2:"+findAny2.get());
        System.out.println("Is there a number greater than 6:"+anyMatch);
    }
}
8
7
9
10
13
 Match first value: 8
 Match any value: 8
 Match any value 2:9
 Is there a number greater than 6: true

1.2 filter

Filtering is the operation of verifying the elements in the flow according to certain rules and extracting the qualified elements into the new flow.
Example 1:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

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

Example 2:
First create a class Fruit to use construction data for subsequent streams:

import java.math.BigDecimal;
import java.math.BigInteger;

public class Fruit {
    private String name;
    private BigDecimal price;
    private BigInteger number;
    private int total;
    private double RealPrice;

    public Fruit(String name, BigDecimal price, BigInteger number, int total, double realPrice) {
        this.name = name;
        this.price = price;
        this.number = number;
        this.total = total;
        RealPrice = realPrice;
    }

    public String getName() {
        return name;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public BigInteger getNumber() {
        return number;
    }

    public int getTotal() {
        return total;
    }

    public double getRealPrice() {
        return RealPrice;
    }
}

Get the names of all fruits whose price is greater than 2:

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Mstream2 {
    public static void main(String[] args) {
        List<Fruit> f=new ArrayList<>();
        f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
        f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
        f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("12"),20,1.8));
        f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("7"),15,3.2));
        f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));
        List<String> b=f.stream().filter(x->(x.getPrice().compareTo(new BigDecimal("2")) > 0)).map(Fruit::getName).collect(Collectors.toList());
        System.out.println(b);
    }
}
[pear, banana]

1.3 polymerization (max/min/count)

max/min/count is often used for data statistics in mysql. These concepts and usages are also introduced into java stream, which can facilitate the statistics of arrays, collections and other data.

Example 1: get the longest element in the collection

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

List<String> l=Arrays.asList("adam","lily","bob","merry","xiaoxu");
Optional<String> max=l.stream().max(Comparator.comparing(String::length));
System.out.println(max.get());

Example 2: get the maximum value in the Integer set

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

List<Integer> s= Arrays.asList(3,1,4,7,5);
//Natural sorting
Optional<Integer> max1=s.stream().max(Integer::compareTo);
//Custom sorting
Optional<Integer> max2=s.stream().max(new Comparator<Integer>() {
   @Override
   public int compare(Integer o1, Integer o2) {
       return o1.compareTo(o2);
//                Compare: return 0,1: returns the first value 3, - 1 returns the last value 5
   }
});
System.out.println("Maximum natural sort:"+max1.get());
System.out.println("Maximum value of custom sort:"+max2.get());
Maximum natural sort: 7
 Maximum value of custom sort: 7

Example 3: get the highest price of fruit

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

public class Mstream2 {
    public static void main(String[] args) {
        List<Fruit> f=new ArrayList<>();
        f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
        f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
        f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("12"),20,1.8));
        f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("7"),15,3.2));
        f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));
        Optional<Fruit> price_max=f.stream().max(Comparator.comparing(Fruit::getPrice));
        System.out.println("Maximum price of fruit"+price_max.get().getPrice());
    }
}
Maximum price of fruit 4

Example 4: calculate the number of elements greater than 6 in the Integer set

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

List<Integer> s= Arrays.asList(3,1,4,7,5,9);
long count=s.stream().filter(x->x>6).count();
System.out.println("The number greater than 6 is:"+count);
The number greater than 6 is: 2

1.4 mapping (map/flatMap)

Mapping, the elements of one flow can be mapped to another flow according to certain mapping rules. It is 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: take a function as a parameter, replace each value in the stream with another stream, and then connect all streams into one stream.

Example 1: all elements of the English string array are changed to uppercase. Integer array + 3 per element.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

String[] s={"abcd","bcdd","defde","fTr","ASa"};
List<String> l=Arrays.stream(s).map(String::toUpperCase).collect(Collectors.toList());
List<Integer> i=Arrays.asList(3,1,5,4);
List<Integer> ini=i.stream().map(x->x+3).collect(Collectors.toList());
System.out.println("Capitalize each element:"+l);
System.out.println("Each element+3: "+ini);
Capitalize each element:[ABCD, BCDD, DEFDE, FTR, ASA]
Each element+3: [6, 4, 8, 7]

Example 2:

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

public class Mstream2 {
    public static void main(String[] args) {
        List<Fruit> f=new ArrayList<>();
        f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
        f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
        f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("12"),20,1.8));
        f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("7"),15,3.2));
        f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));
        //Do not change the way the original set
        List<Fruit> fruits_new=f.stream().map(fruit -> {
            Fruit fNew=new Fruit(fruit.getName(),null,null,0,0);
            fNew.setPrice(fruit.getPrice().add(new BigDecimal("10")));
            return fNew;
        }).collect(Collectors.toList());
        System.out.println("Before change:"+f.get(0).getName()+"-->"+f.get(0).getPrice());
        System.out.println("After modification:"+fruits_new.get(0).getName()+"-->"+fruits_new.get(0).getPrice());

        //Change the way the original set
        List<Fruit> fruits_new2=f.stream().map(Fruit->{
            Fruit.setPrice(Fruit.getPrice().add(new BigDecimal("20")));
            return Fruit;
        }).collect(Collectors.toList());
        System.out.println("Before changing again:"+f.get(0).getName()+"-->"+f.get(0).getPrice());
        System.out.println("After another change:"+fruits_new2.get(0).getName()+"-->"+fruits_new2.get(0).getPrice());
    }
}
Before change: apple-->1.46
 After modification: apple-->11.46
 Before changing again: apple-->21.46
 After another change: apple-->21.46

To change the way of the original collection, you can use the following writing method (peek, which does not need to return the objects in the list like map):

//Change the way the original set
List<Fruit> fruits_new2=f.stream().peek(Fruit-> Fruit.setPrice(Fruit.getPrice().add(new BigDecimal("20")))).collect(Collectors.toList());
System.out.println("Before changing again:"+f.get(0).getName()+"-->"+f.get(0).getPrice());
System.out.println("After another change:"+fruits_new2.get(0).getName()+"-->"+fruits_new2.get(0).getPrice());
//The effect is the same:
Before changing again: apple-->21.46
 After another change: apple-->21.46

Example 3: combine two character arrays into a new character array.

import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.List;
import java.util.Arrays;

List<String> l=Arrays.asList("x,i,x,u","1,4,7,8");
List<String> l_new = l.stream().flatMap(s->{
	String[] spl=s.split(",");
	Stream<String> s2=Arrays.stream(spl);
	return s2;
}).collect(Collectors.toList());
System.out.println("Collection before processing:"+l);
System.out.println("Processed collection:"+l_new);
Collection before processing:[x,i,x,u, 1,4,7,8]
Processed collection:[x, i, x, u, 1, 4, 7, 8]

1.5 reduce

Reduction, also known as reduction, can reduce a stream to a value, and can realize the operations of summation, product and maximization of sets.

Example 1: find the sum, product and maximum of the elements of the Integer set

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


List<Integer> i= Arrays.asList(1,5,8,7,9,10,13);
//Summation method 1
Optional<Integer> o=i.stream().reduce((x,y)->x+y);
//Summation method 2
Optional<Integer> o1=i.stream().reduce(Integer::sum);
//Summation method 3
Integer o2=i.stream().reduce(0,Integer::sum);
System.out.println(o.get());
System.out.println(o1.get());
System.out.println(o2);
53
53
53

Example 2: find the sum of the prices of all fruits and the highest price

Sum of all prices:

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("12"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("7"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));
//1
Optional<BigDecimal> o1=f.stream().map(Fruit::getPrice).reduce((x,y)->x.add(y));
System.out.println(o1.get());
11.56
//2
Optional<BigDecimal> o1=f.stream().map(Fruit::getPrice).reduce(BigDecimal::add);
System.out.println(o1.get());
11.56

Maximum value:

Optional<BigDecimal> max1=f.stream().map(Fruit::getPrice).reduce((x,y)->x.compareTo(y)>0?x:y);
System.out.println(max1.get());
4

1.6 collect

It can be collected into a value or a new collection.

collect mainly relies on the built-in static methods of the java.util.stream.Collectors class

1.6.1 collection (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 re collected into a new set. Common uses include toList/toSet/toMap, toCollection \ tocurrentmap and other complex uses.

The usage of toList/toSet/toMap is as follows:
First override the toString method of the Fruit class to print the Fruit object:

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

List<Integer> i=Arrays.asList(1,5,4,8,4);
List<Integer> new_i=i.stream().filter(x->x%2==0).collect(Collectors.toList());
Set<Integer> new_set=i.stream().filter(x->x%2==0).collect(Collectors.toSet());
List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("12"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("7"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));

Map<?,Fruit> m=f.stream().filter(fr->fr.getPrice().compareTo(new BigDecimal("2"))>0)
     .collect(Collectors.toMap(Fruit::getName,x->x));

System.out.println("toList:"+new_i);
System.out.println("toSet:"+new_set);
System.out.println("toMap:"+m);
toList:[4, 8, 4]
toSet:[4, 8]
toMap:{banana=Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}, pear=Fruit{name='pear', price=4, number=7, total=15, RealPrice=3.2}}

1.6.2 Statistics (count/averaging)

Collectors provide a series of static methods for data statistics:

Count: count
Average value: averagingInt, averagingLong, averagingDouble
Max value: maxBy, minBy
Summation: summerint, summerlong, summerdouble
Statistics of all the above: summarizingInt, summarizingLong, summarizingDouble

Example: count the number of types, average data, average real price, average price, total price and maximum price of fruits

List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("12"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("7"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));

//List total
long count=f.stream().collect(Collectors.counting());
long count1=f.stream().count();
long count2=f.size();
System.out.print(count+" "+count1+" "+count2+"\n");
//Find the average value of total quantity \ average value of real price \ average value of price (BigDecimal)
Double average_total=f.stream().collect(Collectors.averagingInt(Fruit::getTotal));
Double average_real_price=f.stream().collect(Collectors.averagingDouble(Fruit::getRealPrice));
System.out.println(average_real_price);
System.out.println(average_total);
f.stream().map(Fruit::getPrice).mapToDouble(BigDecimal::doubleValue).average().ifPresent(
System.out::println
);
//Sum the price, total and price
//BigDecimal sums with reduce
BigDecimal sum=f.stream().map(Fruit::getPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
//int, double, etc. you can use collect (collectors. Summerint()) or summerdouble
Double real_price_sum = f.stream().collect(Collectors.summingDouble(Fruit::getRealPrice));
int total_sum = f.stream().collect(Collectors.summingInt(Fruit::getTotal));
System.out.println("BigDecimal the sum:"+sum);
System.out.println("Double the sum:"+real_price_sum);
System.out.println("int the sum:"+total_sum);
//Seeking the highest price 1.2.3
Optional<BigDecimal> max_price=f.stream()
.map(Fruit::getPrice)
.collect(Collectors.maxBy((x,y)->x.compareTo(y)));
Optional<BigDecimal> max_price2=f.stream()
.map(Fruit::getPrice).max(BigDecimal::compareTo);
Optional<BigDecimal> max_price3=f.stream()
.map(Fruit::getPrice)
.collect(Collectors.maxBy(BigDecimal::compareTo));
System.out.println(max_price.get());
System.out.println(max_price2.get());
System.out.println(max_price3.get());
//One time statistics of all information
DoubleSummaryStatistics d= f.stream().collect(Collectors.summarizingDouble(Fruit::getRealPrice));
System.out.println("Statistics of all information:"+d);
5 5 5
1.766
21.8
2.3120000000000003
BigDecimal Total: 11.56
Double Total: 8.83
int Total: 109
4
4
4
 Statistics of all information: DoubleSummaryStatistics{count=5, sum=8.830000, min=0.600000, average=1.766000, max=3.200000}

1.6.3 grouping (partitioningBy/groupingBy)

Partition: divide the stream into two maps according to conditions, such as whether the fruit price is higher than 2

Grouping: divide the set into multiple maps. For example, fruits are grouped by number. There are single-level and multi-level grouping.

List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("5"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("15"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));

//Divided into two parts according to whether the fruit price is higher than 2
Map<Boolean,List<Fruit>> m=f.stream()
.collect(Collectors.partitioningBy(x->x.getPrice().compareTo(new BigDecimal("2"))>0));
//Group by fruit number
Map<BigInteger,List<Fruit>> m1=f.stream()
.collect(Collectors.groupingBy(Fruit::getNumber));
//Group by number first, and then by total
Map<BigInteger,Map<Integer,List<Fruit>>> m2=f.stream()
.collect(Collectors.groupingBy(Fruit::getNumber,
Collectors.groupingBy(Fruit::getTotal)));
System.out.println("Whether the fruit price is higher than 2:"+m);
System.out.println("Group by fruit number:"+m1);
System.out.println("First by number, then by total grouping:"+m2);
Whether the fruit price is higher than 2:{false=[Fruit{name='apple', price=1.46, number=15, total=40, RealPrice=1.23}, Fruit{name='watermelon', price=1.1, number=5, total=10, RealPrice=0.6}, Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}], true=[Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}, Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}]}
Group by fruit number:{5=[Fruit{name='watermelon', price=1.1, number=5, total=10, RealPrice=0.6}, Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}], 15=[Fruit{name='apple', price=1.46, number=15, total=40, RealPrice=1.23}, Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}, Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}]}
First by number, then by total grouping:{5={20=[Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}], 10=[Fruit{name='watermelon', price=1.1, number=5, total=10, RealPrice=0.6}]}, 15={24=[Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}], 40=[Fruit{name='apple', price=1.46, number=15, total=40, RealPrice=1.23}], 15=[Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}]}}

1.6.4 joining

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

List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("5"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("15"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));

String names = f.stream().map(Fruit::getName).collect(Collectors.joining(";"));
System.out.println(names);
List<String> s=Arrays.asList("a","y","t");
String s1=s.stream().collect(Collectors.joining("-"));
String s2= String.join("-", s);
System.out.println(s1);
System.out.println(s2);
apple;watermelon;peach;pear;banana
a-y-t
a-y-t

1.6.5 reducing

Compared with the reduce method of stream itself, the reducing method provided by the Collectors class adds support for custom reduction.

List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("1.46"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("1.1"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("5"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("15"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));

//The sum of all the reduced prices of each fruit
//1. Use the reducing () method of the Collectors class
BigDecimal sum_sub1=f.stream().collect(Collectors.reducing(new BigDecimal("0"),Fruit::getPrice,(x,y)->x.add(y).subtract(new BigDecimal("1"))));
//2. Use the reduce() method of stream
BigDecimal sum_sub2= f.stream().map(Fruit::getPrice).reduce(new BigDecimal("0"), (x, y) -> x.add(y).subtract(new BigDecimal("1")));
System.out.println(sum_sub1);
System.out.println(sum_sub2);
6.56
6.56

1.7 sorted

sorted, intermediate operation. There are two sorts:

sorted (): sort naturally. Elements in the stream need to implement the Comparable interface

sorted (Comparator c): Comparator sorter custom sorting

Sort by fruit price in ascending / descending order

//The data are as follows
List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("2"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("4"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("5"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("15"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));
//1. Sorting and Collectors.toMap cannot be used together, and sorting will be invalid
//Redundant 'sorted' call: subsequent 'toMap' call doesn't depend on the sort order 
Map<String,BigDecimal> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice))
        .collect(Collectors.toMap(Fruit::getName,Fruit::getPrice));
System.out.println("sort sorted and Collectors.toMap Use together:"+m);
sort sorted and Collectors.toMap Use together:{banana=3, apple=2, pear=4, peach=2, watermelon=4}
//2. Sort by price increment
List<Fruit> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice))
        .collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
//2.1 sort according to the ascending order of price to obtain the name of fruit
List<String> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice)).map(Fruit::getName)
        .collect(Collectors.toList());
System.out.println(m);
[apple, peach, banana, watermelon, pear]
//3. Sort by price in reverse order
List<Fruit> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice).reversed())
        .collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
//4.1 sort according to the ascending order of price first, and then sort according to the reverse order of quantity total
List<Fruit> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice).reversed().thenComparing(Fruit::getTotal).reversed())
        .collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
//4.2 sort in reverse order of price first, and then sort in reverse order of quantity total
List<Fruit> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice).thenComparing(Fruit::getTotal).reversed())
        .collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
//4.3 sort according to the price in reverse order, and then sort according to the quantity total in ascending order
List<Fruit> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice).reversed().thenComparing(Fruit::getTotal))
        .collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
//4.4 sort by price first, and then by total
List<Fruit> m=f.stream().sorted(Comparator.comparing(Fruit::getPrice).thenComparing(Fruit::getTotal))
        .collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}

Note: in the above special cases, only using reversed() at the end means that the two fields are in reverse order. If you want to increase the order of the first field and reverse the order of the second field, add. Reversed after comparing and thenComparing

Custom sorting:

//User defined sorting 5.1 sort by price increment first, and then sort by quantity total in reverse order
List<Fruit> m=f.stream().sorted((v1,v2)->{
    if(Objects.equals(v1.getPrice(), v2.getPrice())){
        return -(v1.getTotal()-v2.getTotal());
    }else{
        return v1.getPrice().compareTo(v2.getPrice());
    }
}).collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
//User defined sorting 5.2 first sort by price in reverse order, and then sort by quantity total in reverse order
List<Fruit> m=f.stream().sorted((v1,v2)->{
    if(Objects.equals(v1.getPrice(), v2.getPrice())){
        return -(v1.getTotal()-v2.getTotal());
    }else{
        return -v1.getPrice().compareTo(v2.getPrice());
    }
}).collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
//Custom sorting 5.3 sort by price in reverse order, and then sort by total in ascending order
List<Fruit> m=f.stream().sorted((v1,v2)->{
    if(Objects.equals(v1.getPrice(), v2.getPrice())){
        return (v1.getTotal()-v2.getTotal());
    }else{
        return -v1.getPrice().compareTo(v2.getPrice());
    }
}).collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
//Custom sorting 5.4 sort by price first, and then by total
List<Fruit> m=f.stream().sorted((v1,v2)->{
    if(Objects.equals(v1.getPrice(), v2.getPrice())){
        return (v1.getTotal()-v2.getTotal());
    }else{
        return v1.getPrice().compareTo(v2.getPrice());
    }
}).collect(Collectors.toList());
m.forEach(System.out::println);
Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}

1.8 extraction / combination

Streams can be merged, de duplicated, restricted, and skipped.

Note: Stream.of involves reusing streams:

String[] a={"a","b","c","c","d"};
String[] b={"e","e","f","W"};
Stream<String> x1=Stream.of(a);
Stream<String> x2=Stream.of(b);
//concat: merge two streams distinct: de duplication
List<String> l1=Stream.concat(x1,x2).collect(Collectors.toList());
List<String> l2=Stream.concat(x1,x2).distinct().collect(Collectors.toList());
System.out.println(l1);
System.out.println(l2);


Because the above streams have been used in l1, the following will throw an error if x1 and x2 streams are used again. The solution is as follows:
The Supplier interface produces a result of a given type. Unlike Function, Supplier has no input parameters.

String[] a={"a","b","c","c","d"};
String[] b={"e","e","f","W"};
//Stream<String> x1=Stream.of(a);
//Stream<String> x2=Stream.of(b);
Supplier<Stream<String>> y1=()->Stream.of(a);
Supplier<Stream<String>> y2=()->Stream.of(b);
//concat: merge two streams distinct: de duplication
List<String> l1=Stream.concat(y1.get(),y2.get()).collect(Collectors.toList());
List<String> l2=Stream.concat(y1.get(),y2.get()).distinct().collect(Collectors.toList());
System.out.println(l1);
System.out.println(l2);
[a, b, c, c, d, e, e, f, W]
[a, b, c, d, e, f, W]
//Limit: limit the first n data obtained from the stream
List<Integer> l3=Stream.iterate(1,x->x+3).limit(3).collect(Collectors.toList());
System.out.println(l3);
//Skip: skip the first n data
List<Integer> l4=Stream.iterate(3,x->x+2).skip(2).limit(5).collect(Collectors.toList());
System.out.println(l4);
[1, 4, 7]
//It started from 3 and skipped 3 and 5, so it started from 7
[7, 9, 11, 13, 15]

tips:idea shortcut key output system. Err. Println(); = > serr

1.9 practice

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;
List<Fruit> f=new ArrayList<>();
f.add(new Fruit("apple",new BigDecimal("2"),new BigInteger("15"),40,1.23));
f.add(new Fruit("watermelon",new BigDecimal("4"),new BigInteger("5"),10,0.6));
f.add(new Fruit("peach",new BigDecimal("2"),new BigInteger("5"),20,1.8));
f.add(new Fruit("pear",new BigDecimal("4"),new BigInteger("15"),15,3.2));
f.add(new Fruit("banana",new BigDecimal("3"),new BigInteger("15"),24,2));
//Group Collectors.groupingBy, and the value of map is List
Map<BigInteger,List<Fruit>> m=f.stream().collect(Collectors.groupingBy(Fruit::getNumber));
System.err.println(m);
//If you want the value of the map to be a separate object, use Collectors.toMap, but pay attention to the Duplicate key error
Map<BigInteger,Fruit> m1=f.stream().collect(Collectors.toMap(Fruit::getNumber,x->x));
System.err.println(m1);

//Modified as above
//If you want the value of the map to be a separate object, use Collectors.toMap, but pay attention to the Duplicate key error
//(K1, K2) - > K1) indicates a duplicate key. Just take the first K1
Map<BigInteger,Fruit> m1=f.stream().collect(Collectors.toMap(Fruit::getNumber,x->x,(k1,k2)->k1));
System.err.println(m1);

//Sum
BigDecimal total_price=f.stream().map(Fruit::getPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
System.err.println("And:"+total_price);
And: 15
//maxBy: there are more than one max, and only the first one will be taken, so this can't be done (multiple Max needs to be considered)
Optional<Fruit> max_price_fruit=f.stream().collect(Collectors.maxBy(Comparator.comparing(Fruit::getPrice)));
Optional<Fruit> max_price_fruit2= f.stream().max(Comparator.comparing(Fruit::getPrice));
System.err.println(max_price_fruit.get());
System.err.println(max_price_fruit2.get());
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}
System.out.println("duplicate removal:");
//duplicate removal
List<Fruit> unique = f.stream().collect(
        Collectors.collectingAndThen(Collectors.toCollection(()->new TreeSet<>(Comparator.comparing(Fruit::getPrice))),ArrayList::new)
);
unique.forEach(System.err::println);
duplicate removal:
Fruit{name='apple', price=2, number=15, total=40, RealPrice=1.23}
Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}
Fruit{name='watermelon', price=4, number=5, total=10, RealPrice=0.6}

The above de duplication methods are sorted from small to large according to the price, and the repeated price is directly removed and only one value is taken.

Static factory method of Collectors class (structure: factory method + return type + action):

toList: List < >: collect all items in the stream into a list

toSet: Set < T >: collect all items in the stream into a Set and delete duplicates

toCollection: Collection < T >: collect all items in the stream to the collection created by the given supply source, fruitStream.collect(Collectors.toCollection(),ArrayList::new)

counting: Long: counts the number of elements in the stream

summingInt: Integer: sums an Integer attribute of an item in the stream

Averaging int: Double: calculates the average value of the Integer attribute of the item in the flow

summarizingInt: IntSummaryStatistics(java.util.IntSummaryStatistics): collects statistics about the Integer attribute of items in the flow, such as maximum, minimum, sum and average

Joining: String: the string collection (joining (",")) generated by calling the toString method for each item in the connection stream

maxBy: Optional < T >: an Optional that wraps the largest element selected according to the given comparator in the stream, or Optional.empty() if the stream is empty

Minby (maxby above)

reducing: type generated by reduction operation: starting from an initial value as an accumulator, BinaryOperator is used to combine the elements in the stream one by one, so as to reduce the stream to a single value accumulation

collectingAndThen: the type returned by the conversion function: wrap another collector, and apply the conversion function int howManySize=Fstream.collect(collectingAndThen(toList(),List::size)) to its result

int l=f.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size));
System.out.println(l);
5

groupingBy: Map < K, list < T > >: group items in the stream according to the value of an attribute of the item, and take the attribute value as the key of the result map

partitioningBy: Map < Boolean, list < T > >: partition items according to the result of applying predicates to each item in the stream

Refer to the previous example:

//Divided into two parts according to whether the fruit price is higher than 2
Map<Boolean,List<Fruit>> m=f.stream()
.collect(Collectors.partitioningBy(x->x.getPrice().compareTo(new BigDecimal("2"))>0));
System.out.println("Whether the fruit price is higher than 2:"+m);
Whether the fruit price is higher than 2:{false=[Fruit{name='apple', price=1.46, number=15, total=40, RealPrice=1.23}, Fruit{name='watermelon', price=1.1, number=5, total=10, RealPrice=0.6}, Fruit{name='peach', price=2, number=5, total=20, RealPrice=1.8}], true=[Fruit{name='pear', price=4, number=15, total=15, RealPrice=3.2}, Fruit{name='banana', price=3, number=15, total=24, RealPrice=2.0}]}

2.0

Call the Stream api to perform the following operations:

Deferred method: after this kind of method is called, a new Stream object will be returned and no business operations will be performed
filter – enables data filtering
map – flows from one data type to another
Skip – skip the first few
limit – take the first few
Stream.concat() – merge stream objects

Termination method: after calling this kind of method, the Stream stream object will not be returned, and all previous business operations will be triggered
forEach -- implement traversal
Count – implement count
collect – re convert the data in the stream to a collection

Keywords: Java

Added by Dookster on Mon, 25 Oct 2021 08:59:48 +0300