JAVA8 learning - depth Stream flow (the learning process) from the perspective of use

Stream flow

Stream flow of acquaintance

Simple Meet Stream: official introduction Stream class:

/**
 * A sequence of elements supporting sequential and parallel aggregate
 * operations.  The following example illustrates an aggregate operation using
 * {@link Stream} and {@link IntStream}:
 *
 * <pre>{@code
 *     int sum = widgets.stream()
 *                      .filter(w -> w.getColor() == RED)
 *                      .mapToInt(w -> w.getWeight())
 *                      .sum();
 * }</pre>
 * In this example, {@code widgets} is a {@code Collection<Widget>}.  We create
 * a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
 * filter it to produce a stream containing only the red widgets, and then
 * transform it into a stream of {@code int} values representing the weight of
 * each red widget. Then this stream is summed to produce a total weight.
 *
 */
 

To see such a case, similar to the js chain operations. To understand the flow is about what it was like. Linux-like pipeline

Stream comprises three parts:

  1. source
  2. Zero or more intermediate operations
  3. Termination of operation

Stream classification operations:

  1. Lazy evaluation
  2. Eager evaluation
stream.xxx().yyy().zzz().count();

Intermediate operation: lazy evaluation. Only count () is invoked, the middle of the operation will be evaluated.

Eager evaluation, count () method is invoked immediately evaluated, which is called eager evaluation.

Eager evaluation stream will be only one.

Generating three streams that

public class StreamTest {
    public static void main(String[] args) {
        //本章才正式的开始对流进行讲解。

        //第一种方式,通过of方法
        Stream stream1 = Stream.of("hello","world");
        //第二种方式,通过数组方式
        String[] strings = new String[]{"hello","world"};
        Stream stream2 = Arrays.stream(strings);
        Stream stream3 = Stream.of(strings); //of的底层就是 通过Arrays.stream()来实现的.
        //第三种方式,通过集合.stream
        List<String> list = Arrays.asList("hello", "world");
        list.stream();

    }
}

How to use the stream (Getting Started)

Use a:

public class streamTest2 {
    public static void main(String[] args) {
        //Intstream 怎么用
        IntStream.of(5, 6, 7).forEach(System.out::println);
        System.out.println("----");

        IntStream.range(3, 8).forEach(System.out::println);
        System.out.println("----");

        IntStream.rangeClosed(3, 8).forEach(System.out::println);
        System.out.println("----");
    }
}
public class streamTest3 {
    public static void main(String[] args) {
        //List类型,int的值, 对每一个元素*2,然后加起来,得到结果
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        //以前的写法
//        int i=0;
//        for (Integer i : list) {
//            sum += 2;
//        }
//        sum...

        //stream的写法,一行
        System.out.println(list.stream().map(integer -> integer*2).reduce(0,Integer::sum));

        //reduce方法,map()方法的调用会在下面进行详解.
        //实现简单,语义更明确
    }
}

the reduce (), terminates the operation, eager evaluation.

Deep stream flow

Functional programming, the most fundamental point: the method of delivery is the behavior of all previous data transfer.

  1. Collection provides a new stream () method
  2. ** stream is not stored value, the value acquired by way of conduit
  3. A functional nature, will generate a convection results, but does not modify the underlying data source, a data set may be used as the underlying source stream
  4. Find the delay , many operation flow (filtration, mapping, sorting, etc.) can be implemented delay (the lazy)

Look at this Example:

public class streamTest4 {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("hello", "world", "hello world");
      //lambda写法   
      //stream.toArray(length -> new String[length]);
      //方法引用的写法 (构造方法引用)
        String[] stringArray = stream.toArray(String[]::new);
        Arrays.asList(stringArray).forEach(System.out::println);
    }
}

Known flow, turn List

        //已知流,转List
        Stream<String> stream = Stream.of("hello", "world", "hello world");
        List<String> collect = stream.collect(Collectors.toList());
        collect.forEach(System.out::println);

