Speaking of flow, we will think of mobile phones, computer assembly line, logistics warehouse commodity packaging line and so on. If mobile phones, computers and packages are regarded as the final results, various parts before processing goods can be regarded as data sources, while a series of processing operations in the middle can be regarded as stream processing.

The concept of flow

Java Se has input/output IO streams for streams, and The Stream introduced in Java8 is a new member of the Java API that allows you to handle collections of data declaratively. Stream provides a high-level abstraction of Java collection operations and expressions in an intuitive way similar to SQL statements querying data from a database. Note that the stream operation here can be thought of as processing set data.

Simply put, a stream is a data channel that manipulates sequences of elements produced by data sources (collections, arrays, files, and so on).

  • The source – abandoned the use of a data source, such as collection, array, or input output resources |.

Streams generated from ordered sets retain the original order. A stream generated by a list with elements in the same order as the list

  • Element sequences – Just like collections, streams provide an interface to access an ordered set of values for a particular element type.

  • Data processing operations – The data processing capabilities of streams support database-like operations (data filtering, filtering, sorting, and so on).

  • Pipelining – Multiple stream operations themselves return a stream, and multiple operations can be linked together as a pipeline for data processing.

Flow & collection

  • Period of calculation

The data in the collection is all calculated data, such as querying user records from the database in descending order by user ID and receiving user records through the list. The calculation of data has been completed before the collection is put into the collection.

The data in the stream is calculated according to the needs of users. For example, when searching through the search engine, the searched items are not all presented, and the top 10 or 20 items that most match are displayed first. Only after clicking “Next page”, the new 10 items will be output. The same is true for Stream computation, where the Stream evaluates data when the user needs it.

  • External iteration versus internal iteration

If the collection is compared to the warehouse of a factory, the hardware of the factory is relatively backward at the beginning, and the goods need to be modified. At this time, workers go into the warehouse to process the goods and sometimes transfer the processed goods to another warehouse. At this point, it is necessary for developers to do the iteration themselves, find the needed goods one by one and deal with them, which is called external iteration.

When the factory developed and was equipped with assembly line operation, the factory only had to design the corresponding assembly line according to the demand, and then the workers only had to put the goods on the assembly line, and they could wait to receive the results, and the assembly line could also directly transport the goods to the corresponding warehouse according to the requirements.

This is called internal iteration, and the pipeline has done the iteration for you, you just have to say what to do (design the pipeline properly). The equivalent of Stream’s introduction of Java8 “automates” the processing of data.

Flow process

The entire flow operation is a pipeline on which elements are processed one by one. Note that many stream operations return a stream themselves, so multiple operations can be directly connected, as shown in the figure below. Operations can be chain-called, and parallel flows can also implement data stream parallel processing operations.

In general, the flow operation process is divided into three phases:

  • create

Create a flow object with a data source

  • In the middle of processing

Filtering, slicing, mapping, sorting and other intermediate operations

  • Termination of the flow

Match, summarize, group, etc

The creation of a flow

For the convection operation, the corresponding flow should be created first, and the centralized form of the flow creation is as follows:

1 Collection creation flow

In Java 8, the collection interface has two methods to generate streams:

  • Stream () − Creates a serial stream for the collection.

  • ParallelStream () − Creates parallel streams for collections.

Example code is as follows:

