A couple of weeks ago, a reader urged me to write a Java Stream article. I said there are already a lot of Java Streams out there, and guess what he said: “I just want to read yours!” You see you see, how pale like ah. Well, then, write one. Hee hee.

From the perspective of the word “Stream”, it seems to have something to do with InputStream and OutputStream in the java.io package. Actually, it doesn’t matter. Streams were added to Java 8 to free up programmer productivity when working with collections, thanks in large part to the simultaneous advent of Lambda expressions, which greatly improved programming efficiency and program readability.

What exactly is a Stream?

Stream is like a high-level iterator that can only be traversed once, like a Stream flowing east. During a stream, elements in the stream perform operations such as “filter out strings greater than 10 in length”, “get the first letter of each string”, and so on.

To manipulate a stream, you first need a data source, either an array or a collection. Each operation returns a new stream object to facilitate chain operations, but the original stream object remains unchanged.

Flow operations can be divided into two types:

1) There can be multiple intermediate operations. Each time a new flow is returned, and chain operations can be carried out.

2) There can only be one terminal operation. After each execution, the stream is used up and the next operation cannot be performed, so it can only be put at the end.

Let’s take an example.

List list = new ArrayList<>(); List.add (” wuhan come on “); List.add (” Go China “); List.add (” World go! “); List.add (” World go! “);

long count = list.stream().distinct().count(); System.out.println(count); The distinct() method is an intermediate operation (de-duplication) that returns a new stream (with no common elements).

Stream distinct(); The count() method is a terminal operation that returns the number of elements in the stream.

long count(); Intermediate operations are not performed immediately, and only when terminal operations are performed does the stream actually traverse, for mapping, filtering, and so on. In layman’s terms, performing multiple operations at once improves performance.

So much for the theory part, let’s go straight to the actual part.

Arrays.stream() or stream.of () can be used to create streams for Arrays. In the case of collections, you can create a stream directly using the stream() method, which has been added to the Collection interface.

Public class CreateStreamDemo {public static void main(String[] args) {String[] arr = new String[]{ “Go world “}; Stream stream = Arrays.stream(arr);

Stream = stream. of(" Come on wuhan ", "Come on China "," Come on world "); List<String> list = new ArrayList<>(); List.add (" wuhan come on "); List.add (" Go China "); List.add (" World go! "); stream = list.stream(); }Copy the code

} Arrays.stream() is called internally from the of() method.

public static Stream of(T… values) { return Arrays.stream(values); } In addition, collections can create concurrent streams by calling the parallelStream() method, using the default ForkJoinPool.commonPool() thread pool.

List aList = new ArrayList<>(); Stream parallelStream = aList.parallelStream(); The Stream class provides a number of useful methods for manipulating a Stream. Let me pick out a few common ones.

1) filter

The filter() method is used to filter out the desired elements from the stream.

public class FilterStreamDemo { public static void main(String[] args) { List list = new ArrayList<>(); List.add (” Jay “); List.add (” Leehom wang “); List. The add (” tao “); List.add (” Jj Lin “); Stream = list.stream().filter(element -> element. Contains (” king “)); stream.forEach(System.out::println); The}} filter() method accepts arguments of type Predicate, so we can pass a Lambda expression directly to the method, For example, element -> element.contains(” king “) filters out strings with “king” in them.

The forEach() method accepts a Consumer (a new functional interface in Java 8 that takes an input argument and returns no operations) class name: Method names are new syntax introduced in Java 8. System.out returns the PrintStream class, and the println method you should know is printed.

stream.forEach(System.out::println); Equivalent to printing in the for loop, similar to the following:

for (String s : strs) { System.out.println(s); } Obviously, one line of code looks cleaner. Take a look at the program’s output:

Wang Lee-hom 2) Mapping

If you want to convert elements in a stream to elements in a new stream by some operation, you can use the map() method.

public class MapStreamDemo { public static void main(String[] args) { List list = new ArrayList<>(); List.add (” Jay “); List.add (” Leehom wang “); List. The add (” tao “); List.add (” Jj Lin “); Stream stream = list.stream().map(String::length); stream.forEach(System.out::println); }} map() takes a Function (int T, int R, int length, int length, int length, int length). Turn a Stream into a Stream.

The output of the program is as follows:

3, 3, 2, 3, 3) Match

The Stream class provides three methods for element matching:

AnyMatch (), which returns true as long as one element matches the passed condition.