collect () method Detailed - Collectors also through the inside collect (three parameters) method to achieve this

    /**
     * 第一个参数介绍
     * Performs a <a href="package-summary.html#MutableReduction">mutable
     * reduction</a> operation on the elements of this stream.  A mutable
     * reduction is one in which the reduced value is a mutable result container,
     * such as an {@code ArrayList}, and elements are incorporated by updating
     * the state of the result rather than by replacing the result.  This
     * produces a result equivalent to:  第二个参数的介绍
     * <pre>{@code
     *     R result = supplier.get();
     *     for (T element : this stream)
     *         accumulator.accept(result, element);
     *     return result;
     * }</pre>
     * 被并行化. 流带来的好处.
     * <p>Like {@link #reduce(Object, BinaryOperator)}, {@code collect} operations
     * can be parallelized without requiring additional synchronization.
     * 这是一个终止操作.
     * <p>This is a <a href="package-summary.html#StreamOps">terminal
     * operation</a>.
     * 方法签名是非常适合于使用方法引用的方式.就是最下面举例的Example
     * @apiNote There are many existing classes in the JDK whose signatures are
     * well-suited for use with method references as arguments to {@code collect()}.
     * For example, the following will accumulate strings into an {@code ArrayList}:
     * <pre>{@code
     *     List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add,
     *                                                ArrayList::addAll);
     * }</pre>
     * 扩展功能:字符串实现拼接的操作
     * <p>The following will take a stream of strings and concatenates them into a
     * single string:
     * <pre>{@code
     *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
     *                                          StringBuilder::append)
     *                                 .toString();
     * }</pre>
     *
     * @param <R> type of the result
     第一个参数:结果容器,如LinkList
     * @param supplier a function that creates a new result container. For a
     *                 parallel execution, this function may be called
     *                 multiple times and must return a fresh value each time.
     第二个参数:关联性的,不冲突的,无状态的,用于合并.   item->list
     * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
     *                    <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                    <a href="package-summary.html#Statelessness">stateless</a>
     *                    function for incorporating an additional element into a result
     第三个参数:用于融合,将上次遍历得到的集合融合到最终的结果集中.
     * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
     *                    <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                    <a href="package-summary.html#Statelessness">stateless</a>
     *                    function for combining two values, which must be
     *                    compatible with the accumulator function
     * @return the result of the reduction
     */
    <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);

By source explained: We realize that the underlying transfer List is through this collect three-parameter method to achieve, we come one by one to find out about these three parameters.

1. Parameters 1: supplier, the type of functional Supplier interface functions: to provide a preliminary container List

2. Parameter 2: accumulator, a function of the type of interface functions BiConsumer: accumulator, the stream is accumulated into a collection element.

3. Parameter 3: combiner, a function of the type of interface functions BiConsumer: combiner, the last set of traversal of the resulting fused to a final List.

Read on their own document Collector of the above. I say these elements are reflected in it.

Through the above understanding, we can collect three parameters () method, to realize his conversion to achieve a bottom stream List, as follows:

//功能描述:已知流,转List
Stream<String> stream = Stream.of("hello", "world", "hello world");
List<String> collect = stream.collect(Collectors.toList());
collect.forEach(System.out::println);

//使用collect(三个参数)的底层方法来实现这个操作.  因为这个三参的collect()方法就是这个操作的底层.
List<String> list = stream.collect(() -> new ArrayList(),(theList,item)->theList.add(item),(theList1,theList2)->theList1.addAll(theList2));

//通过方法引用优化后的代码如下:
//优化后的代码:
List<String> list1 = stream.collect(LinkedList::new,LinkedList::add,LinkedList::addAll);

Note further source provided above the string concatenation operation


     * 扩展功能:字符串实现拼接的操作
     * <p>The following will take a stream of strings and concatenates them into a
     * single string:
     * <pre>{@code
     *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
     *                                          StringBuilder::append)
     *                                 .toString();
     * }</pre>
     *

Other using streams

        //使用 Collectors.toCollection()方法来实现 流转List
        Stream<String> stream = Stream.of("hello", "world", "hello world");
//        ArrayList<String> list = stream.collect(Collectors.toCollection(ArrayList::new));
//        list.forEach(System.out::println);

        //使用 Collectors.toCollection()方法来实现 流转Set
        Set<String> list = stream.collect(Collectors.toCollection(TreeSet::new));
        list.forEach(System.out::println);

        //使用 方法来实现,流转String字符串
        stream.collect(Collectors.joining());

Later developed the time, to give more consideration, List, Set, whether these conversions can use these stream JAVA8 provided to achieve. Used in the actual development.

Rethinking

