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