[Java11] Stream Usage Summary -Basics-

-[Java11] Stream Summary -Advantages of Stream- -[Java11] Stream Usage Summary -Basics-

Introduction

It's been about two years since I wrote Java, and recently I've implemented it in Java 11. From Java 8 to 9,10 to Stream and Optional Some methods have also been added to https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/Optional.html). In the current development, we have introduced Optional in earnest, and it has become an environment where Stream and Optional can be used more effectively.

Apart from that, I'm often asked "Can I write this in Stream?" "I want to write in Stream here ..." ... Looking at other people's code, I thought that Stream could be written more beautifully ...

In any case, I want you to write in Stream more aggressively! (Why do you want to write in Stream here)

By the way, if you can read the official reference without hesitation, this article may not be useful.

Note

--This article is written based on the Java 11 specification. --Not all methods are covered ――For the sake of clarity, each operation is placed in a variable, but in reality it is preferable to write it in one sentence. --Although the intermediate operation expresses the change in the contents of the Stream after each operation with a comment, please note that the intermediate operation is not actually performed until the termination operation is performed.

Main story

"⭐️" is attached to the items that are used most often.

Assumption of Widget class
class Widget {
    private Color color;
    
    private int weight;
    
    private String text;
    
    private List<Widget> childWeights = new ArrayList<>();
    
    public Widget(Color color, int weight) {
        this.color = color;
        this.weight = weight;
    }
    
    public Widget(Color color, int weight, String text) {
        this(color, weight);
        this.text = text;
    }
    
    public Color getColor() {
        return color;
    }
    
    public int getWeight() {
        return weight;
    }
    
    public Optional<String> getText() {
        return Optional.ofNullable(text);
    }
    
    public List<Widget> getChildWeights() {
        return childWeights;
    }
    
    public void setChildWeights(List<Widget> childWeights) {
       this.childWeights = childWeights;
    }
    
    public boolean isColorRed() {
        return color == RED;
    }
    
    public boolean isColorBlue() {
        return color == BLUE;
    }
    
    @Override
    public String toString() {
        return "Widget {color: " + color + ", weigth: " + weight + "}";
    }
    
    @Override
    public boolean equals(Object o) {
        Widget w = (Widget) o;
        return this.color == w.color && this.weight == w.weight;
    }
}

Stream generation

⭐️ From List / Set / Map

How to use No. 1

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

//From List
List<Widget> list = List.of(a, b, c); // [a, b, c]
Stream<Widget> listToStream = list.stream(); // <a, b, c>
//From Set
Set<Widget> set = Set.of(a, b, c); // {a, b, c}
Stream<Widget> setToStream = set.stream(); // <a, b, c>
//From Map
Map<Long, Widget> map = Map.of(1L, a, 2L, b, 3L, c); // {1L : a, 2L : b, 3L : c}
Stream<Long> mapKeyToStream = map.keySet().stream(); // <1L, 2L, 3L>
Stream<Widget> mapValueToStream = map.values().stream(); // <a, b, c>
Stream<Entry<Long, Widget>> mapToStream = map.entrySet().stream(); // <{1L : a}, {2L : b}, {3L : c}>

When you want to parallel from the beginning

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

//From List
List<Widget> list = List.of(a, b, c); // [a, b, c]
Stream<Widget> listToStream = list.parallelStream(); // <a, b, c>
//From Set
Set<Widget> set = Set.of(a, b, c); // {a, b, c}
Stream<Widget> setToStream = set.parallelStream(); // <a, b, c>
//From Map
Map<Long, Widget> map = Map.of(1L, a, 2L, b, 3L, c); // {1L : a, 2L : b, 3L : c}
Stream<Long> mapKeyToStream = map.keySet().parallelStream(); // <1L, 2L, 3L>
Stream<Widget> mapValueToStream = map.values().parallelStream(); // <a, b, c>
Stream<Entry<Long, Widget>> mapToStream = map.entrySet().parallelStream(); // <{1L : a}, {2L : b}, {3L : c}>

From the array

Widget[] arr = {a, b, c};
Stream<Widget> arrayToStream = Arrays.stream(arr); // <a, b, c>