Public static void main(String[] args) {/** * array <String> l1 = array. asList(" zhou ", "Zhou "," Zhou ", "Chow Yun-fat "); L1.stream (); L1.parallelstream (); l1.parallelstream (); }Copy the code

In addition to the basic operation of flow creation, there are several ways to create a flow.

2 value create stream

Stream.of(T…) : stream.of (“aa”, “bb”) generates a Stream

Stream<String> Stream = stream. of("java8", "Spring", "SpringCloud"); stream.forEach(System.out::println);Copy the code

Array creation stream

Create the corresponding stream based on the array type of the parameter.

  • Arrays.stream(T[ ])

  • Arrays.stream(int[ ])

  • Arrays.stream(double[ ])

  • Arrays.stream(long[ ])

    / array.stream (array.asList (10, 20, 30, 40).toarray ())); Stream = array.stream (arrays.asList (10, 20, 30, 40).toarray (), 0, 2);

4 File generation flow

stream = Files.lines(Paths.get("C:\\java\\jdbc.properties")); System.out.println(stream.collect(Collectors.toList())); Stream = files.lines (path.get ("C:\\ Java \\jdbc.properties"), charset.forname (" utF-8 ")); System.out.println(stream.collect(Collectors.toList()));Copy the code

5 Functions generate streams

Two methods:

  • Iterate: Applies the function to each newly generated value in turn

  • Generate: Accepts a function and generates a new value

    // Weight 100 starts to generate even Stream. Iterate (100, n -> n + 2); Generate (() ->(int) (math.random () * 100 + 1));

Mid-stream operation

The intermediate operations of a stream fall into three main categories: filter slicing, map, and sort.

Filter slicing: An operation to filter elements similar to where criteria in SQL

Mapping: Transforms the result of an element. The advantage is similar to the meaning of a SELECT field or transforms the content of an element

Sort: easy to understand, commonly used IN SQL according to the field ascending order descending operation

Data preparation for intermediate flow operations (order data processing is taken as an example)

@datapublic class Order {// Order id private Integer ID; // order userId private Integer userId; Private String orderNo; // orderDate private Date orderDate; // Private String address; Private Date createDate; // Update time private Date updateDate; // Order status 0- Unpaid 1- Paid 2- To be shipped 3- Shipped 4- Received 5- Completed private Integer status; 1- Valid order 0- Invalid order private Integer isValid; Private Double total; }Order order01 = new Order(1, 10, "20190301", new Date(), new Date(), new Date(), 4, 1, 100.0); Order order02 = new Order(2, 30, "20190302", new Date(), new Date(), new Date(), new Date(), 1, 1, 2000.0); Order03 = new Order(3, 20, "20190303", new Date(), New Date(), new Date(), 4, 1, 500.0); Order order03 = new Order(3, 20, "20190303", New Date(), New Date(), new Date(), 4, 1, 500.0); Order04 = new Order(4, 40, "20190304", new Date(), New Date(), new Date(), 4, 1, 256.0); order04 = New Order(4, 40, "20190304", New Date(), New Date(), new Date(), 4, 1, 256.0); Order order05 = new Order(5, 40, "20190304", new Date(), New Date(), new Date(), 4, 1, 1000.0); Order order05 = new Order(5, 40, "20190304", New Date(), new Date(), 4, 1, 1000.0); ordersList = Arrays.asList(order01, order02, order03, order04, order05);Copy the code

Screening & slicing

  • Screening valid orders

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).foreach (system.out ::println);

  • Filter valid orders and take the first page of data (2 records per page)

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).limit(2) .forEach(System.out::println);

  • Filter order collection valid order takes the last record

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).skip(orderslist.size () – 2) // Skip the former orderslist.size ()-2 record.foreach (system.out ::println);

  • Filter valid orders and take data on page 3 (2 records per page)

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).skip((3-1) * 2) .limit(2) .forEach(System.out::println);

  • Filter invalid orders to remove duplicate order number records

    Orderslist.stream ().filter((Order) -> order.getisValid () == 0) .distinct() .forEach(System.out::println);

mapping

  • Filter valid orders to get all order numbers

    // Filter valid orders, Orderslist.stream ().filter((order) -> order.getisValid () == 1).map((order) -> order.getorderno ()) .forEach(System.out::println);

  • Filter valid orders and separate the shipping address area information for each order

    ordersList.stream().map(o -> o.getAddress() .split(“-“)) .flatMap(Arrays::stream) .forEach(System.out::println);

The sorting

  • Filter valid orders to sort by user ID

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).sorted((o1, o2) -> o1.getUserId() – o2.getUserId()) .forEach(System.out::println); Orderslist.stream ().filter((order) -> order.getisValid () == 1) .sorted(Comparator.comparingInt(Order::getUserId)) .forEach(System.out::println);

  • Filter valid orders and sort by order status if order status is the same sort by order creation time

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).sorted((o1, o2) -> { if (o1.getStatus().equals(o2.getStatus())) { return o1.getCreateDate().compareTo(o2.getCreateDate()); } else { return o1.getStatus().compareTo(o2.getStatus()); }}) .forEach(System.out::println); Orderslist.stream ().filter((order) -> order.getisValid () == 1).sorted(Comparator.comparing(order ::getCreateDate)) .thenComparing(Comparator.comparing(Order::getStatus))) .forEach(System.out::println);

The termination operation of a stream

Termination operations generate results from the pipeline of the flow. The result is any value that is not a stream, such as the usual List, Integer, and even void results. Termination operations for streams fall into the following three categories:

Find and match

  • Filter whether valid order matches are all paid orders

    Println (“allMatch match result :” + orderslist.stream ().filter((order) -> order.getisValid () == 1) .allMatch((o) -> o.getStatus() ! = 0));

  • Filter valid order matches for unpaid orders

    Println (“anyMatch match result :” + orderslist.stream ().filter((order) -> order.getisValid () == 1) .anyMatch((o) -> o.getStatus() == 0) );

  • Filter valid orders all outstanding orders

    System.out.println(“noneMatch matching result :” + orderslist.stream ().filter((order) -> order.getisValid () == 1) .noneMatch((o) -> o.getStatus() == 5) );

  • Filter the valid order to return the first order

    Println (“findAny match result :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1)) .findAny() .get() );

  • Filter all valid orders to return total orders

    System.out.println(“count result :” + orderslist.stream ().filter((order) -> order.getisValid () == 1)) .count() );

  • Filter valid order return amount Maximum order amount

    System.out.println(” order Max :” + orderslist.stream ().filter((order) -> order.getisValid () == 1)) .map(Order::getTotal) .max(Double::compare) .get() );

  • Filter valid order return amount Minimum order amount

    System.out.println(” order minimum :” + orderslist.stream ().filter((order) -> order.getisValid () == 1)) .map(Order::getTotal) .min(Double::compare) .get() );

Reduction & collection

1 reduction

The operation of repeatedly combining elements in a stream to obtain a value

  • Calculate the total amount of valid order

    System.out.println(” orderslist.stream ().filter((order) -> order.getisValid () == 1)) .map(Order::getTotal) .reduce(Double::sum) .get() );

2 Collector Data collection

To transform the Stream into something else, the Coollect method acts as a terminal operation, receiving an implementation of the Collector interface that summarizes the elements in the Stream. The most common method is to collect all elements of a stream into a List, Set, or Collection.

3 Collection

Common collection collection methods toList, toSet, toCollection, toMap, etc

  • Filter all valid orders and collect the order list

    Orderslist.stream ().filter((order) -> order.getisValid () == 1).collect(Collectors. ToList ()) .forEach(System.out::println);

  • Filter all valid orders and collect order numbers and order amounts

    Map<String,Double> Map = orderslist.stream ().filter((order) -> order.getisValid () == 1). collect(Collectors.toMap(Order::getOrderNo, Order::getTotal)); Map.foreach ((k,v)->{system.out. println(“k:”+k+”:v:”+v); });

PS: get Java learning materials and tutorials, lezijie007 (code 999)

summary

Summary operations are common in Stream operations, such as calculating totals and averaging. Common methods are as follows:

Related operations are as follows

  • Filter all valid orders to return total orders

    System.out.println(“count result :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1)) .collect(Collectors.counting()) ); System.out.println(“count result :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1).count());

  • Return the total order amount

    System.out.println(” order sum :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1)) .collect(Collectors.summarizingDouble(Order::getTotal)) ); System.out.println(” order sum :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1)) .mapToDouble(Order::getTotal) .sum() ); System.out.println(” order total amount :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1).map(order ::getTotal) .reduce(Double::sum) .get() );

  • Returns the average amount spent per valid order with user ID =20

    System.out.println(” orderslist.stream () + orderslist.stream ().filter((order) -> order.getisValid () == 1)) .filter((order -> order.getUserId()==20)) .collect(Collectors.averagingDouble(Order::getTotal)) ); System.out.println(” orderslist.stream () + orderslist.stream ().filter((order) -> order.getisValid () == 1)) .filter((order -> order.getUserId()==20)) .mapToDouble(Order::getTotal) .average() .getAsDouble() ); System.out.println(” orderslist.stream () + orderslist.stream ().filter((order) -> order.getisValid () == 1)) .filter((order -> order.getUserId()==20)) .collect(Collectors.summarizingDouble(Order::getTotal)) .getAverage() );

  • Filter all valid orders and calculate the total order amount

    System.out.println(” order sum :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1)) .collect(Collectors.summingDouble(Order::getTotal)) );

The most value

  • Filter all valid orders and calculate the minimum order amount

    System.out.println(” minimum order amount :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1).map(order ::getTotal) .collect(Collectors.minBy(Double::compare)) );

  • Filter all valid orders and calculate the maximum order amount

    System.out.println(” maximum order amount :”+ orderslist.stream ().filter((order) -> order.getisValid () == 1)) .map(Order::getTotal) .collect(Collectors.maxBy(Double::compare)) );

Grouping & Partitioning

1 group

GroupingBy is used to group data, and finally returns a Map. The second parameter of groupingBy is used to implement multi-level grouping

  • Group operations based on valid order payment status

    Map<Integer,List> g01=ordersList.stream() .filter((order) -> order.getIsValid() == 1) .collect(Collectors.groupingBy(Order::getStatus)); g01.forEach((status,order)->{ System.out.println(“—————-“); System.out.println(” order status :”+status); order.forEach(System.out::println); });

  • Filter valid orders, grouping by user ID and payment status

    Map<Integer,Map<String,List>> g02= ordersList.stream() .filter((order) -> order.getIsValid() == 1) GroupingBy (Order::getUserId, Collectors. GroupingBy ((o)->{if(O.gottStatus ()==0){return “not paid “; }else if (o.gestatus ()==1){return “paid “; }else if (o.gestatus ()==2){return “to be sent “; }else if (o.gestatus ()==3){return “geStatus “; }else if (o.gestatus ()==4){return “received “; } else{return “done “; }}))); G02. ForEach ((userId, m) – > {System. Out. Println (” user id: “+ userId +” — — > effective order is as follows: “); M. orEach ((status, OS) – > {System. Out. Println (” : “+ status +” – order list as follows: “); os.forEach(System.out::println); }); System.out.println(“———————–“); });

2 partitions

The difference between partitioning and grouping is that partitions are divided according to true and false, so the lambda accepted by partitioningBy is also T -> Boolean

  • Partition operation – Filter valid orders with order amount >1000

    Map<Boolean,List> g03= ordersList.stream() .filter((order) -> order.getIsValid() == 1) .collect(Collectors.partitioningBy((o)->o.getTotal()>1000)); G03. ForEach ((b, OS) – > {System. Out. Println (” partition results: “a + b +” – results of a list: “); os.forEach(System.out::println); });

  • Splice operation – Filter valid orders and splice them

    String orderStr=ordersList.stream() .filter((order) -> order.getIsValid() == 1) .map(Order::getOrderNo) .collect(Collectors.joining(“,”)); System.out.println(orderStr);

The application of flow

Java8 introduced Stream operation, making the processing of elements more convenient and fast, through the Stream provided by the relevant method is a good combination of Lambda, functional interface, method reference and other related content, making the Stream processing compared with the original collection processing code greatly simplified, Stream support function chain call, The code is more compact and the parallelization of elements supported by Stream improves the performance of the program.

The application of Stream is usually in the data processing of collection elements, especially in the case of multiple processing of elements. At the same time, the taste of functional programming is stronger, which is also a trend of future development.

Java8 core features Stream Stream introduction here, should be very detailed, I hope you enjoy.