Skip to content

Commit 5234b21

Browse files
committed
JDK 24: added examples of Stream Gatherers
1 parent 7d75f68 commit 5234b21

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed

java-24/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,6 @@ To run each example use: `java --enable-preview --source 24 <FileName.java>`
183183
* Blogs:
184184
* [A Basic Introduction to the Classfile API](https://ifesunmola.com/a-basic-introduction-to-the-classfile-api/#creating-the-personrunner-class)
185185
* [Class File API: Not Your Everyday Java API](https://www.unlogged.io/post/class-file-api-not-your-everyday-java-api)
186+
* Presentations:
187+
* [Stream Gatherers - Deep Dive with the Expert](https://www.youtube.com/watch?v=v_5SKpfkI2U)
186188

java-24/StreamGatherersBuiltin.java

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import static java.util.stream.Collectors.toList;
2+
import java.util.stream.Stream;
3+
import java.util.stream.Gatherer;
4+
import java.util.stream.Gatherers;
5+
6+
/*
7+
* To run: `java StreamGatherersBuiltin.java`
8+
*/
9+
public class StreamGatherersBuiltin {
10+
public static void main(String[] args) {
11+
System.out.println("=== Fold ===");
12+
fold();
13+
System.out.println("=== Scan ===");
14+
scan();
15+
System.out.println("=== Window Fixed ===");
16+
windowFixed();
17+
System.out.println("=== Window Sliding ===");
18+
windowSliding();
19+
System.out.println("=== Map Concurrent ===");
20+
mapConcurrent();
21+
}
22+
23+
static void fold() {
24+
var sum = generate(10)
25+
.gather(
26+
Gatherers.fold(() -> 0, (acc, elem) -> acc + elem)
27+
)
28+
.findFirst()
29+
.get();
30+
System.out.println("The sum of all elements: " + sum);
31+
}
32+
33+
static void scan() {
34+
var sums = generate(10)
35+
.gather(
36+
Gatherers.scan(() -> 0, (acc, elem) -> acc + elem)
37+
)
38+
.collect(toList());
39+
System.out.println("The sum of each element with its previous: " + sums);
40+
}
41+
42+
static void windowFixed() {
43+
var pairs = generate(10)
44+
.gather(
45+
Gatherers.windowFixed(2)
46+
)
47+
.collect(toList());
48+
System.out.println("Pair of elements: " + pairs);
49+
}
50+
51+
static void windowSliding() {
52+
var neighbors = generate(10)
53+
.gather(
54+
Gatherers.windowSliding(2)
55+
)
56+
.collect(toList());
57+
System.out.println("Elements that are neighbor: " + neighbors);
58+
}
59+
60+
static void mapConcurrent() {
61+
// mapConcurrent uses VirtualThreads
62+
// preserves the ordering of the stream
63+
var first10thSquares = generate(50)
64+
.gather(Gatherers.mapConcurrent(5, elem -> elem * elem))
65+
.collect(toList());
66+
System.out.println("First 50th squares: " + first10thSquares);
67+
}
68+
69+
static Stream<Integer> generate(int size) {
70+
return Stream.iterate(1, acc -> acc + 1).limit(size);
71+
}
72+
}

java-24/StreamGatherersExamples.java

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import static java.util.stream.Collectors.toList;
2+
import java.util.LinkedList;
3+
import java.util.List;
4+
import java.util.Set;
5+
import java.util.TreeSet;
6+
import java.util.stream.Stream;
7+
import java.util.stream.Gatherer;
8+
import java.util.stream.Gatherers;
9+
10+
/*
11+
* To run: `java StreamGatherersExamples.java`
12+
*/
13+
public class StreamGatherersExamples {
14+
public static void main(String[] args) {
15+
deduplicateStream();
16+
filterIfHasAtLeastFiveEvenNumbers();
17+
}
18+
19+
static void deduplicateStream() {
20+
var uniques = Stream.of(1, 2, 5, 8, 1, 9, 3, 5, 4, 8, 7, 3)
21+
.gather(deduplicate())
22+
.collect(toList());
23+
System.out.println("Unique elements: " + uniques);
24+
}
25+
26+
static Gatherer<Integer, Set<Integer>, Integer> deduplicate() {
27+
return Gatherer.ofSequential(
28+
// initializer: start the state with a Set
29+
() -> new TreeSet<>(),
30+
// integrator: only add if doesn't exists in the set
31+
Gatherer.Integrator.ofGreedy((state, element, downstream) -> {
32+
if (state.contains(element)) {
33+
// ask for the next element if the downstream is on
34+
return !downstream.isRejecting();
35+
}
36+
state.add(element);
37+
// pushes downstream and ask for more if the downstream is on
38+
return downstream.push(element);
39+
})
40+
);
41+
}
42+
43+
static void filterIfHasAtLeastFiveEvenNumbers() {
44+
var list = Stream.generate(() -> (int) (Math.random() * 10) + 1)
45+
.limit(10)
46+
.gather(filterAtLeastFiveEvenNumbers())
47+
.collect(toList());
48+
if (list.isEmpty())
49+
System.out.println("There were not enough even numbers");
50+
else
51+
System.out.println("Even numbers: " + list);
52+
}
53+
54+
static Gatherer<Integer, List<Integer>, Integer> filterAtLeastFiveEvenNumbers() {
55+
return Gatherer.of(
56+
// initializer: start a new list
57+
LinkedList::new,
58+
// integrator: only add if it is an even number, also increments
59+
(state, element, downstream) -> {
60+
if (element % 2 == 0) {
61+
state.add(element);
62+
}
63+
return !downstream.isRejecting();
64+
},
65+
// combiner: merge the parallel gathering
66+
(leftState, rightState) -> {
67+
leftState.addAll(rightState);
68+
return leftState;
69+
},
70+
// finisher: only pushes if has at least five even numbers
71+
(state, downstream) -> {
72+
if (state.size() < 5) {
73+
return;
74+
}
75+
state.forEach(i -> {
76+
downstream.push(i);
77+
});
78+
}
79+
);
80+
}
81+
}

0 commit comments

Comments
 (0)