From some values

1 piece

Stream<Long> stream1 = Stream.of(100L); // <100L>

//× Error
Stream<Long> stream2 = Stream.of(null); // <null> ?

2..N pieces

Stream<Long> stream1 = Stream.of(100L, 200L); // <100L, 200L>
Stream<String> stream2 = Stream.of("A", "B", "C", null); // <"A", "B", "C", null>

Stream<Long> stream3 = Stream.of(null, null); // <null, null>

0 .. 1 piece

Stream<Long> stream1 = Stream.ofNullable(100L); // <100L>

Stream<Long> stream2 = Stream.ofNullable(null); // <>
Stream<Long> stream3 = Stream.empty(); // <>

From multiple Streams

⭐️ From 2 Streams

Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
Stream<Widget> stream2 = Stream.of(x, y, z); // <x, y, z>
Stream<Widget> stream3 = Stream.concat(stream1, stream2); // <a, b, c, x, y, z>

3. From N Streams

I haven't used it, but I can write it like this in case of emergency

Stream<Widget> stream1 = Stream.of(a, b); // <a, b>
Stream<Widget> stream2 = Stream.of(c, d); // <c, d>
Stream<Widget> stream3 = Stream.of(e, f); // <e, f>
Stream<Widget> stream4 = Stream.of(g, h); // <g, h>
Stream<Stream<Widget>> stream5_1 = Stream.of(stream1, stream2, stream3, stream4); // <<a, b>, <c, d>, <e, f>, <g, h>>
Stream<Widget> stream5_2 = stream5_1.flatMap(UnaryOperator.identity()); // <a, b, c, d, e, f, g, h>

From a specific range of integers (IntStream)

IntStream stream1To4 = IntStream.range(1, 5); // IntStream<1, 2, 3, 4>
IntStream stream1To5 = IntStream.rangeClosed(1, 5); // IntStream<1, 2, 3, 4, 5>

Intermediate operation

⭐️ Mapping

1: 1 conversion

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

// Widget -> Color
Stream<Widget> stream1_1 = Stream.of(a, b, c); // <a, b, c>
Stream<Color> stream1_2 = stream1_1.map(Widget::getColor); // <RED, RED, BLUE>

// Widget ->weight(int)
Stream<Widget> stream2_1 = Stream.of(a, b, c); // <a, b, c>
Stream<Integer> stream2_2 = stream2_1.map(Widget::getWeight); // <10, 15, 20>

// number -> number * 2
IntStream stream3_1 = IntStream.range(1, 5); // IntStream<1, 2, 3, 4>
IntStream stream3_2 = stream3_1.map(i -> i * 2); // IntStream<2, 4, 6, 8>

1: 0..N conversion

Widget a = new Widget(RED, 10);
Widget a_1 = new Widget(RED, 1);
Widget a_2 = new Widget(RED, 2);
Widget a_3 = new Widget(RED, 4);
a.setChildWeights(List.of(a_1, a_2, a_3));
Widget b = new Widget(RED, 15);
Widget b_1 = new Widget(RED, 8);
b.setChildWeights(List.of(b_1));
Widget c = new Widget(BLUE, 20);

// Widget ->Each child widget
Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
Stream<List<Widget>> stream2 = stream1.map(Widget::getChildWeights); // <[a_1, a_2, a_3], [b_1], []>
Stream<Widget> stream3 = stream2.flatMap(Collection::stream); // <a_1, a_2, a_3, b_1>

1: 0..1 conversion

Widget a = new Widget(RED, 10, "A");
Widget b = new Widget(RED, 15, "B");
Widget c = new Widget(BLUE, 20);

// Widget -> text(String)
Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
Stream<Optional<String>> stream2 = stream1.map(Widget::getText); // <<"A">, <"B">, <>>
Stream<String> stream3 = stream2.flatMap(Optional::stream); // <"A", "B">

From Stream \ <T > to IntStream etc.

Stream<Integer> stream1_1 = Stream.of(1, 2, 3, 4); // <1, 2, 3, 4>
IntStream stream1_2 = stream1_1.mapToInt(i -> i); // IntStream<1, 2, 3, 4>

