Learn Java8 Stream stream operation once [Figure]!

 

Stream operation is a new feature of JAVA8, which has better performance for collection operations.

First understand the concept of operators.

What is an operator? The operator is a kind of processing work on the data, a processing procedure; just like a factory worker performs a processing procedure on the products on the assembly line.

Stream operators are generally divided into two types: intermediate operators and termination operators

intermediate operator

For data flow, after the intermediate operator executes the specified processing program, the data flow can still be passed to the next-level operator.

There are 8 intermediate operators (parallel and sequential are excluded, these two operations do not involve the processing of data streams):

  • map(mapToInt, mapToLong, mapToDouble) conversion operator, such as A->B, here provides operators for converting int, long and double by default.

  • flatmap(flatmapToInt,flatmapToLong,flatmapToDouble) The flatmap operation such as flattening int[]{2,3,4} into 2, 3, 4 means from the original one data to three data, which is provided by default here Slap into int, long, double operators.

  • limit Current limiting operation, for example, if there are 10 in the data stream, I only need to get the first 3 to use.

  • distint deduplication operation, deduplication of repeated elements, the bottom layer uses the equals method.

  • filter Filter operation, filter unwanted data.

  • peek Pick out the operation, if you want to perform certain operations on the data, such as: read, edit and modify, etc.

  • skip skip operation, skip some elements.

  • sorted(unordered) sorting operation, sorting elements, the premise is to implement the Comparable interface, of course, you can also customize the comparator.

termination operator

After the data has undergone intermediate processing operations, it is the turn of the termination operator to play; the termination operator is used to collect or consume data, and the data will not flow downward after the termination operation, and the termination operator can only be used once.

  • Collect collects all data. This operation is very important. The official Collectors provide a lot of collectors. It can be said that the core of Stream lies in Collectors.

  • count Statistical operation, counting the final number of data.

  • findFirst, findAny Search operations, find the first, find any return type is Optional.

  • noneMatch, allMatch, anyMatch match operation, whether there is a qualified element in the data stream, the return value is a bool value.

  • Min and max are the most value operations, which require a custom comparator to return the maximum and minimum values ​​in the data stream.

  • The reduce reduction operation reduces the value of the entire data stream to one value, and the bottom layer of count, min, and max uses reduce.

  • forEach, forEachOrdered traversal operation, here is to consume the final data.

  • toArray Array operation, convert the elements of the data stream into an array.

Only Stream is introduced here, and IntStream, LongStream, and DoubleStream are not involved. These three streams implement some unique operators, which I will introduce in subsequent articles. Reply to "Aggregation of Interview Questions" in the JavaMissence official account, and send you a collection of interviews from major companies.

Having said all that, it's not enough to just introduce these operators; as the saying goes, practice makes the truth. Well, Let's go.

code walkthrough

A series of Stream operations must use the termination operation, otherwise the entire data stream will not flow, that is, the processing operation will not be executed.

  • map, you can see that the map operator requires the input of a Function function is an interface instance, and the function is to convert the T type to the R type.

The map operation converts the original word into the length of each word, using the length() method of String itself, which returns an int. Here I directly use lambda expressions. Readers are welcome to understand lambda expressions by themselves.

public class Main {

    public static void main(String[] args) {
        Stream.of("apple","banana","orange","waltermaleon","grape")
                .map(e->e.length()) //转成单词的长度 int
                .forEach(e->System.out.println(e)); //输出
    }
}

Of course, this is also possible. Member function references are used here. For the convenience of readers, lambda expressions will be used instead of function references in subsequent examples.

public class Main {

    public static void main(String[] args) {
         Stream.of("apple","banana","orange","waltermaleon","grape")
                .map(String::length) //转成单词的长度 int
                .forEach(System.out::println);
    }
}

The result is shown in the figure:

  • mapToInt converts the elements in the data stream to Int, which limits the type of conversion to Int, and the final stream is IntStream, and the result can only be converted to int.

 

 

public class Main {

