Study Stream and Optional [notes]

Stream API

Inheritance implementation relationship ---- > >

public interface Stream extends BaseStream<T,​Stream>

Class description ---- > > >

Element sequence operations that support sequential and parallel aggregation, (classes that support functional operations on element streams – lambda)

Stream, which is an object reference stream, has original professional IntStream, LongStream, and DoubleStream, all of which are called "streams" and comply with the characteristics and limitations described here.

To perform calculations, flow operations are combined into a flow pipeline. A stream pipeline consists of a source (it may be an array, a collection, a generator function, an I/O channel, etc.)

Methods in class ----- > > > static

Methods in class ----- > > >
Since it is an interface, focus on the static methods in the interface,

Builder() - stream builder

   @Test
    public void StreamBuilder(){
        //Create a flow constructor. After creation, you can specify the type of elements in the flow
        Stream.Builder<Integer> builder = Stream.builder();
//        Add elements to the stream
        builder.add(1);
        builder.add(2);
        builder.add(3);
        builder.add(null);
        //The bottom layer of the add method also uses accept
        builder.accept(4);
       // Build flow to transition this builder to the built state. If there are further attempts after the builder enters the build state, an IllegalStateException will be thrown
        Stream<Integer> build = builder.build();
        build.forEach(System.out::println);
    }

Merge stream Concat()

 @Test
    public void StreamConcat() {
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 12, 13, 22);
        Stream<Integer> stream = list.stream();
        List<Integer> list2 = new LinkedList<>();
        Collections.addAll(list2, 1,2,3);
        Stream<Integer> stream1 = list2.stream();
//        Create two collections and get the stream before merging into one piece
        Stream<Integer> concat = Stream.concat(stream, stream1);
//        ergodic
concat.forEach(System.out::println);
    }

Empty flow ()

 @Test
    public void StreamEmpty() {
//Returns an empty Stream, which is not null
        Stream<Object> empty = Stream.empty();
        System.out.println(empty.toArray().length);//0
    }

Infinite stream Generate()

@Test
    public void StreamGenerate(){
        //
        //Returns an infinite sequential unordered stream, where each element is provided by the Supplier.
        Stream<Double> limit = Stream.generate(Math::random).limit(5);
        //The limit method returns the stream composed of this stream element, and the truncation length does not exceed the maxSize length.
        limit.forEach(System.out::println);
    }


iterate() - iterative flow

 @Test
    public void StreamIterate(){
//        java8
//Pass in a seed, and then iterate the seed according to a rule (unaryoperator < T > F)-
        Stream<Integer> iterate = Stream.iterate(0, e -> e + 2).limit(3);
        iterate.forEach(System.out::println);
  System.out.println("____________________");
//        java9
//        Pass in a seed, and make some constraints on the seed during iteration, including iteration rules
        Stream<Integer> iterate1 = Stream.iterate(0, e -> e<10,f->f+2);
        iterate1.forEach(System.out::println);

    }