From IntStream etc. to Stream \ <Integer > etc.

IntStream stream1_1 = IntStream.range(1, 5); // IntStream<1, 2, 3, 4>
Stream<Integer> stream1_2 = stream1_1.boxed(); // <1, 2, 3, 4>

IntStream stream2_1 = IntStream.range(1, 5); // IntStream<1, 2, 3, 4>
Stream<String> stream2_2 = stream2_1.mapToObj(i -> String.valueOf(i)); // <"1", "2", "3", "4">

⭐️ Filter

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);
Widget d = new Widget(GREEN, 25);

//Extract the red one
Stream<Widget> stream1_1 = Stream.of(a, b, c, d); // <a, b, c, d>
Stream<Widget> stream1_2 = stream1_1.filter(Widget::isColorRed); // <a, b>
//Extract those that weigh more than 10
Stream<Widget> stream1_3 = Stream.of(a, b, c, d); // <a, b, c, d>
Stream<Widget> stream1_4 = stream1_3.filter(w -> w.getWeight() > 10); // <b, c, d>

//Extract non-red ones(1)
Stream<Widget> stream2_1 = Stream.of(a, b, c, d); // <a, b, c, d>
Stream<Widget> stream2_2 = stream2_1.filter(w -> !w.isColorRed()); // <c, d>
//Extract non-red ones(2)
Stream<Widget> stream2_3 = Stream.of(a, b, c, d); // <a, b, c, d>
Stream<Widget> stream2_4 = stream2_2.filter(Predicate.not(Widget::isColorRed)); // <c, d>

//Extract the equivalent(1)
Stream<Widget> stream3_1 = Stream.of(a, b, c, d, null); // <a, b, c, d, null>
Stream<Widget> stream3_2= stream3_1.filter(w -> Objects.equals(w, new Widget(RED, 15))); // <b>
//Extract the equivalent(2)
Stream<Widget> stream3_3 = Stream.of(a, b, c, d, null); // <a, b, c, d, null>
Stream<Widget> stream3_4= stream3_3.filter(Predicate.isEqual(new Widget(RED, 15))); // <b>

//Extract red or blue ones(1)
Stream<Widget> stream4_1 = Stream.of(a, b, c, d); // <a, b, c, d>
Stream<Widget> stream4_2 = stream4_1.filter(w -> w.isColorRed() || w.isColorBlue()); // <a, b, c>
//Extract red or blue ones(2)
Stream<Widget> stream4_3 = Stream.of(a, b, c, d); // <a, b, c, d>
Predicate<Widget> isColorRed = Widget::isColorRed; 
// Widget::Because there is no guarantee that isColorRed is Predicate
// filter((Widget::isColorRed).or(Widget::isColorBlue))Can't write
Stream<Widget> stream4_4 = stream4_2.filter(isColorRed.or(Widget::isColorBlue)); // <a, b, c>

Deduplication (distinct)

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);

Stream<Widget> stream1_1 = Stream.of(a, a, b, b, null, null); // <a, a, b, b, null, null>
Stream<Widget> stream1_2 = stream1_1.distinct(); // <a, b, null>

⭐️ Sort


Widget a = new Widget(RED, 10, "A");
Widget b = new Widget(RED, 15, "B");
Widget c = new Widget(BLUE, 20);
Widget d = new Widget(GREEN, 25;

//Sort by weight
Stream<Widget> stream1_1 = Stream.of(b, c, a); // <b, c, a>
Stream<Widget> stream1_2 = stream1_1.sorted(Comparator.comparing(Widget::getWeight)); // <a, b, c>

//Sort by weight(descending order)
Stream<Widget> stream2_1 = Stream.of(b, c, a); // <b, c, a>
Stream<Widget> stream2_2 = stream2_1.sorted(Comparator.comparing(Widget::getWeight, Comparator.reverseOrder())); // <c, b, a>

//Sort by text(Make null first)
Stream<Widget> stream3_1 = Stream.of(b, c, a); // <b, c, a>
Stream<Widget> stream3_2 = stream3_1.sorted(Comparator.comparing(w -> w.getText().orElse(null), Comparator.nullsFirst(Comparator.naturalOrder()))); <c, a, b>

//First sort:Is it red,Second sort:weight
Stream<Widget> stream4_1 = Stream.of(b, c, a, d); // <b, c, a, d>
Stream<Widget> stream4_2 = stream4_1.sorted(Comparator.comparing(Widget::isColorRed).thenComparing(Widget::getWeight)); // <c, d, a, b>

First N

Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5); // <1, 2, 3, 4, 5>
Stream<Integer> stream2 = stream1.limit(3); // <1, 2, 3>

