The application of Stream stream, a new feature of java8

Keywords: Java Apache

As a qualified programmer, how to make the code more concise and clear, and improve the coding speed.

Today, follow me to learn the application of java 8 stream.

Don't talk much nonsense, go straight to the point.

Considering the following business scenario, there are four personnel information, and we need to count the names of personnel according to their gender.

package com;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {
    public static void main(String[] args) {

        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("userName", "Zhang San");
        map.put("age", "18");
        map.put("sex", "male");
        list.add(map);

        Map<String, String> map1 = new HashMap<>();
        map1.put("userName", "Li Si");
        map1.put("age", "20");
        map1.put("sex", "female");
        list.add(map1);

        Map<String, String> map2 = new HashMap<>();
        map2.put("userName", "Wang Wu");
        map2.put("age", "15");
        map2.put("sex", "female");
        list.add(map2);

        Map<String, String> map3 = new HashMap<>();
        map3.put("userName", "Ruofeng");
        map3.put("age", "23");
        map3.put("sex", "male");
        list.add(map3);

        //Now we're going to count people by gender
        //Primary writing
        StringBuilder stringBuilder1 = new StringBuilder();
        StringBuilder stringBuilder2 = new StringBuilder();
        for (Map<String, String> item : list) {
            //map pointing to the current subscript
            System.out.println("item: " + item);
            if (item.get("sex").equals("male")) {
                //Names of persons with gender as male, separated by commas
                stringBuilder1.append(item.get("userName")).append(",");
            } else {
                //Names of persons with gender as female, separated by commas
                stringBuilder2.append(item.get("userName")).append(",");
            }
        }
        //Remove the last comma
        String userName_nan = stringBuilder1.deleteCharAt(stringBuilder1.length() - 1).toString();
        String userName_nv = stringBuilder2.deleteCharAt(stringBuilder2.length() - 1).toString();
        System.out.println("userName_nan: " + userName_nan);
        System.out.println("userName_nv: " + userName_nv);
    }
}

The printing records are as follows:

 

Does it feel that the code is not very elegant? Then we start to change our posture and use java8 Stream flow to operate.

package com;

import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {
    public static void main(String[] args) {

        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("userName", "Zhang San");
        map.put("age", "18");
        map.put("sex", "male");
        list.add(map);

        Map<String, String> map1 = new HashMap<>();
        map1.put("userName", "Li Si");
        map1.put("age", "20");
        map1.put("sex", "female");
        list.add(map1);

        Map<String, String> map2 = new HashMap<>();
        map2.put("userName", "Wang Wu");
        map2.put("age", "15");
        map2.put("sex", "female");
        list.add(map2);

        Map<String, String> map3 = new HashMap<>();
        map3.put("userName", "Ruofeng");
        map3.put("age", "23");
        map3.put("sex", "male");
        list.add(map3);

        //Now we're going to count people by gender
        //Primary writing
//        StringBuilder stringBuilder1 = new StringBuilder();
//        StringBuilder stringBuilder2 = new StringBuilder();
//        for (Map<String, String> item : list) {
//            //map pointing to the current subscript
//            System.out.println("item: " + item);
//            if (item.get("sex").equals("men"){
//                //Names of persons with gender as male, separated by commas
//                stringBuilder1.append(item.get("userName")).append(",");
//            } else {
//                //Names of persons with gender as female, separated by commas
//                stringBuilder2.append(item.get("userName")).append(",");
//            }
//        }
//        //Remove the last comma
//        String userName_nan = stringBuilder1.deleteCharAt(stringBuilder1.length() - 1).toString();
//        String userName_nv = stringBuilder2.deleteCharAt(stringBuilder2.length() - 1).toString();
//        System.out.println("userName_nan: " + userName_nan);
//        System.out.println("userName_nv: " + userName_nv);

        //The writing method of java8 stream
        //First, define a Map to store the names of our personnel
        Map<String, String> userNameMap = new HashMap<>(4);
        //Start acting
        //
        list.stream().map(v1 -> {
            //Map can be understood as a new object. copy the data of the original List to a new List. When using map to modify the data, the original object will not be changed. Return value required!!!
            //v1 points to the map object of the current subscript
            System.out.println("v1: " + v1);
            //Define a new map to store people's names and gender
            Map<String, String> data = new HashMap<>();
            map.put("userName", v1.get("userName"));
            map.put("sex", v1.get("sex"));
            return map;
        }).reduce(userNameMap, (a, b) -> {
            //a can be understood as the return result of the last cycle
            //Bcurrent loop o b ject
            //Get the name of the person in the current cycle
            String thisUserName = b.get("userName");
            //Take out the gender of the person in the current cycle
            String thisSex = b.get("sex");
            if (thisSex.equals("male")) {
                //Take the return result of the last cycle. The first cycle has no value. The second cycle gets the return result of the first cycle, and so on.
                String val = a.get("newMenUserName");
                System.out.println("val: " + val);
                //In the first loop, val has no value. We assign an empty string,
                // In the second cycle, take out the value of newUserName returned by the first cycle, and add comma to splice the name of the current subscript
                String newUserName = (StringUtils.isBlank(val) ? StringUtils.EMPTY : val + ",") + thisUserName;
                //Add the spliced person name to the map
                System.out.println("newUserName: " + newUserName);
                a.put("newMenUserName", newUserName);
            } else {
                //Take the return result of the last cycle. The first cycle has no value. The second cycle gets the return result of the first cycle, and so on.
                String val = a.get("newWomenUserName");
                System.out.println("val: " + val);
                //In the first loop, val has no value. We assign an empty string,
                // In the second cycle, take out the value of newUserName returned by the first cycle, and add comma to splice the name of the current subscript
                String newUserName = (StringUtils.isBlank(val) ? StringUtils.EMPTY : val + ",") + thisUserName;
                System.out.println("newUserName: " + newUserName);
                //Add the spliced person name to the map
                a.put("newWomenUserName", newUserName);
            }
            //Returns the map of the current loop
            return a;
        });
        System.out.println("userNameMap: " + userNameMap);
        System.out.println("userName_nan: " + userNameMap.get("newMenUserName"));
        System.out.println("userName_nv: " + userNameMap.get("newWomenUserName"));

    }
}