! [insert picture description here]( https://img-blog.csdnimg.cn/0cad7e4d1f7d47e6bebe35a5336faf71.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAR2F2aW5fTGlt,size_20,color_FFFFFF,t_70,g_se

Static factory method of

The static factory method returns a stream. The difference lies in the number of elements in the stream and whether it can be null;

    @Test
    public void StreamOf() {
        Stream<Integer> integerStream = Stream.of(1, 2, 3, null);
        Stream<Integer> integerStream1 = Stream.of(1, 2, 3, null, null);
        Stream<String> n = Stream.of("Hello");
//        Stream < Object > objectstream = stream. Of (null); / / if there is only one element, it cannot be null
        Stream<Object> objectStream1 = Stream.ofNullable(null);
        Stream<Object> objectStream2 = Stream.ofNullable("world");
//        Start iteration
        integerStream.forEach(System.out::println);
        System.out.println("----------------------");
        integerStream1.forEach(System.out::println);
        System.out.println("----------------------");
        n.forEach(System.out::println);
        // objectStream.forEach(System.out::println);
        System.out.println("----------------------");
        objectStream1.forEach(System.out::println);
        System.out.println("----------------------");
        objectStream2.forEach(System.out::println);
    }

Look at the results. What questions do you have from time to time???

This is because when null is passed in the ofnullabe method, an empty stream is returned (that is, there are no elements in the stream)

You can verify it with code;

So what's the use of Streaming??

Application of flow

Several examples are given in the API - > >

  int sum = widgets.stream()
                      .filter(w -> w.getColor() == RED)
                      .mapToInt(w -> w.getWeight())
                      .sum();

In this example, widgets is a Collection. We create a stream Widget object, filter it through Collection.stream() to generate a stream containing only red widgets, and then convert it to the value of stream int representing weight. Each red Widget is then added to generate the total weight.

Streams have some similarities with collections, but they have different uses and characteristics. Collections mainly focus on efficiently managing and accessing their elements. In contrast, streams do not provide a way to directly access or manipulate their elements, but focus on declaratively describing their source and summarizing the computing operations to be performed on the source. That is, the operations in the stream will not affect the data source Actual impact;

The stream is automatically closed after being used once, unless it is an IO stream;
Streams have a basic stream. Close () method and can be closed automatically. Most stream instances do not need to be closed after use, because they are supported by collection, array or generation functions and do not need special resource management. Generally, only streams with IO channel source (such as file. Line (path)) Only the returned flow needs to be closed. If the flow does need to be closed, it must be opened as a resource in the attempt resource declaration or similar control structure to ensure that the flow is closed immediately after the operation is completed.

Simple application of stream - > >

If there is a set -- find the extreme value in the set-----

@Test  
    public void StreamMax(){
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 12, 13, 22,99,32,566,322,555,8888);
        Optional<Integer> optional = list.stream().max((a, b) -> a - b);
        //Get the extreme value
        System.out.println(optional.get());
    }

In this way, we don't have to write code to traverse the set to get the extreme value, and the code is greatly simplified;

Stream+lambda greatly simplifies the number of codes and is very simple and convenient in practical application;

Non static methods in Stream

Match()

    @Test
    public void StreamMatch(){
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 12, 13, 22,99,32,566,322,555,8888);
//        Are all even numbers in the collection
        boolean b = list.stream().allMatch(e -> e % 2 == 0);
        System.out.println("Are all even numbers in the collection--"+b);
        boolean b1 = list.stream().anyMatch(e -> e % 2 == 1);
        System.out.println("There are odd numbers in the set--"+b1);
    }

Similarly, nonmetch

Collect()

One method requires that the Collector or its implementation class be passed in the parameters -- but the implementation of the Collector interface is still troublesome. Therefore, like collections or arrays, java provides a tool class Collectors to help us quickly implement the object of a Collector

   @Test
    public void StreamCollect() {
//Convert array to string
        //Prepare an array
        String[] str = {"Hello", "world", "world", "Hello"};
//        Get a stream using a tool class
        String collect = Arrays.stream(str).collect(Collectors.joining("-"));
        System.out.println(collect);
//Convert array to collection
        List<String> collect1 = Arrays.stream(str).collect(Collectors.toList());
        System.out.println(collect1);
        Person per = new Person("Zhang San", 18);
        Person per1 = new Person("Zhang San", 16);
        Person per2 = new Person("Zhang San", 18);
        Person per3 = new Person("Zhang San", 16);
        Person per4 = new Person("Zhang San", 18);
        Person per5 = new Person("Zhang San", 16);
        Person per6 = new Person("Zhang San", 17);
        List<Person> list = new ArrayList<>();
Collections.addAll(list,per,per1,per2,per3,per4,per5,per6);
//        Create a map set with age as key and number of people as value
        Map<Integer, Long> collect2 = list.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
        Set<Map.Entry<Integer, Long>> entries = collect2.entrySet();
        for (Map.Entry<Integer, Long> e : entries) {
            System.out.println(e.getKey()+"--"+e.getValue());
        }

    }

Some other methods are also provided in the Collectors tool class;

Another collect method