    public static void main(String[] args) {
         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToInt(e -> e.length()) //转成int
                .forEach(e -> System.out.println(e));
    }
}

mapToInt as shown in the figure:

  • mapToLong, mapToDouble are similar to mapToInt

public class Main {

    public static void main(String[] args) {
         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToLong(e -> e.length()) //转成long ,本质上是int 但是存在类型自动转换
                .forEach(e -> System.out.println(e));
    }
}

mapToLong as shown in the figure:

public class Main {

    public static void main(String[] args) {
         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToDouble(e -> e.length()) //转成Double ,自动类型转换成Double
                .forEach(e -> System.out.println(e));
    }
}

mapToDouble is shown in the figure:

  • The function of flatmap is to flatten the elements, reorganize the flattened elements into a Stream, and merge these Streams serially into a Stream

 

public class Main {

    public static void main(String[] args) {
        Stream.of("a-b-c-d","e-f-i-g-h")
                .flatMap(e->Stream.of(e.split("-")))
                .forEach(e->System.out.println(e));

    }
}

flatmap as shown in the figure:

  • flatmapToInt, flatmapToLong, flatmapToDouble are similar to flatMap, but the type is limited, so I won’t give an example here.

  • limit limits the number of elements, just pass in the long type to indicate the maximum number of limits

public class Main {

    public static void main(String[] args) {
        Stream.of(1,2,3,4,5,6)
                .limit(3) //限制三个
                .forEach(e->System.out.println(e)); //将输出 前三个 1,2,3
    }
}

limit as shown in the figure:

public class Main {

    public static void main(String[] args) {

        Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
                .distinct() //去重
                .forEach(e->System.out.println(e));

    }
}

distinct as shown in the figure:

  • filter Filters certain elements, and those that do not meet the filter conditions will not be able to enter the downstream of the stream

public class Main {

    public static void main(String[] args) {
        Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
                .filter(e->e>=5) //过滤小于5的
                .forEach(e->System.out.println(e));
    }
}

filter as shown in the figure:

  • peek selection, pick out elements, can be understood as consumption in advance

public class Main {

    public static void main(String[] args) {

        User w = new User("w",10);
        User x = new User("x",11);
        User y = new User("y",12);

        Stream.of(w,x,y)
                .peek(e->{e.setName(e.getAge()+e.getName());}) //重新设置名字 变成 年龄+名字
                .forEach(e->System.out.println(e.toString()));

    }

    static class User {

        private String name;

        private int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

peek as shown in the figure:

  • skip skip elements

public class Main {

    public static void main(String[] args) {
        Stream.of(1,2,3,4,5,6,7,8,9)
                .skip(4) //跳过前四个
                .forEach(e->System.out.println(e)); //输出的结果应该只有5,6,7,8,9
    }
}

skip as shown in the figure:

  • The bottom layer of sorted depends on the implementation of Comparable, and a custom comparator can also be provided

Here Integer implements the comparator

public class Main {

    public static void main(String[] args) {
        Stream.of(2,1,3,6,4,9,6,8,0)
                .sorted()
                .forEach(e->System.out.println(e));
    }
}

The sorted default comparator is shown in the figure:

A custom comparison is used here, of course User can implement the Comparable interface

public class Main {

    public static void main(String[] args) {

        User x = new User("x",11);
        User y = new User("y",12);
        User w = new User("w",10);

        Stream.of(w,x,y)
                .sorted((e1,e2)->e1.age>e2.age?1:e1.age==e2.age?0:-1)
                .forEach(e->System.out.println(e.toString()));

    }

    static class User {

        private String name;

        private int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

As shown in the picture:

  • collect collection, use the collector provided by the system to collect the final data flow into containers such as List, Set, and Map.

Here I use collect to collect elements into a set

public class Main {