AllMatch (), which returns false if one element does not match the passed condition; Return true if all matches.

NoneMatch (), which returns false as long as one element matches the passed condition; Return true if all matches.

public class MatchStreamDemo { public static void main(String[] args) { List list = new ArrayList<>(); List.add (” Jay “); List.add (” Leehom wang “); List. The add (” tao “); List.add (” Jj Lin “);

Boolean anyMatchFlag = list.stream().anymatch (Element -> element.contains(" king ")); boolean allMatchFlag = list.stream().allMatch(element -> element.length() > 1); Boolean noneMatchFlag = list.stream().nonematch (element -> element.endswith (" sink ")); System.out.println(anyMatchFlag); System.out.println(allMatchFlag); System.out.println(noneMatchFlag); }Copy the code

} Because “Wang Leehom” starts with “wang”, anyMatchFlag should be true; The string length of Jay Chou, Leehom Wang, David Tao, and Jj Lin is greater than 1, so allMatchFlag is true. Because none of the four strings ends in sink, noneMatchFlag is true.

The output of the program is as follows:

True true true 4) Combination

The reduce() method, whose main function is to combine elements in Stream, can be used in two ways:

Optionalreduce(BinaryOperatoraccumulator)

There’s no starting value, there’s only one argument, which is the operation rule, and we return Optional.

T reduce(T identity, BinaryOperatoraccumulator)

It has a start value, it has a rule, it has two arguments, and it returns the same type as the start value.

Consider the following example.

public class ReduceStreamDemo { public static void main(String[] args) { Integer[] ints = {0, 1, 2, 3}; List list = Arrays.asList(ints);

    Optional<Integer> optional = list.stream().reduce((a, b) -> a + b);
    Optional<Integer> optional1 = list.stream().reduce(Integer::sum);
    System.out.println(optional.orElse(0));
    System.out.println(optional1.orElse(0));

    int reduce = list.stream().reduce(6, (a, b) -> a + b);
    System.out.println(reduce);
    int reduce1 = list.stream().reduce(6, Integer::sum);
    System.out.println(reduce1);
}
Copy the code

} can be a Lambda expression (e.g. (a, b) -> a + b) or a class name :: method name (e.g. Integer::sum).

The result of running the program is as follows:

6, 6, 12, 12 0, 1, 2, 3 without adding the starting values is 6; It’s 12 when you start with 6.

If you can convert a collection or an array to a stream, there should be a method to convert a stream back — collect() does the trick.

public class CollectStreamDemo { public static void main(String[] args) { List list = new ArrayList<>(); List.add (” Jay “); List.add (” Leehom wang “); List. The add (” tao “); List.add (” Jj Lin “);

    String[] strArray = list.stream().toArray(String[]::new);
    System.out.println(Arrays.toString(strArray));

    List<Integer> list1 = list.stream().map(String::length).collect(Collectors.toList());
    List<String> list2 = list.stream().collect(Collectors.toCollection(ArrayList::new));
    System.out.println(list1);
    System.out.println(list2);

    String str = list.stream().collect(Collectors.joining(", ")).toString();
    System.out.println(str);
}
Copy the code

} The toArray() method converts streams into arrays. You might be wondering what String[]::new is. Take a look at the source code for the toArray() method.

A[] toArray(IntFunction<A[]> generator); That is, String[]::new is an IntFunction, a function that generates the desired new array, and you can decompile bytecode to see what it is:

String[] strArray = (String[])list.stream().toArray((x$0) -> { return new String[x$0]; }); System.out.println(Arrays.toString(strArray)); This returns an array of strings of a specified length.

When we need to convert a collection to another collection according to certain rules, we can use map() method and collect() method together.

List list1 = list.stream().map(String::length).collect(Collectors.toList()); After creating a stream of the collection through the stream() method, it is mapped to a new stream of String length through map(String:length), and finally converted to a new collection through the collect() method.

Collectors are a tool class for Collectors that has a set of built-in collector implementations, such as the toList() method that collects elements into a new java.util.list. The toCollection() method, for example, collects elements into a new java.util.arrayList; For example, the joining() method collects elements into a string that can be delimited.

Take a look at the program’s output:

Jay Chou, Leehom Wang, Zhe Tao, Junjie Lin [3, 3, 2, 3] Jay Chou, Leehom Wang, Zhe Tao, Junjie Lin

Thank you, my dear readers, that’s all for this article, don’t you feel that Stream is too powerful?