-[Java11] Stream Summary -Advantages of Stream- -[Java11] Stream Usage Summary -Basics-
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.
--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.
"⭐️" is attached to the items that are used most often.
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;
}
}
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}>
Widget[] arr = {a, b, c};
Stream<Widget> arrayToStream = Arrays.stream(arr); // <a, b, c>
Stream<Long> stream1 = Stream.of(100L); // <100L>
//× Error
Stream<Long> stream2 = Stream.of(null); // <null> ?
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>
Stream<Long> stream1 = Stream.ofNullable(100L); // <100L>
Stream<Long> stream2 = Stream.ofNullable(null); // <>
Stream<Long> stream3 = Stream.empty(); // <>
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>
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>
IntStream stream1To4 = IntStream.range(1, 5); // IntStream<1, 2, 3, 4>
IntStream stream1To5 = IntStream.rangeClosed(1, 5); // IntStream<1, 2, 3, 4, 5>
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>
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>
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">
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>
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">
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>
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>
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>
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5); // <1, 2, 3, 4, 5>
Stream<Integer> stream2 = stream1.limit(3); // <1, 2, 3>
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5); // <1, 2, 3, 4, 5>
Stream<Integer> stream2 = stream1.skip(2); // <3, 4, 5>
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]
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}
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]}
Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
stream.forEach(System.out::println);
//Standard output:
// 1
// 2
// 3
Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
long cnt = stream.count(); // 3L
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]"
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
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>
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>
Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
Optional<Integer> n = stream.findFirst() // <1>
Stream<Integer> stream = Stream.of(1, 2, 3); // <1, 2, 3>
Optional<Integer> n = stream.findAny() // <1>
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
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
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