Skip to content

Commit 1c21d2d

Browse files
authored
Merge pull request #6 from lokic/dev/stream-ex
Dev/stream ex
2 parents dac8fde + ac82945 commit 1c21d2d

File tree

10 files changed

+703
-75
lines changed

10 files changed

+703
-75
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.github.lokic</groupId>
88
<artifactId>java-plus</artifactId>
9-
<version>0.3.1</version>
9+
<version>0.4.0</version>
1010
<name>java-plus</name>
1111
<description>Provide some useful extensions on the basis of java8 to make java more usable.</description>
1212
<url>https://github.com/lokic/java-plus</url>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.github.lokic.javaplus;
22

33
import java.util.ArrayList;
4+
import java.util.Collections;
45
import java.util.List;
56
import java.util.stream.Stream;
67

78
public class NullData {
8-
private static final List<?> NULL_LIST = createNullList();
9+
private static final List<?> NULL_LIST = Collections.unmodifiableList(createNullList());
910

1011
private static <T> List<T> createNullList() {
1112
List<T> li = new ArrayList<>();

src/main/java/com/github/lokic/javaplus/Collectors.java renamed to src/main/java/com/github/lokic/javaplus/OtherCollectors.java

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,32 @@
44
import com.github.lokic.javaplus.tuple.Tuple;
55
import com.github.lokic.javaplus.tuple.Tuple2;
66

7+
import java.math.BigDecimal;
8+
import java.math.RoundingMode;
79
import java.util.*;
8-
import java.util.function.BinaryOperator;
9-
import java.util.function.Function;
10-
import java.util.function.Supplier;
10+
import java.util.function.*;
1111
import java.util.stream.Collector;
1212
import java.util.stream.Stream;
1313

14-
public class Collectors {
14+
public class OtherCollectors {
15+
16+
17+
public static final Set<Collector.Characteristics> CH_CONCURRENT_ID
18+
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
19+
Collector.Characteristics.UNORDERED,
20+
Collector.Characteristics.IDENTITY_FINISH));
21+
public static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
22+
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
23+
Collector.Characteristics.UNORDERED));
24+
public static final Set<Collector.Characteristics> CH_ID
25+
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
26+
public static final Set<Collector.Characteristics> CH_UNORDERED_ID
27+
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
28+
Collector.Characteristics.IDENTITY_FINISH));
29+
public static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
30+
public static final Set<Collector.Characteristics> CH_UNORDERED_NOID
31+
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED));
32+
1533

1634
public static class Reversed {
1735

@@ -193,4 +211,127 @@ private enum Order {
193211
java.util.stream.Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapSupplier),
194212
m -> m.entrySet().stream().map(e -> Tuple.of(e.getKey(), e.getValue())));
195213
}
214+
215+
@SuppressWarnings("unchecked")
216+
private static <I, R> Function<I, R> castingIdentity() {
217+
return i -> (R) i;
218+
}
219+
220+
/**
221+
* Simple implementation class for {@code Collector}.
222+
*
223+
* @param <T> the type of elements to be collected
224+
* @param <R> the type of the result
225+
*/
226+
public static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
227+
private final Supplier<A> supplier;
228+
private final BiConsumer<A, T> accumulator;
229+
private final BinaryOperator<A> combiner;
230+
private final Function<A, R> finisher;
231+
private final Set<Characteristics> characteristics;
232+
233+
CollectorImpl(Supplier<A> supplier,
234+
BiConsumer<A, T> accumulator,
235+
BinaryOperator<A> combiner,
236+
Function<A, R> finisher,
237+
Set<Characteristics> characteristics) {
238+
this.supplier = supplier;
239+
this.accumulator = accumulator;
240+
this.combiner = combiner;
241+
this.finisher = finisher;
242+
this.characteristics = characteristics;
243+
}
244+
245+
public CollectorImpl(Supplier<A> supplier,
246+
BiConsumer<A, T> accumulator,
247+
BinaryOperator<A> combiner,
248+
Set<Characteristics> characteristics) {
249+
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
250+
}
251+
252+
@Override
253+
public BiConsumer<A, T> accumulator() {
254+
return accumulator;
255+
}
256+
257+
@Override
258+
public Supplier<A> supplier() {
259+
return supplier;
260+
}
261+
262+
@Override
263+
public BinaryOperator<A> combiner() {
264+
return combiner;
265+
}
266+
267+
@Override
268+
public Function<A, R> finisher() {
269+
return finisher;
270+
}
271+
272+
@Override
273+
public Set<Characteristics> characteristics() {
274+
return characteristics;
275+
}
276+
}
277+
278+
279+
public static <T, A, R>
280+
Collector<T, ?, R> filtering(Predicate<? super T> predicate,
281+
Collector<? super T, A, R> downstream) {
282+
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
283+
return Collector.of(downstream.supplier(),
284+
(r, t) -> {
285+
if (predicate.test(t)) {
286+
downstreamAccumulator.accept(r, t);
287+
}
288+
},
289+
downstream.combiner(), downstream.finisher(),
290+
downstream.characteristics().toArray(new Collector.Characteristics[0]));
291+
}
292+
293+
public static <T, U, A, R>
294+
Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
295+
Collector<? super U, A, R> downstream) {
296+
BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
297+
return Collector.of(downstream.supplier(),
298+
(r, t) -> {
299+
try (Stream<? extends U> result = mapper.apply(t)) {
300+
if (result != null)
301+
result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
302+
}
303+
},
304+
downstream.combiner(), downstream.finisher(),
305+
downstream.characteristics().toArray(new Collector.Characteristics[0]));
306+
}
307+
308+
public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(Function<? super T, BigDecimal> mapper) {
309+
return new CollectorImpl<>(
310+
() -> new BigDecimal[]{BigDecimal.ZERO},
311+
(a, t) -> a[0] = a[0].add(mapper.apply(t)),
312+
(a, b) -> {
313+
a[0] = a[0].add(b[0]);
314+
return a;
315+
},
316+
a -> a[0], CH_NOID);
317+
}
318+
319+
320+
public static <T> Collector<T, ?, BigDecimal> averagingBigDecimal(Function<? super T, BigDecimal> mapper, int scale, RoundingMode roundingMode) {
321+
return new CollectorImpl<>(
322+
() -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO},
323+
(a, t) -> {
324+
a[0] = a[0].add(mapper.apply(t));
325+
a[1] = a[1].add(BigDecimal.ONE);
326+
},
327+
(a, b) -> {
328+
a[0] = a[0].add(b[0]);
329+
a[1] = a[1].add(b[1]);
330+
return a;
331+
},
332+
a -> (a[1].compareTo(BigDecimal.ZERO) == 0) ? BigDecimal.ZERO.setScale(scale, roundingMode) : a[0].divide(a[1], scale, roundingMode),
333+
CH_NOID);
334+
}
335+
336+
196337
}

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.github.lokic.javaplus;
22