public class StreamTest5 {
    public static void main(String[] args) {
        //集合,全部转换大写,然后输出.
        List<String> list = Arrays.asList("hello", "world", "hello world");
        //要考虑能不能用函数式接口,lambda表达式的技能?显然是可以呢
        //这是不是映射? 先要要用map. 给定一个参数,返回一个结果.
        //java8提供这些接口,就是为了方便开发者.合理的应用.
        list.stream().map(String::toUpperCase).collect(Collectors.toList()).forEach(System.out::println);
      
        //求出每个数字的平方,然后打印出来
        List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
        list1.stream().map(item -> item * item).collect(Collectors.toList()).forEach(System.out::println);
      
    }
}
        //要考虑能不能用函数式接口,lambda表达式的技能?显然是可以呢
    //这是不是映射? 先要要用map. 给定一个参数,返回一个结果.
    //java8提供这些接口,就是为了方便开发者.合理的应用.

flatMap () Method: Flat mapping


    /**
     * Returns a stream consisting of the results of replacing each element of
     * this stream with the contents of a mapped stream produced by applying
     * the provided mapping function to each element.  Each mapped stream is
     * {@link java.util.stream.BaseStream#close() closed} after its contents
     * have been placed into this stream.  (If a mapped stream is {@code null}
     * an empty stream is used, instead.)
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @apiNote
     * The {@code flatMap()} operation has the effect of applying a one-to-many
     * transformation to the elements of the stream, and then flattening the
     * resulting elements into a new stream.
     *
     * <p><b>Examples.</b>
     *
     * <p>If {@code orders} is a stream of purchase orders, and each purchase
     * order contains a collection of line items, then the following produces a
     * stream containing all the line items in all the orders:
     * <pre>{@code
     *     orders.flatMap(order -> order.getLineItems().stream())...
     * }</pre>
     *
     * <p>If {@code path} is the path to a file, then the following produces a
     * stream of the {@code words} contained in that file:
     * <pre>{@code
     *     Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);
     *     Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));
     * }</pre>
     * The {@code mapper} function passed to {@code flatMap} splits a line,
     * using a simple regular expression, into an array of words, and then
     * creates a stream of words from that array.
     *
     * @param <R> The element type of the new stream
     * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *               <a href="package-summary.html#Statelessness">stateless</a>
     *               function to apply to each element which produces a stream
     *               of new values
     * @return the new stream
     */
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

And much like the map, but totally different otherwise it would not exist the way to go.

Map flattened;

When 1.map mapped, a collection of three List, List each have a different value. After completion of mapping module also

When 2.flatMap mapped, a collection of three List, go to tie the convergence to a list.

Examples Example:

//每一个元素都乘方,然后将数据作为一个整体,输出. 当做一个集合.  就要用flatmap()
        Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
        listStream.flatMap(theList->theList.stream()).map(integer -> integer*integer).forEach(System.out::println);

Other methods described in the Stream class

  1. generate()
    /**
     * Returns an infinite sequential unordered stream where each element is
     * generated by the provided {@code Supplier}.  This is suitable for
     * generating constant streams, streams of random elements, etc.
     *
     * @param <T> the type of stream elements
     * @param s the {@code Supplier} of generated elements
     * @return a new infinite sequential unordered {@code Stream}
     */
    public static<T> Stream<T> generate(Supplier<T> s) {
        Objects.requireNonNull(s);
        return StreamSupport.stream(
                new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
    }

How to Use the following Example?:

public class StreamTest6 {
    public static void main(String[] args) {
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
        System.out.println(generate.findFirst());
    }
}
Optional<T> findFirst();

Why is this findFirst () method returns a Optional?

Because Optional, NPE is to circumvent the problem.

So here need to use Optional.ifPresent (), this is the proper use of Optional classes should be amended as follows:

public class StreamTest6 {
    public static void main(String[] args) {
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
       generate.findFirst().ifPresent(System.out::println);
    }
}
  1. iterate()
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
        Objects.requireNonNull(f);
        final Iterator<T> iterator = new Iterator<T>() {
            @SuppressWarnings("unchecked")
            T t = (T) Streams.NONE;

            @Override
            public boolean hasNext() {
                return true;
            }

            @Override
            public T next() {
                return t = (t == Streams.NONE) ? seed : f.apply(t);
            }
        };
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                iterator,
                Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
    }

how to use?

package com.dawa.jdk8.stream;

