Skip to content

Commit f508750

Browse files
committed
feat: 带缓存功能的Stream,可以多次重发
1 parent e4e31b6 commit f508750

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

src/main/java/com/github/lokic/javaplus/Memoized.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,18 @@
66
import com.github.lokic.javaplus.tuple.Tuple2;
77
import com.github.lokic.javaplus.tuple.Tuple3;
88

9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.Spliterator;
12+
import java.util.Spliterators;
913
import java.util.concurrent.ConcurrentHashMap;
1014
import java.util.concurrent.ConcurrentMap;
15+
import java.util.function.Consumer;
1116
import java.util.function.Function;
17+
import java.util.function.Supplier;
18+
import java.util.stream.Stream;
19+
20+
import static java.util.stream.StreamSupport.stream;
1221

1322
/**
1423
* 对执行的函数提供记忆化的功能,减少相同参数的重复调用
@@ -30,4 +39,41 @@ public static <T1, T2, T3, R> Function3<T1, T2, T3, R> of(Function3<T1, T2, T3,
3039
return (t1, t2, t3) -> cache.computeIfAbsent(Tuple.of(t1, t2, t3), t -> function3.apply(t.getT1(), t.getT2(), t.getT3()));
3140
}
3241

42+
43+
/**
44+
* 带缓存功能,可多次重放Stream
45+
*
46+
* @param streamSupplier
47+
* @param <T>
48+
* @return
49+
*/
50+
public static <T> Supplier<Stream<T>> of(Supplier<Stream<T>> streamSupplier) {
51+
final Spliterator<T> spliterator = streamSupplier.get().spliterator();
52+
final List<T> cache = new ArrayList<>();
53+
return () -> {
54+
Spliterator<T> split = new Spliterators.AbstractSpliterator<T>(
55+
spliterator.estimateSize(), spliterator.characteristics()) {
56+
57+
private int index = 0;
58+
private boolean hasNext = true;
59+
60+
@Override
61+
public boolean tryAdvance(Consumer<? super T> action) {
62+
int currentIndex = index++;
63+
if (currentIndex < cache.size()) {
64+
action.accept(cache.get(currentIndex));
65+
return true;
66+
} else if (hasNext) {
67+
hasNext = spliterator.tryAdvance(item -> {
68+
cache.add(item);
69+
action.accept(item);
70+
});
71+
}
72+
return hasNext;
73+
}
74+
};
75+
return stream(split, false);
76+
};
77+
}
78+
3379
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.github.lokic.javaplus;
2+
3+
import org.assertj.core.api.Assertions;
4+
import org.junit.Test;
5+
6+
import java.util.List;
7+
import java.util.function.Supplier;
8+
import java.util.stream.Collectors;
9+
import java.util.stream.Stream;
10+
11+
public class MemoizedTest {
12+
13+
@Test
14+
public void of_stream() {
15+
Supplier<Stream<Integer>> streamSupplier = Memoized.of(() -> Stream.of(1, 2, 3));
16+
17+
List<Integer> first = streamSupplier.get().collect(Collectors.toList());
18+
Assertions.assertThat(first)
19+
.containsExactly(1, 2, 3);
20+
21+
List<Integer> second = streamSupplier.get().collect(Collectors.toList());
22+
Assertions.assertThat(second)
23+
.containsExactly(1, 2, 3);
24+
}
25+
}

0 commit comments

Comments
 (0)