The printed values are as follows:

 

Scenario 2. Take the intersection of two lists

package com;

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

public class Test {
    public static void main(String[] args) {

//        Business scenario 2: take out two List Element with the same value (intersection)
        List<Integer> list1=new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        List<Integer> list2=new ArrayList<>();
        list2.add(2);
        list2.add(4);
        //intersection
        List<Integer> list3=new ArrayList<>();
        //Primary writing
        for(Integer item:list1){
            if(list2.contains(item)){
                list3.add(item);
            }
        }
        System.out.println("for The result of the cycle");
        System.out.println("list3: "+list3);

        System.out.println("------------------------------------------------------------");

        //stream The writing method of flow
        //v1 Object representing the current subscript
        //filter  The filtering result is false Data for
        list3=list1.stream().filter(v1->list2.contains(v1)).collect(Collectors.toList());
        System.out.println("stream The result of the cycle");
        System.out.println("list3: "+list3);

        //list Own approach
        System.out.println("------------------------------------------------------------");
        System.out.println("old Data, list1: "+list1);
        System.out.println("old Data, list2: "+list2);
        list1.retainAll(list2);
        System.out.println("new Data, list1"+list1);
        System.out.println("new Data, list2"+list2);
    }
}

Print results:

 

Scenario 3. Sorting a List

package com;

import java.util.*;
import java.util.stream.Collectors;

public class Test {
    public static void main(String[] args) {

//        Business scenario 3: sorting List
        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("userName", "Zhang San");
        map.put("age", "18");
        map.put("sex", "male");
        list.add(map);

        Map<String, String> map1 = new HashMap<>();
        map1.put("userName", "Li Si");
        map1.put("age", "20");
        map1.put("sex", "female");
        list.add(map1);

        Map<String, String> map2 = new HashMap<>();
        map2.put("userName", "Wang Wu");
        map2.put("age", "15");
        map2.put("sex", "female");
        list.add(map2);

        Map<String, String> map3 = new HashMap<>();
        map3.put("userName", "Ruofeng");
        map3.put("age", "23");
        map3.put("sex", "male");
        list.add(map3);


        //The writing method of stream stream
        System.out.println("------------------------Before sorting--------------------------------");
        System.out.println("Before sorting,List :"+list);
        //sorted stream, where we sort by age and name
        //In Test::age Java 8, we can use the ':' keyword to access class construction methods, object methods, and static methods.
        //Start acting
        List<Map<String, String>> list2=list.stream().sorted(Comparator.comparing(Test::age).thenComparing(Comparator.comparing(Test::userName))).collect(Collectors.toList());
        System.out.println();
        System.out.println("------------------------After sorting--------------------------------");
        System.out.println("After sorting,list2 :"+list2);
    }
    private static String userName(Map<String,String> map){
        return map.get("userName");
    }
    private static Integer age(Map<String,String> map){
        return Integer.parseInt(map.get("age"));
    }
}