Remove duplicate element Distinct()

   @Test
    public void StreamDistinct() {
        ArrayList<Person> list = new ArrayList<>();
        Person per = new Person("Zhang San", 18);
        Person per1 = new Person("Li Si", 16);
        Person per2 = new Person("Zhang San", 18);
        Person per3 = new Person("Li Si", 16);
        Person per4 = new Person("Zhang San", 18);
        Person per5 = new Person("Wang Wu", 16);
        Person per6 = new Person("Zhang San", 37);
        Collections.addAll(list, per, per1, per2, per3, per4, per5, per6);
//        System.out.println(list.stream().count()); / / returns the number of elements in the stream
//distinct remove duplicate elements
        Stream<Person> distinct = list.stream().distinct();//equals and hashCode need to be rewritten
        distinct.forEach(System.out::println);
    }

default Stream dropWhile​(Predicate<? super T> predicate)

DropWhile()

/**
Returns, if this stream is ordered, a stream consisting of the remaining elements of this stream after dropping the longest prefix of elements that match the given predicate.
*/
   @Test
    public void StreamDropWhile(){
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 111, 13, 22, 99, 32, 566, 322, 555, 8888);
//        Delete the odd number until the first one is not satisfied, and keep the rest, jdk9 which will be added in the future
        Stream<Integer> integerStream = list.stream().dropWhile(e -> e % 2 == 1);
        integerStream.forEach(System.out::println);
    }

FindAny()

 @Test
    public  void StreamFindAny(){
        Person per = new Person("Zhang San", 18);
        Person per1 = new Person("Li Si", 16);
        Person per2 = new Person("Zhang San", 18);
        Person per3 = new Person("Li Si", 16);
        Person per4 = new Person("Zhang San", 18);
        Person per5 = new Person("Wang Wu", 16);
        Person per6 = new Person("Zhang San", 17);
        Person per7 = new Person("Wang Wu", 36);
        List<Person> list = new ArrayList<>();
       Collections.addAll(list, per, per1, per2, per3, per4, per5, per6,per7);
/*//        Find the first one
        Optional<Person> first = list.stream().findFirst();
        System.out.println(first.get());*/
//Find any one,
        Optional<Person> any = list.stream().findAny();
        //If the stream is empty
        Person person = any.get();
        System.out.println(person);

    }

FlatMap

 @Test
    public void StreamFlatMap1() {
        Person per = new Person("Zhang San", 18);
        Person per1 = new Person("Li Si", 16);
        Person per2 = new Person("Zhang San", 18);
        Person per3 = new Person("Li Si", 16);
        Person per4 = new Person("Zhang San", 18);
        Person per5 = new Person("Wang Wu", 16);
        Person per6 = new Person("Zhang San", 17);
        Person per7 = new Person("Wang Wu", 36);
        List<Person> list = new ArrayList<>();
        Collections.addAll(list, per, per1, per2, per3, per4, per5, per6, per7);
        Stream<Person> stream = list.stream();
//       Stream returned by list.stream() and Stream.of() -- one is the stream that returns person, and the other is the stream that returns list < person >
//Usage of flatMap - > > > put the stream into a small stream;
        Stream<List<Person>> list1 = Stream.ofNullable(list);
        //Stream<Object> ss = list1.flatMap(e -> e.stream());

//        Here, the stream < list < person > > LIST1 is published as a collection. This collection can also be converted into a stream, so when traversing
        Stream<Person> personStream = list1.flatMap(e -> e.stream());
        personStream.forEach(System.out::println);

    }

flatMapToDouble​

Take out the data in the large stream, and put the returned results after operation in flatMapToDouble;
For example:

 @Test
    public void StreamFlatMap3() {
        Person per = new Person("Zhang San", 18,78.8);
        Person per1 = new Person("Li Si", 16,76.9);
        Person per2 = new Person("Zhang San", 18,78.6);
        Person per3 = new Person("Li Si", 16,88.9);
        Person per4 = new Person("Zhang San", 18,69.9);
        Person per5 = new Person("Wang Wu", 16,90.3);
        Person per6 = new Person("Zhang San", 17,89.8);
        Person per7 = new Person("Wang Wu", 36,77.7);
        List<Person> list = new ArrayList<>();
        Collections.addAll(list, per, per1, per2, per3, per4, per5, per6, per7);
        //Find the sum of those whose weight is less than 80
//        Double stream is required
        double sum = list.stream().filter(e -> e.getWeight() < 80).flatMapToDouble(e -> DoubleStream.of(e.getWeight())).sum();
        System.out.println(sum);
//Sum of ages
        int sum1 = list.stream().flatMapToInt(e -> IntStream.of(e.getAge())).sum();
        System.out.println(sum1);


    }