import java.util.UUID;
import java.util.stream.Stream;

public class StreamTest6 {
    public static void main(String[] args) {
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
       generate.findFirst().ifPresent(System.out::println);

        //如果不加限制,iterate 会变成一个无限流.
        //Stream.iterate(1, integer -> integer + 2).forEach(System.out::println);
        //所以在使用的时候一定不要单独使用.
        //要搭配limit()方法,一个中间操作,使用.
        Stream.iterate(1, integer -> integer + 2).limit(6).forEach(System.out::println);
    }
}

Note: // if unchecked, iterate will become an endless stream.
// So be sure not to use when used alone.
// To match limit () method, an intermediate operation and use.

Find (1,3,5,7,9) is greater than the flow elements 2, and then multiplies each element 2, and then ignored in the first two elementary stream, and then remove the first two elementary stream, and finally obtaining the sum of the flow elements.

//找出(1,3,5,7,9)流中大于2的元素,然后将每个元素乘以2,然后忽略流中的前两个元素,然后再取出流的前两个元素,最后求出流中元素的总和.
// Stream<Integer> stream = Stream.of(1, 3, 5, 7, 9);
        Stream<Integer> stream = Stream.iterate(1, integer -> integer + 2).limit(6);//通过iterate方法来获取值
        System.out.println(stream.filter(integer -> integer > 2).mapToInt(integer -> integer * 2).skip(2).limit(2).sum());
//用到的方法. map,mapToint,skip,limit.
  1. ... skip () skip

  2. ... limit () interception

  3. ...map().mapToInt(),mapToDouble().... 映射

    mapToInt ... avoid automatic boxing and unboxing automatically. (avoid performance loss).

  4. ... sum (), min (), max (). The maximum, minimum, sum, etc.

    sum () is the return value of type int.

    . Min () max (), return type is: OptionalInt.

    Why? Optional classes, because of the use or not, depends on the nature of this value can not be empty.

  5. summaryStatistics (): Summary, simple summary statistics of the stream.

    Such as: a summary Object: IntSummaryStatistics {count = 2, sum = 32, min = 14, average = 16.000000, max = 18}

    This class provides a variety of methods.

    getCount
    getSum
    getMin
    getMax
    getAverage
    toString

The above case, it was already using a number of methods Stream class. If necessary, confirm their official source.

Note: When intermediate operate on the stream, returns a new stream up to be a time of termination of operations, will get the final result.

About the stream is closed issue.

image-20200104174241664

Between just inadvertently, when in operation, such an exception is thrown to a prompt stream it has been closed.

Replay code below:


Stream<Integer> stream = Stream.iterate(1, integer -> integer + 2).limit(6);
System.out.println(stream);
System.out.println(stream.filter(integer -> integer > 2));
System.out.println(stream.distinct());

Features streams

  1. Once it operated. Closes automatically flow.
  2. With a stream can not be repeated.
  3. Close the flow can not continue to operate.
  4. Each intermediate operation returns a new stream object operation.

How to avoid?

  1. Mr. into a stream, after completing the operation, and then generate a stream.

  2. Then the newly generated stream to operate.

  3. Stream<Integer> stream = Stream.iterate(1, integer -> integer + 2).limit(6);//通过iterate方法来获取值
    
    System.out.println(stream);
    Stream<Integer> stream1 = stream.filter(integer -> integer > 2);
    System.out.println(stream1);
    Stream<Integer> stream2 = stream1.distinct();
    System.out.println(stream2);

The essential difference between on the termination operation and intermediate operation

Example:

public class StreamTest7 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "hello world");
        //首字母大写,其他的小写,然后打印输出.
        list.stream().map(item -> item.substring(0, 1).toUpperCase() + item.substring(1)).forEach(System.out::println);

        //另外的操作
        list.stream().map(item -> {
            String result = item.substring(0, 1).toUpperCase() + item.substring(1);
            System.out.println("test");
            return result;
        });//运行之后没有值

        //另外的操作
        list.stream().map(item -> {
            String result = item.substring(0, 1).toUpperCase() + item.substring(1);
            System.out.println("test");
            return result;
        }).forEach(System.out::println);//运行之后能够执行.

        //原因:中间操作,如果没有终止操作,是不会自己执行的,是lazy类型的.是惰性求值的.

    }
}