Print results:

 

 

Summary:

1. Stream stream is not a data structure and does not save data. It only defines a set of operations on the original dataset.
2. These operations are lazy, that is, each time an element in the flow is accessed, this series of operations will be performed on this element.
3. Streams do not save data, so each Stream can only be used once.
A stream can be divided into two parts: intermediate and terminal. The return results of the intermediate operations are all Stream, so multiple intermediate operations can be overlapped; the termination operation is used to return the data we ultimately need, and there can only be one termination operation!!!
1, Intermediate method of stream (intermediate operation)
1,filter(Predicate)
Filter out the element whose result is false. It will not change the data of the original object. You need to display the specified return value!!!
2,map(fun)
copy the object to a new object, traverse the new object, modify the data will not change the original object data, need to display the specified return value!!!
3,flatMap(fun)
If the element is a flow, flatten the flow to a normal element, and then convert the element
4,limit(n)
Keep the first n elements
5, skip(n)
Skip the first n elements
6,distinct()
Eliminate duplicate elements
7,sorted(Comparator)
Sort flow elements by Comparator
8,peek(fun)
The flow does not change, but each element is passed into the fun for execution, which can be used as debugging
9,forEach()
Traversing the current object and modifying the data will change the data of the object without displaying the specified return value!!! (note the difference with map)
2, Terminal method of stream (end operation)
Reduction operation
1,max(Comparator)  
Take the maximum value
2,min(Comparator)   
Take the minimum value
3, count()         
Go and
4,findFirst()
Returns the first element
5, findAny()
Return any element
6,anyMatch(Predicate)
Returns true when any element matches
7,allMatch(Predicate)
Returns true when all elements match
8,noneMatch(Predicate)
Returns true when no element matches
9,reduce(fun)
Calculate a value from the flow, accept a binary function as the accumulator, apply it continuously from the first two elements, the middle result of the accumulator as the first parameter, and the flow element as the second parameter
10, reduce(a, fun)
a is the unitary value as the starting point of the accumulator
11,reduce(a, fun1, fun2)
        Similar to binary deformation, in concurrent operation, when the first and second parameters of the accumulator are of flow element type, the accumulator can also be used to merge the intermediate results, but when the first parameter of the accumulator is not of flow element type but of type T, the intermediate results are also of type T, and fun2 is required to merge the intermediate results (refer to) Scenario 1)
3, Collection operation of stream stream:
1,Collectors.toList()
Return a List
2,Collectors.toSet()
Returns a collection
3. Collectors.tocollection (constructor reference to collection)
4,Collectors.joining(),Collectors.joining(delimiter),Collectors.joining(delimiter,prefix,suffix)
String element connection
5,Collectors.summarizingInt/Long/Double(ToInt/Long/DoubleFunction)
Generate the Int/Long/DoubleSummaryStatistics object, which has getCount, getSum, getMax, getMin methods. Note that when there is no element, getMax and getMin return integer / long / double.max/min'value
6,Collectors.toMap(fun1, fun2)/toConcurrentMap
Two funs are used to generate keys and values. If the value is the element itself, fun2 is Function.identity()
7,Collectors.toMap(fun1, fun2, fun3)/toConcurrentMap
fun3 is used to resolve key conflicts, for example (oldvalue, newvalue) - > oldvalue, keep the original value when there is a conflict
8,Collectors.toMap(fun1, fun2, fun3, fun4)/toConcurrentMap
By default, HashMap or ConcurrentHashMap is returned. fun4 can specify the returned Map type, which is the corresponding constructor argument
9,Collectors.groupingBy(fun)/groupingByConcurrent(fun)
Fun is the classification function, generate Map, key is the result of fun function, value is the list with the same result element of fun function
10,Collectors.partitioningBy(fun)
The key is true/false, which is more efficient than groupingBy(fun) when fun is an assertion function
11,Collectors.groupingBy(fun1, fun2)
Fun2 is a downstream collector, which can convert the list to other forms, such as toSet(), counting(), summingInt/Long/Double(fun), maxBy(Comparator), minBy(Comparator), mapping(fun1, fun2)(fun1 is the conversion function, fun2 is the downstream collector)

Reference: https://blog.csdn.net/lixiaobuaa/article/details/81099838
This blog is for learning reference only

Posted by sajidfiaz on Sat, 16 May 2020 07:12:15 -0700