    public static void main(String[] args) {
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .collect(Collectors.toSet()) //set 容器
                .forEach(e -> System.out.println(e));
    }
}

Huh? , doesn't it mean that the termination operator can only be used once, why is forEach called here? forEach is not only an operator in Stream but also a syntactic sugar in various collections. If you don’t believe me, let’s try it. Reply to "Aggregation of Interview Questions" in the JavaMissence official account, and send you a collection of interviews from major companies.

public class Main {

    public static void main(String[] args) {

        Set<String> stringSet = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .collect(Collectors.toSet()); //收集的结果就是set
        stringSet.forEach(e->System.out.println(e)); set的语法糖forEach
}

The result is shown in the figure:

  • count counts the number of elements in the data stream, and returns a long type

public class Main {

    public static void main(String[] args) {

        long count = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .count();

        System.out.println(count);
    }
}

count as shown in the figure:

  • findFirst gets the first element in the stream

Find the first element apple here

public class FindFirst {

    public static void main(String[] args) {
        Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .findFirst();
        stringOptional.ifPresent(e->System.out.println(e));
    }
}

The result of findFirst is shown in the figure:

  • findAny Get any element in the stream

public class FindAny {

    public static void main(String[] args) {
        Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .parallel()
                .findAny(); //在并行流下每次返回的结果可能一样也可能不一样
        stringOptional.ifPresent(e->System.out.println(e));
    }
}

findAny uses the result under parallel streams:

output orange

output banana

  • noneMatch None of the elements in the data stream match the condition

The function here is to judge that there is no element equal to aa in the data stream, but aa exists in the stream, so the final result should be false

public class NoneMatch {

    public static void main(String[] args) {
        boolean result = Stream.of("aa","bb","cc","aa")
                .noneMatch(e->e.equals("aa"));
        System.out.println(result);
    }
}

noneMatch as shown in the figure:

  • allMatch and anyMatch, one is full match, and the other is arbitrary match, which is similar to noneMatch, so I won’t give an example here.

  • min The smallest one, passed to the comparator, or none (if the data stream is empty)

public class Main {

    public static void main(String[] args) {

        Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
                .min((e1,e2)->e1.compareTo(e2));

        integerOptional.ifPresent(e->System.out.println(e));

    }

min as shown in the figure:

  • The largest of the max elements, which needs to be passed to the comparator, or may not be available (when the stream is Empty)

     

public class Main {

    public static void main(String[] args) {

        Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
                .max((e1,e2)->e1.compareTo(e2));

        integerOptional.ifPresent(e->System.out.println(e));

    }
}

max as shown in the figure:

  • reduce is a reduction operation, all elements are reduced to one, such as summing all elements, multiplying, etc.

An addition is implemented here, specifying the initialized value

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

        int sum = Stream.of(0,9,8,4,5,6,-1)
              .reduce(0,(e1,e2)->e1+e2);
        System.out.println(sum);
    }
}

reduce as shown in the figure:

  • forEach

forEach has actually seen it before, traversing iterations for each data

  • forEachOrdered is suitable for iteration in the case of parallel flow, which can ensure the order of iteration

Here the numbers are output in parallel

public class ForEachOrdered {
    public static void main(String[] args) {
        Stream.of(0,2,6,5,4,9,8,-1)
                .parallel()
                .forEachOrdered(e->{
                    System.out.println(Thread.currentThread().getName()+": "+e);});
    }
}

forEachOrdered as shown in the figure:

  • toArray is converted into an array, and a custom array generator can be provided

public class ToArray {
    public static void main(String[] args) {
        Object[] objects=Stream.of(0,2,6,5,4,9,8,-1)
                .toArray();

        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }
    }
}

toArray as shown in the figure:

 

 

Summary: Stream operation is a supplement to the Java collection framework. It is to facilitate the operation of the collection. Learning Stream operation can use the collection framework better and faster.

If there is something you don't understand, you can type it yourself to deepen your understanding.

 

Code words are not easy, if you find it helpful, please give me a thumbs up~~

Otherwise, believe it or not, I smashed your lamp and secretly kissed you in the middle of the night ( ̄ε ̄)!!!

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/wangerrong/article/details/109587621