Cause: intermediate operation, if no termination operation is not performed their own, it is a type of lazy lazy evaluation.

Then consider the efficiency issues.

Perhaps might think, many intermediate operations, will be recycled many times, it will reduce efficiency.

In fact, it performed only once and will not affect efficiency.

There will be a container, all the intermediate operations together. One execution of the operation does not have redundancy.

How to distinguish intermediate operation and termination operation

Intermediate operation returns a Stream object, for example, returns Stream ,...Wait

Another look at the operation: Effect on termination operation and intermediate operation of

public class StreamTest8 {
    public static void main(String[] args) {
        IntStream.iterate(0, i -> (i + 1) % 2).distinct().limit(6).forEach(System.out::println);
    }
}

After the above code is not running up automatically terminated.

It should be amended as follows:

public class StreamTest8 {
    public static void main(String[] args) {
        IntStream.iterate(0, i -> (i + 1) % 2).limit(6).distinct().forEach(System.out::println);
    }
}

The reason is because the middle of the operation and termination of operation of impact.

  1. If the first execution limit, is a termination operation. Then eliminate repeat, the program will terminate.

  2. If the first repeat of eliminating operation is a first case, a return flow, and then taken 6, it does not turn off the flow.


Stream bottom depth

  • And another difference is that the iterator, Stream parallel operations, commands only iterator type, the serial operations
  • When a serial mode to traverse, and then read each item to read the next item.
  • When used to traverse the parallel data it is divided into a plurality of segments, wherein each of the different threads to process, and then outputs the result with
  • Fork parallel operation dependent Stream stream introduced in JAVA7 / Join frame.

Essentially three main operations flow: Source -> intermediate operation -> intermediate operation -> ...-> terminating operation

Here we use a SQL reference to learning

select name from student where age>20 and address='beijing' order by age desc;

Descriptive language

By stream describe this SQL

student.stream()
  .filter(student->student.getAge>20)
  .filter(student->student.getAddress()
          .equals("beijing")
          .sorted(...)
          .forEach(student->System.out.println(student.getName()));
//这个描述和上面的SQL其实是等价的.

You just send a command to the DB, but not how to find that you just give a description, and then to be screened according to the rules in descending like. For the whole process, you did not tell how to achieve the underlying.

SQL is the case, Stream, too. Just descriptive language.

This way is called internal iteration.

Internal iterations

External iteration (way before)

  1. Treatment is not descriptive, based entirely on the old version of the implementation. And descriptive language compared to the poor readability.

  2. Operations are serialized, not parallelized

for(int i=0;i<student.size();i++){
  Student student = students.get(i);
  if(student.getAge()>20&&student.getAddress().equals("beijing")){
    list.add(student);
  }
}
//然后进行排序
Collection.sort(list,Comparator()...);
//然后再去寻找需要的东西
for(Student student:list){
    System.out.println(student.getName);
}

Internal iteration (descriptive language)

The couple also be able to read it.

student.stream()
  .filter(student->student.getAge>20)
  .filter(student->student.getAddress()
          .equals("beijing")
          .sorted(...)
          .forEach(student->System.out.println(student.getName()));

Stream emergence and collections are inextricably linked.

  1. Of the operation may be performed in parallel.
  2. When the underlying execution, not a condition to condition a loop through

The difference between the internal and the iterative nature of most external iteration

  1. Coupling
  2. Bottom treatment
  3. Of the various parallel and serial

to sum up

  1. Data collection is concerned with the data store itself;
  2. Stream of interest is calculated data;
  3. Stream iterators similar point is: the flow can not be reused and consumption;
  4. Use the bottom: fork / join method, decomposing large tasks into small tasks to perform.

Most in need of attention

The implementation of the principle of flow is definitely not a method of execution cycles a method traversal.


Used in parallel flow (parallelStream)

Serial stream (Stream ()) and the parallel streams (parallelStream ()) of the determination efficiency.

  • Serial stream
package com.dawa.jdk8.stream;

import java.util.ArrayList;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class StreamTest9 {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>(5000000);
        for (int i = 0; i < 5000000; i++) {
            list.add(UUID.randomUUID().toString());
        }

        System.out.println("开始排序");
        long startTime = System.nanoTime();//纳秒 比毫秒的精度高
        list.stream().sorted().count();

        long endTime = System.nanoTime(); //纳秒, 结束时间

        long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
        System.out.println("耗时:" + millis + "毫秒");
    }
}

Run Results: Serial time: 4.0 seconds

image-20200104185911432

  • Parallel flow
public class StreamTest9 {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>(5000000);
        for (int i = 0; i < 5000000; i++) {
            list.add(UUID.randomUUID().toString());
        }

        System.out.println("开始排序");
        long startTime = System.nanoTime();//纳秒 比毫秒的精度高
        list.parallelStream().sorted().count();

        long endTime = System.nanoTime(); //纳秒, 结束时间

        long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
        System.out.println("耗时:" + millis + "毫秒");
    }
}