Similarly, flatMapToInt and flatMapToLong will not be repeated

To summarize:
Differences between flatMap and flatMapToInt / flatMapToLong/flatMapToDouble ----- > >

**flatMap Is to split a large flow into a small flow, as shown in the above code
 from Stream<List<Person>>Split into Stream<Person>,In short, it is to List<Person>Each of person Take it out as a stream and replace the elements in the original stream;
If you want to expand the flow, it is also possible;
flatMapToInt Is to take out the elements in the stream to do an operation,And return a result;
Similarly flatMapToLong/flatMapToDouble;**

flatMap is used for splicing streams and has the function of map at the same time

Collect is used to collect stream results into a data structure

For example, if the result stream in the figure needs to be collected into a list, it can be result.collect(Collectors.toList())

forEach​

Traversal ----- >

    @Test
    public void StreamForeach(){
        Person per = new Person("Zhang San", 18,78.8);
        Person per1 = new Person("Li Si", 16,76.9);
        Person per2 = new Person("Zhang San", 18,78.6);
        Person per3 = new Person("Li Si", 16,88.9);
        Person per4 = new Person("Zhang San", 18,69.9);
        Person per5 = new Person("Wang Wu", 16,90.3);
        Person per6 = new Person("Zhang San", 17,89.8);
        Person per7 = new Person("Wang Wu", 36,77.7);
        List<Person> list = new ArrayList<>();
        Collections.addAll(list, per, per1, per2, per3, per4, per5, per6, per7);
        //list.stream().forEach(System.out::println);
        list.stream().forEachOrdered(System.out::println);

    }

Peek()

 @Test
    public void StreamPeek(){
        Person per = new Person("Zhang San", 18,78.8);
        Person per1 = new Person("Li sigouzi", 16,76.9);
        Person per2 = new Person("Zhang Sanya", 12,78.6);
        Person per3 = new Person("Li Laosi", 15,88.9);
        Person per4 = new Person("\u5f20\u6c42\u80dc", 18,69.9);
        Person per5 = new Person("Wang Wu", 16,90.3);
        Person per6 = new Person("Zhang San", 14,89.8);
        Person per7 = new Person("bachelor", 36,77.7);
        List<Person> list = new ArrayList<>();
        Collections.addAll(list, per, per1, per2, per3, per4, per5, per6, per7);
        List<String> collect = list.stream().filter(e -> e.getName().equals("Zhang San")).peek(e-> System.out.println("filter-value"+e)).map(e -> e.getName()).peek(e -> System.out.println("Mapped value: " + e)).collect(Collectors.toList());

        collect.forEach(System.out::println);
        System.out.println("------------------");
        List<String> collect1 = Stream.of("one", "two", "three", "four")
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("Filtered value: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value: " + e))
                .collect(Collectors.toList());
        collect1.forEach(System.out::println);
    }


The peek method is used to return the elements operated at each node, which is generally used in debug;

skip/sorted

//Skip a few elements and take the rest
        Stream<Person> skip = list.stream().skip(2);
      //  skip.forEach(System.out::println);

        Stream<Person> sorted = list.stream().sorted();

        Stream<Person> sorted1 = list.stream().sorted((a, b) -> (int) (a.getWeight() - b.getWeight()));
        sorted1.forEach(System.out::println);

takeWhile()

    @Test
    public void StreamtakeWhile() {
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 111, 13, 22, 99, 32, 566, 322, 555, 8888);
//        Take an odd number until the first one is not satisfied, delete the rest, and jdk9 add the new one
        Stream<Integer> integerStream = list.stream().takeWhile(e -> e % 2 == 1);
        integerStream.forEach(System.out::println);

    }

The remaining reduce method needs to be continued

Keywords: Java stream

Added by wilsonodk on Fri, 12 Nov 2021 08:22:43 +0200