Skip to content

Commit 8323b3d

Browse files
authored
Merge pull request #3 from lokic/dev/0.0.16
Dev/0.0.16
2 parents 2436131 + 4ad5384 commit 8323b3d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+972
-99
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.0.15</version>
9+
<version>0.0.16-SNAPSHOT</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/Collectors.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ private enum Order {
124124
}
125125
}
126126

127+
public static <K, U, M extends Map<K, U>>
128+
Collector<Map.Entry<K, U>, ?, M> toMap(Supplier<M> mapSupplier) {
129+
return toMap(Map.Entry::getValue, mapSupplier);
130+
}
131+
132+
public static <T, K, U, M extends Map<K, T>>
133+
Collector<Map.Entry<K, U>, ?, M> toMap(
134+
Function<? super Map.Entry<K, U>, ? extends T> valueMapper, Supplier<M> mapSupplier) {
135+
return java.util.stream.Collectors.toMap(
136+
Map.Entry::getKey, valueMapper,
137+
(u, v) -> {
138+
throw new IllegalStateException(String.format("Duplicate key %s", u));
139+
},
140+
mapSupplier);
141+
}
142+
127143
public static <T1, T2, K, U, M extends Map<K, U>>
128144
Collector<Tuple2<T1, T2>, ?, M> toMap(
129145
Function2<? super T1, ? super T2, ? extends K> keyMapper,
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.github.lokic.javaplus;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.ToString;
5+
6+
import java.io.Serializable;
7+
import java.util.NoSuchElementException;
8+
import java.util.function.Function;
9+
10+
public interface Either<L, R> {
11+
12+
static <L, R> Either<L, R> left(L left) {
13+
return new Left<>(left);
14+
}
15+
16+
static <L, R> Either<L, R> right(R right) {
17+
return new Right<>(right);
18+
}
19+
20+
L getLeft();
21+
22+
R getRight();
23+
24+
boolean isLeft();
25+
26+
boolean isRight();
27+
28+
@SuppressWarnings("unchecked")
29+
default <U> Either<L, U> flatMap(Function<? super R, ? extends Either<L, ? extends U>> mapper) {
30+
if (isRight()) {
31+
return (Either<L, U>) mapper.apply(getRight());
32+
} else {
33+
return (Either<L, U>) this;
34+
}
35+
}
36+
37+
@ToString
38+
@EqualsAndHashCode
39+
final class Left<L, R> implements Either<L, R>, Serializable {
40+
41+
private static final long serialVersionUID = 1L;
42+
43+
private final L value;
44+
45+
private Left(L value) {
46+
this.value = value;
47+
}
48+
49+
@Override
50+
public L getLeft() {
51+
return value;
52+
}
53+
54+
@Override
55+
public R getRight() {
56+
throw new NoSuchElementException("getRight() at Left");
57+
}
58+
59+
@Override
60+
public boolean isLeft() {
61+
return true;
62+
}
63+
64+
@Override
65+
public boolean isRight() {
66+
return false;
67+
}
68+
}
69+
70+
71+
@ToString
72+
@EqualsAndHashCode
73+
final class Right<L, R> implements Either<L, R>, Serializable {
74+
75+
private static final long serialVersionUID = 1L;
76+
77+
private final R value;
78+
79+
private Right(R value) {
80+
this.value = value;
81+
}
82+
83+
@Override
84+
public L getLeft() {
85+
throw new NoSuchElementException("getLeft() at Right");
86+
}
87+
88+
@Override
89+
public R getRight() {
90+
return value;
91+
}
92+
93+
@Override
94+
public boolean isLeft() {
95+
return false;
96+
}
97+
98+
@Override
99+
public boolean isRight() {
100+
return true;
101+
}
102+
}
103+
104+
}

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

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,41 @@ public static <T1, T2> JoinType<T1, T2> fullOuterJoin(Stream<T1> left, Stream<T2
3232
return new JoinType<>(left, right, t -> !(t.getT1() == null && t.getT2() == null));
3333
}
3434

35+
public static class JoinStream<T1, T2> {
36+
37+
private final Stream<Tuple2<T1, T2>> left;
38+
39+
private JoinStream(Stream<Tuple2<T1, T2>> stream) {
40+
this.left = stream;
41+
}
42+
43+
public Stream<Tuple2<T1, T2>> stream() {
44+
return left;
45+
}
46+
47+
public <R> Stream<R> flattenStream(Function<? super Tuple2<T1, T2>, ? extends R> mapper) {
48+
return left.map(mapper);
49+
}
50+
51+
public <T3> JoinType<Tuple2<T1, T2>, T3> innerJoin(Stream<T3> right) {
52+
return Join.innerJoin(left, right);
53+
}
54+
55+
public <T3> JoinType<Tuple2<T1, T2>, T3> leftOuterJoin(Stream<T3> right) {
56+
return Join.leftOuterJoin(left, right);
57+
}
58+
59+
public <T3> JoinType<Tuple2<T1, T2>, T3> rightOuterJoin(Stream<T3> right) {
60+
return Join.rightOuterJoin(left, right);
61+
}
62+
63+
public <T3> JoinType<Tuple2<T1, T2>, T3> fullOuterJoin(Stream<T3> right) {
64+
return Join.fullOuterJoin(left, right);
65+
}
66+
}
3567

3668
public static class JoinType<T1, T2> {
69+
3770
private final Stream<Tuple2<T1, T2>> leftWrappedStream;
3871
private final Stream<Tuple2<T1, T2>> rightWrappedStream;
3972
private final Predicate<Tuple2<T1, T2>> joinMatcher;
@@ -44,15 +77,22 @@ public JoinType(Stream<T1> left, Stream<T2> right, Predicate<Tuple2<T1, T2>> joi
4477
this.joinMatcher = joinMatcher;
4578
}
4679

47-
public <K> Stream<Tuple2<T1, T2>> on(Function<T1, K> leftKey, Function<T2, K> rightKey) {
48-
return Stream.concat(leftWrappedStream, rightWrappedStream)
80+
public <K> JoinStream<T1, T2> on(Function<T1, K> leftKey, Function<T2, K> rightKey) {
81+
Stream<Tuple2<T1, T2>> stream = Stream.concat(leftWrappedStream, rightWrappedStream)
4982
.collect(Collectors.groupingBy(t -> matchKey(t, leftKey, rightKey)))
5083
.values()
5184
.stream()
5285
.flatMap(this::cartesian)
5386
.filter(this.joinMatcher);
87+
return new JoinStream<>(stream);
5488
}
5589

90+
/**
91+
* 笛卡尔积化
92+
*
93+
* @param li
94+
* @return
95+
*/
5696
private Stream<Tuple2<T1, T2>> cartesian(List<Tuple2<T1, T2>> li) {
5797
Map<Boolean, List<Tuple2<T1, T2>>> map = li.stream()
5898
.collect(Collectors.partitioningBy(this::isLeft, this.toListOrNullList()));
@@ -91,18 +131,14 @@ private <T> Collector<T, List<T>, List<T>> toListOrNullList() {
91131
},
92132
l -> {
93133
if (l == null || l.isEmpty()) {
94-
return nullList();
134+
return NullData.nullList();
95135
}
96136
return l;
97137
}
98138
);
99139
}
100140

101-
private <T> List<T> nullList() {
102-
List<T> li = new ArrayList<>();
103-
li.add(null);
104-
return li;
105-
}
141+
106142
}
107143

108144
}

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 java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.stream.Stream;
6+
7+
class NullData {
8+
private static final List<?> NULL_LIST = createNullList();
9+
10+
private static <T> List<T> createNullList() {
11+
List<T> li = new ArrayList<>();
12+
li.add(null);
13+
return li;
14+
}
15+
16+
public static <T> Stream<T> nullStream() {
17+
return NullData.<T>nullList().stream();
18+
}
19+
20+
public static <T> List<T> nullList() {
21+
@SuppressWarnings("unchecked")
22+
List<T> l = (List<T>) NULL_LIST;
23+
return l;
24+
}
25+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
package com.github.lokic.javaplus.functional.consumer;
22

3+
import java.util.function.Consumer;
4+
35
@FunctionalInterface
46
public interface Consumer2<T1, T2> {
57
void accept(T1 t1, T2 t2);
8+
9+
static <T1, T2> Consumer2<T1, T2> $1(Consumer<T1> consumer) {
10+
return (t1, t2) -> consumer.accept(t1);
11+
}
12+
13+
static <T1, T2> Consumer2<T1, T2> $2(Consumer<T2> consumer) {
14+
return (t1, t2) -> consumer.accept(t2);
15+
}
616
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
package com.github.lokic.javaplus.functional.consumer;
22

3+
import java.util.function.Consumer;
4+
35
@FunctionalInterface
46
public interface Consumer3<T1, T2, T3> {
57
void accept(T1 t1, T2 t2, T3 t3);
8+
9+
10+
static <T1, T2, T3> Consumer3<T1, T2, T3> $1(Consumer<T1> consumer) {
11+
return (t1, t2, t3) -> consumer.accept(t1);
12+
}
13+
14+
static <T1, T2, T3> Consumer3<T1, T2, T3> $2(Consumer<T2> consumer) {
15+
return (t1, t2, t3) -> consumer.accept(t2);
16+
}
17+
18+
static <T1, T2, T3> Consumer3<T1, T2, T3> $3(Consumer<T3> consumer) {
19+
return (t1, t2, t3) -> consumer.accept(t3);
20+
}
621
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
package com.github.lokic.javaplus.functional.consumer;
22

3+
import java.util.function.Consumer;
4+
35
@FunctionalInterface
46
public interface Consumer4<T1, T2, T3, T4> {
57
void accept(T1 t1, T2 t2, T3 t3, T4 t4);
8+
9+
static <T1, T2, T3, T4> Consumer4<T1, T2, T3, T4> $1(Consumer<T1> consumer) {
10+
return (t1, t2, t3, t4) -> consumer.accept(t1);
11+
}
12+
13+
static <T1, T2, T3, T4> Consumer4<T1, T2, T3, T4> $2(Consumer<T2> consumer) {
14+
return (t1, t2, t3, t4) -> consumer.accept(t2);
15+
}
16+
17+
static <T1, T2, T3, T4> Consumer4<T1, T2, T3, T4> $3(Consumer<T3> consumer) {
18+
return (t1, t2, t3, t4) -> consumer.accept(t3);
19+
}
20+
21+
static <T1, T2, T3, T4> Consumer4<T1, T2, T3, T4> $4(Consumer<T4> consumer) {
22+
return (t1, t2, t3, t4) -> consumer.accept(t4);
23+
}
624
}

src/main/java/com/github/lokic/javaplus/functional/entry/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* .stream()
1212
* .map((EntryFunction<Integer, String, String>) (index, desc) -> a + b))
1313
* }</pre>
14-
*
14+
* <p>
1515
* 或者
1616
* <pre>{@code
1717
* Map<Integer, String> map = ...

0 commit comments

Comments
 (0)