33
import java.util.Set;
4+
import java.util.Spliterator;
5+
import java.util.Spliterators;
46
import java.util.concurrent.ConcurrentHashMap;
7+
import java.util.function.Consumer;
58
import java.util.function.Function;
69
import java.util.function.Predicate;
10+
import java.util.stream.Stream;
11+
import java.util.stream.StreamSupport;
712

813
public class Predicates {
914

@@ -17,4 +22,67 @@ public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor
1722
return object -> seen.add(keyExtractor.apply(object));
1823
}
1924

25+
/**
26+
* 获取数据,直到{@code predicate}为false
27+
* <p>
28+
* stream : "1", "2", "3", "", "5", "6"
29+
* predicate: isNotEmpty
30+
* result: "1", "2", "3"
31+
*
32+
* @param stream
33+
* @param predicate
34+
* @param <T>
35+
* @return
36+
*/
37+
public static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
38+
Spliterator<T> spliterator = stream.spliterator();
39+
return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(spliterator.estimateSize(), 0) {
40+
private boolean stillGoing = true;
41+
42+
@Override
43+
public boolean tryAdvance(Consumer<? super T> action) {
44+
boolean hasNext = spliterator.tryAdvance(item -> {
45+
if (predicate.test(item)) {
46+
action.accept(item);
47+
} else {
48+
stillGoing = false;
49+
}
50+
});
51+
return hasNext && stillGoing;
52+
}
53+
}, false);
54+
}
55+
56+
/**
57+
* 抛弃数据,直到{@code predicate}为false
58+
* <p>
59+
* stream : "1", "2", "3", "", "5", "6"
60+
* predicate: isNotEmpty
61+
* result: "", "5", "6"
62+
*
63+
* @param stream
64+
* @param predicate
65+
* @param <T>
66+
* @return
67+
*/
68+
public static <T> Stream<T> dropWhile(Stream<T> stream, Predicate<? super T> predicate) {
69+
Spliterator<T> spliterator = stream.spliterator();
70+
return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(spliterator.estimateSize(), 0) {
71+
private boolean canGo = false;
72+
73+
@Override
74+
public boolean tryAdvance(Consumer<? super T> action) {
75+
return spliterator.tryAdvance(item -> {
76+
if (!canGo) {
77+
if (!predicate.test(item)) {
78+
action.accept(item);
79+
canGo = true;
80+
}
81+
} else {
82+
action.accept(item);
83+
}
84+
});
85+
}
86+
}, false);
87+
}
2088
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.github.lokic.javaplus;
2+
3+
import com.github.lokic.javaplus.tuple.*;
4+
5+
import java.util.LinkedHashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Objects;
9+
import java.util.stream.Collector;
10+
11+
import static com.github.lokic.javaplus.OtherCollectors.filtering;
12+
13+
public class TupleCollectors {
14+
15+
public static <T1, T2>
16+
Collector<Tuple2<T1, T2>, ?, Map<T1, List<T2>>> groupingBy1() {
17+
return java.util.stream.Collectors.groupingBy(
18+
Tuple2::getT1,
19+
LinkedHashMap::new,
20+
java.util.stream.Collectors.mapping(Tuple2::getT2, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
21+
}
22+
23+
public static <T1, T2, T3>
24+
Collector<Tuple3<T1, T2, T3>, ?, Map<Tuple2<T1, T2>, List<T3>>> groupingBy2() {
25+
return java.util.stream.Collectors.groupingBy(
26+
t -> Tuple.of(t.getT1(), t.getT2()),
27+
LinkedHashMap::new,
28+
java.util.stream.Collectors.mapping(Tuple3::getT3, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
29+
}
30+
31+
public static <T1, T2, T3, T4>
32+
Collector<Tuple4<T1, T2, T3, T4>, ?, Map<Tuple3<T1, T2, T3>, List<T4>>> groupingBy3() {
33+
return java.util.stream.Collectors.groupingBy(
34+
t -> Tuple.of(t.getT1(), t.getT2(), t.getT3()),
35+
LinkedHashMap::new,
36+
java.util.stream.Collectors.mapping(Tuple4::getT4, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
37+
}
38+
39+
public static <T1, T2, T3, T4, T5>
40+
Collector<Tuple5<T1, T2, T3, T4, T5>, ?, Map<Tuple4<T1, T2, T3, T4>, List<T5>>> groupingBy4() {
41+
return java.util.stream.Collectors.groupingBy(
42+
t -> Tuple.of(t.getT1(), t.getT2(), t.getT3(), t.getT4()),
43+
LinkedHashMap::new,
44+
java.util.stream.Collectors.mapping(Tuple5::getT5, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
45+
}
46+
47+
public static <T1, T2, T3, T4, T5, T6>
48+
Collector<Tuple6<T1, T2, T3, T4, T5, T6>, ?, Map<Tuple5<T1, T2, T3, T4, T5>, List<T6>>> groupingBy5() {
49+
return java.util.stream.Collectors.groupingBy(
50+
t -> Tuple.of(t.getT1(), t.getT2(), t.getT3(), t.getT4(), t.getT5()),
51+
LinkedHashMap::new,
52+
java.util.stream.Collectors.mapping(Tuple6::getT6, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
53+
}
54+
55+
public static <T1, T2, T3, T4, T5, T6, T7>
56+
Collector<Tuple7<T1, T2, T3, T4, T5, T6, T7>, ?, Map<Tuple6<T1, T2, T3, T4, T5, T6>, List<T7>>> groupingBy6() {
57+
return java.util.stream.Collectors.groupingBy(
58+
t -> Tuple.of(t.getT1(), t.getT2(), t.getT3(), t.getT4(), t.getT5(), t.getT6()),
59+
LinkedHashMap::new,
60+
java.util.stream.Collectors.mapping(Tuple7::getT7, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
61+
}
62+
63+
public static <T1, T2, T3, T4, T5, T6, T7, T8>
64+
Collector<Tuple8<T1, T2, T3, T4, T5, T6, T7, T8>, ?, Map<Tuple7<T1, T2, T3, T4, T5, T6, T7>, List<T8>>> groupingBy7() {
65+
return java.util.stream.Collectors.groupingBy(
66+
t -> Tuple.of(t.getT1(), t.getT2(), t.getT3(), t.getT4(), t.getT5(), t.getT6(), t.getT7()),
67+
LinkedHashMap::new,
68+
java.util.stream.Collectors.mapping(Tuple8::getT8, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
69+
}
70+
71+
public static <T1, T2, T3, T4, T5, T6, T7, T8, T9>
72+
Collector<Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9>, ?, Map<Tuple8<T1, T2, T3, T4, T5, T6, T7, T8>, List<T9>>> groupingBy8() {
73+
return java.util.stream.Collectors.groupingBy(
74+
t -> Tuple.of(t.getT1(), t.getT2(), t.getT3(), t.getT4(), t.getT5(), t.getT6(), t.getT7(), t.getT8()),
75+
LinkedHashMap::new,
76+
java.util.stream.Collectors.mapping(Tuple9::getT9, filtering(Objects::nonNull, java.util.stream.Collectors.toList())));
77+
}
78+
79+
80+
}

0 commit comments

Comments
 (0)