Other than the first N

Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5); // <1, 2, 3, 4, 5>
Stream<Integer> stream2 = stream1.skip(2); // <3, 4, 5>

Termination operation

⭐️ Create List

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream = Stream.of(a, b, c); // <a, b, c>
List<Widget> list = stream.collect(Collectors.toList()); // [a, b, c]

Create Set

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream = Stream.of(a, b, c); // <a, b, c>
Set<Widget> set = stream.collect(Collectors.toSet()); // {a, b, c}

⭐️ Create Map

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
Map<Integer, Color> map1 = stream.collect(Collectors.toMap(Widget::getWeight, Widget::getColor)); // {10: RED, 15: RED, 20: BLUE}

Stream<Widget> stream2_1 = Stream.of(a, b, c); // <a, b, c>
Map<Color, Widget> map2_1 = stream.collect(Collectors.toMap(Widget::getColor, UnaryOperator.identity(), (w1, w2) -> w1)); // {RED: a, BLUE: c}
Stream<Widget> stream2_2 = Stream.of(a, b, c); // <a, b, c>
Map<Color, Widget> map2_2 = stream.collect(Collectors.toMap(Widget::getColor, UnaryOperator.identity(), (w1, w2) -> w2)); // {RED: b, BLUE: c}
//× Error(In case of key collision, it is necessary to specify whether to prioritize the first or the second.)
Stream<Widget> stream2_3 = Stream.of(a, b, c); // <a, b, c>
Map<Color, Widget> map2_3 = stream.collect(Collectors.toMap(Widget::getColor, UnaryOperator.identity())); 

Stream<Widget> stream3 = Stream.of(a, b, c); // <a, b, c>
Map<Color, List<Widget>> map3 = stream3.collect(Collectors.groupingBy(Widget::getColor)); // {RED: [a, b], BLUE: [c]}

⭐️ Iterative processing (for Each)

Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
stream.forEach(System.out::println);
//Standard output:
// 1
// 2
// 3

Get the number of elements

Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
long cnt = stream.count(); // 3L

⭐️ Combine strings

Stream<Widget> stream1 = Stream.of("A", "B", "C"); // <"A", "B", "C">
String str1 = stream1.collect(Collectors.joining()); // "ABC"

Stream<Widget> stream2 = Stream.of("A", "B", "C"); // <"A", "B", "C">
String str2 = stream2.collect(Collectors.joining(", ")); // "A, B, C"

Stream<Widget> stream3 = Stream.of("A", "B", "C"); // <"A", "B", "C">
String str3 = stream3.collect(Collectors.joining(", ", "[", "]")); // "[A, B, C]"

Get the sum of numbers

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream1_1 = Stream.of(a, b, c); // <a, b, c>
IntStream stream1_2 = stream1_1.mapToInt(Widget::getWeight); // <10, 15, 20>
int sum1 = stream1_2.sum(); // 45

Stream<Widget> stream2_1 = Stream.of(a, b, c); // <a, b, c>
int sum2 = stream2.collect(Collectors.summingInt(Widget::getWeight)); // 45

⭐️ Get maximum

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
Optional<Widget> widget = stream1.max(Comparator.comparing(Widget::getWeight)); // <c>

Stream<Widget> stream2_1 = Stream.of(a, b, c); // <a, b, c>
IntStream stream2_2 = stream2_1.mapToInt(Widget::getWeight); // <10, 15, 20>
OptionalInt max = stream2_2.max(); // <20>