The result: parallel time: 1.1 seconds

image-20200104185700662

Parallel and serial - Cost time difference: 3-5 times.

Short circuit

public class StreamTest10 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "hello world");
        //找出列表中,长度为5的第一个单词,同时将长度5打印出来.
//        list.stream().mapToInt( String::length).filter(length -> length == 5).findFirst().ifPresent(System.out::println);

        list.stream().mapToInt(item -> {
            int length = item.length();
            System.out.println(item);
            return length;
        }).filter(length -> length == 5).findFirst().ifPresent(System.out::println);

    }
}

The results set:

image-20200104190933025

Why print when printed only one?

Reason: a vessel which is stored for each operation of the container.

When the stream is an iterative process, the container will hold operation, one by one to a value of use of this

If not filtering rules, then it will happen short circuit arithmetic operations. This is the second reason. Just find qualified, will not be back on the run.

Such as: does not meet the rules will be fully implemented it will be finished the following results:

image-20200104191315339

Case: Find the set of all words, and go heavy (application flatMap method).

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

        //找出集合中所有的单词,并去重.
        List<String> list = Arrays.asList("hello world", "hello welcome", "hello", "hello world hello", "hello world welcome");
        //要输出: hello world welcome.
//        list.stream().map(item -> item.split(" ")).distinct().collect(Collectors.toList()); //不对
        List<String> collect = list.stream().map(item -> item.split(" ")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
        collect.forEach(System.out::println);
    }
}

Case: The two sets combined, hello - names (flatMap application)

public class StreamTest12 {
    public static void main(String[] args) {
        //将两个集合组合起来,  打招呼-人名
        List<String> list1 = Arrays.asList("Hi", "Hello", "你好");
        List<String> list2 = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");

//        list1.stream().map(item->item.concat(list2.stream().map()))
        List<String> collect = list1.stream().flatMap(item -> list2.stream().map(item2 ->item+ " " + item2)).collect(Collectors.toList());
        collect.forEach(System.out::println);
    }
}

Grouping and partition

As the group by SQL.

select * from studeny group by name;

Result:Map<String,List >

The traditional realization of ideas:

  1. Circular list
  2. Remove the student's name
  3. Check the presence of the name map, there is no directly added to the map; map will be present in the List object taken out, and then add the object to the Student List.
  4. Map object returned

Packet flow is achieved by way of (groupingby () method)


public class StreamTest13 {
    public static void main(String[] args) {
        Student student1 = new Student("zhangsan", 100, 20);
        Student student2 = new Student("lisi", 90, 20);
        Student student3 = new Student("wangwu", 90, 30);
        Student student4 = new Student("zhaoliu", 80, 40);

        List<Student> students = Arrays.asList(student1, student2, student3, student4);

        //Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getName));
       // System.out.println(collect);
        Map<Integer, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getScore));
        System.out.println(collect);
    }
}

How to achieve this SQL with the flow?

select name,count(*) from student group by name; 

It is easy to:

Map<String, Long> collect = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));
        System.out.println(collect);

To achieve group name, and then take the average over how the group Using flow?

Map<String, Double> collect = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.averagingDouble(Student::getScore)));
        System.out.println(collect);

Written above are the concept of grouping.

Groups: group by

Zoning: partition by

Partition

Partition is a special case of packet, such as Boolean, only true and false. Above cases, such as in a cut-off point 90 is divided into, the partition

        Map<Boolean, List<Student>> collect = students.stream().collect(Collectors.partitioningBy(student -> student.getScore() > 90));
        System.out.println(collect);
collect.get(true);//获取ture对应的值
collect.get(false);//获取false对应的值

Guess you like

Origin www.cnblogs.com/bigbaby/p/12150703.html
Recommended