I often hear "I tried stream with java8 but I'm not used to it" or "I can't do it if I try to do something a little difficult", so I'll summarize it.
If you grasp the type, it seems that you know 80%, so I will try to make it a picture.
~~ By the way, the article is long, but it's enough to read the first [main story - headline! ~~
It's too long to think calmly, so I divided it.
Let's hold down the basic three hands.
You may not be familiar with reduce, but it's aMapReduce model advocated by Google, so it's talked about with map. -> wiki
Let's look at it using the example below.
/*
 *There is the following log
 *Label or label:Output line by line in millisec format
 *
 *Find the sum of milliseconds
 */
List<String> lines = Arrays.asList(
    "application-boot", "access-dispatch:10", "dispatched", "authentication:30", "database-access:45", "response-creation:15", "access-logging"
);
The important thing is the type anyway, so don't be afraid of generics and just check it.
Then, a lot of such pictures will come out.
ʻA-> B fis written in java code asB f (a);, and ʻA and B are String and ʻOptional 
filter
The definition of filter is as follows.
Stream<T> filter(Predicate<? super T> predicate);
Forget about Predicate <T>, which means "argument is T and return value is bool", and ? Super T.
Let's take the type notation of Predicate <T> as T to bool and write(T-> bool).
By the way, let's simplify Generics as well.
Stream<T> filter((T -> bool) f);
To use filter to make lines only lines with :, you can write:
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
If you write the definition as T-> bool, the implementationline-> line.contains (":")looks the same.
(In this subject, T is specifically String)
Is it like this when drawn in a picture?
filter means that the ** type ** does not change, but the ** number ** changes.
map
Here is the definition of map.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
This is also simplified in the same way.
Stream<R> map((T -> R) f);
Using map to make the line of label: millisec ʻInteger can be written after filter` as follows.
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
        .map(line -> Integer.valueOf(line.split(":")[1]))    // [10, 30, 45, 15]
Here, too, the implementation has the same shape as the definition T-> R.
(In this subject, R is specifically ʻInteger, so it would be nice if T-> Rlooks likeString-> Integer`)
Is it like this when drawn in a picture?
map means that the ** number ** does not change, but the ** type ** changes.
reduce
There are three definitions of reduce in java8 stream, but this is what I'm going to use now.
T reduce(T identity, BinaryOperator<T> accumulator);
BinaryOperator <T> is a little unfamiliar, but it means that "the argument is two T and the return value is T".
Let's simplify this without being afraid.
T reduce(T t, ((T, T) -> T) f);
reduce is generally called" convolution "and is a process of accumulating results in order from the top of the list.
To use reduce to make a line of ʻInteger the sum of ʻInteger, you can write this after map.
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
        .map(line -> Integer.valueOf(line.split(":")[1]))    // [10, 30, 45, 15]
        .reduce(0, (acc, n) -> acc + n)                      // 100
There are a few parentheses in the definition, but it should be a little easier to understand because T, (T, T)-> T and0, (acc, n)-> ...have the same shape.
Is it like this when drawn in a picture?
reduce is a process in which ** list elements ** become ** single result **.
This is clear!
 *Find the sum of milliseconds
Is
// (Repost)
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
        .map(line -> Integer.valueOf(line.split(":")[1]))    // [10, 30, 45, 15]
        .reduce(0, (acc, n) -> acc + n)                      // 100
I solved it with.
For the time being, I will post the whole picture.
All the extras from here onwards have been separated into the following articles.
List processing understood by pictures --java8 stream / javaslang --bonus
Refreshing.
Recommended Posts