⭐️ Get the minimum value

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
Optional<Widget> widget = stream1.min(Comparator.comparing(Widget::getWeight)); // <a>

Stream<Widget> stream2_1 = Stream.of(a, b, c); // <a, b, c>
IntStream stream2_2 = stream2_1.mapToInt(Widget::getWeight); // <10, 15, 20>
OptionalInt min = stream2_2.min(); // <10>

⭐️ Get the first element

Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
Optional<Integer> n = stream.findFirst() // <1>

⭐️ Get any element

Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
Optional<Integer> n = stream.findAny() // <1>

⭐️ Returns boolean value

Any one or more elements meet the criteria

Widget a = new Widget(RED, 10);
Widget b = new Widget(RED, 15);
Widget c = new Widget(BLUE, 20);

Stream<Widget> stream1 = Stream.of(a, b, c); // <a, b, c>
boolean bool1 = stream1.anyMatch(Widget::isColorRed); // true

Stream<Widget> stream2 = Stream.of(c); // <c>
boolean bool2 = stream2.anyMatch(Widget::isColorRed); // false

Stream<Widget> stream3 = Stream.of(); // <>
boolean bool3 = stream3.anyMatch(Widget::isColorRed); // false

All elements meet the conditions

Note the behavior when Stream is empty

Stream<Widget> stream1 = Stream.of(a, b); // <a, b>
boolean bool1 = stream1.allMatch(Widget::isColorRed); // true

Stream<Widget> stream2 = Stream.of(b, c); // <b, c>
boolean bool2 = stream2.allMatch(Widget::isColorRed); // false

Stream<Widget> stream3 = Stream.of(); // <>
boolean bool3 = stream3.allMatch(Widget::isColorRed); // true

Not all elements meet the conditions

Note the behavior when Stream is empty

Stream<Widget> stream1 = Stream.of(c); // <c>
boolean bool1 = stream1.noneMatch(Widget::isColorRed); // true

Stream<Widget> stream2 = Stream.of(b, c); // <a, b, c>
boolean bool2 = stream2.noneMatch(Widget::isColorRed); // false

Stream<Widget> stream3 = Stream.of(); // <>
boolean bool3 = stream3.noneMatch(Widget::isColorRed); // true

Recommended Posts

[Java11] Stream Usage Summary -Basics-
Java8 Stream Rough Summary
[Java11] Stream Summary -Advantages of Stream-
Summary of Java language basics
Java basics
Java basics
Java basics
Java knowledge summary
Java Generics Summary
[JAVA] Stream type
Try Java 8 Stream
java programming basics
Java Stream API
Java JAR basics
Object-oriented (Java) basics
Java 8 documentation summary
Studying Java 8 (Stream)
Java concurrency basics
Java 11 document summary
Java Stream termination
[Java] Stream processing
Stream API basics
Java 9 Optional :: stream
Java No.3 for, stream memory usage useful for business
Java 12 new feature summary
[Java] Stream Collectors notes
[Summary] Java environment preparation
effective java 3rd summary
Java 13 new feature summary
[Java] Stream API-Stream generation
[Java] Stream API / map
Regarding Java variable usage
Java programming basics practice-array
Java static [Personal summary]
Java Network Basics (Communication)
Thread safe summary ~ Java ~
Java8 Stream reduction operation
Java Primitive Specialization Summary
Java development link summary
Personal summary about Java
Java 10 new feature summary
Muscle Java Basics Day 1
Java 14 new feature summary
Summary of Java support 2018
Java design pattern summary
Java reserved word summary
What is Java Assertion? Summary.
[Java] Mirage-Basic usage of SQL
Basics of character operation (java)
Java Stream API cheat sheet
[Java] Summary of regular expressions
[Java] Summary of operators (operator)
Object-oriented summary by beginners (Java)
Java programming basics practice-for statement
Java Stream cannot be reused.
Java tips --Spring execution Summary
[Java] Summary of for statements
Summary of Java Math class
Getting Started with Java Basics
Java Development Basics ~ Exercise (Array) ~
[Java] Introduction to Stream API