Skip to content

Commit 850d9af

Browse files
committed
feat: 支持多join场景
1 parent 781b96e commit 850d9af

3 files changed

Lines changed: 137 additions & 24 deletions

File tree

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

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.github.lokic.javaplus.tuple.Tuple;
44
import com.github.lokic.javaplus.tuple.Tuple2;
5-
65
import java.util.ArrayList;
76
import java.util.List;
87
import java.util.Map;
@@ -32,8 +31,41 @@ public static <T1, T2> JoinType<T1, T2> fullOuterJoin(Stream<T1> left, Stream<T2
3231
return new JoinType<>(left, right, t -> !(t.getT1() == null && t.getT2() == null));
3332
}
3433

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

3667
public static class JoinType<T1, T2> {
68+
3769
private final Stream<Tuple2<T1, T2>> leftWrappedStream;
3870
private final Stream<Tuple2<T1, T2>> rightWrappedStream;
3971
private final Predicate<Tuple2<T1, T2>> joinMatcher;
@@ -44,13 +76,14 @@ public JoinType(Stream<T1> left, Stream<T2> right, Predicate<Tuple2<T1, T2>> joi
4476
this.joinMatcher = joinMatcher;
4577
}
4678

47-
public <K> Stream<Tuple2<T1, T2>> on(Function<T1, K> leftKey, Function<T2, K> rightKey) {
48-
return Stream.concat(leftWrappedStream, rightWrappedStream)
49-
.collect(Collectors.groupingBy(t -> matchKey(t, leftKey, rightKey)))
50-
.values()
51-
.stream()
52-
.flatMap(this::cartesian)
53-
.filter(this.joinMatcher);
79+
public <K> JoinStream<T1, T2> on(Function<T1, K> leftKey, Function<T2, K> rightKey) {
80+
Stream<Tuple2<T1, T2>> stream = Stream.concat(leftWrappedStream, rightWrappedStream)
81+
.collect(Collectors.groupingBy(t -> matchKey(t, leftKey, rightKey)))
82+
.values()
83+
.stream()
84+
.flatMap(this::cartesian)
85+
.filter(this.joinMatcher);
86+
return new JoinStream<>(stream);
5487
}
5588

5689
private Stream<Tuple2<T1, T2>> cartesian(List<Tuple2<T1, T2>> li) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.github.lokic.javaplus.functional.tuple;
2+
3+
import com.github.lokic.javaplus.tuple.Tuple;
4+
import com.github.lokic.javaplus.tuple.Tuple2;
5+
import com.github.lokic.javaplus.tuple.Tuple3;
6+
import com.github.lokic.javaplus.tuple.Tuple4;
7+
import com.github.lokic.javaplus.tuple.Tuple5;
8+
import com.github.lokic.javaplus.tuple.Tuple6;
9+
10+
public class TupleFlattened {
11+
12+
public static <T1, T2, T3> Tuple3<T1, T2, T3> flatten3(Tuple2<Tuple2<T1, T2>, T3> t) {
13+
return Tuple.of(
14+
t.getT1().getT1(),
15+
t.getT1().getT2(),
16+
t.getT2());
17+
}
18+
19+
public static <T1, T2, T3, T4> Tuple4<T1, T2, T3, T4> flatten4(
20+
Tuple2<Tuple2<Tuple2<T1, T2>, T3>, T4> t) {
21+
return Tuple.of(
22+
t.getT1().getT1().getT1(),
23+
t.getT1().getT1().getT2(),
24+
t.getT1().getT2(),
25+
t.getT2());
26+
}
27+
28+
public static <T1, T2, T3, T4, T5> Tuple5<T1, T2, T3, T4, T5> flatten5(
29+
Tuple2<Tuple2<Tuple2<Tuple2<T1, T2>, T3>, T4>, T5> t) {
30+
return Tuple.of(
31+
t.getT1().getT1().getT1().getT1(),
32+
t.getT1().getT1().getT1().getT2(),
33+
t.getT1().getT1().getT2(),
34+
t.getT1().getT2(),
35+
t.getT2());
36+
}
37+
38+
public static <T1, T2, T3, T4, T5, T6> Tuple6<T1, T2, T3, T4, T5, T6> flatten6(
39+
Tuple2<Tuple2<Tuple2<Tuple2<Tuple2<T1, T2>, T3>, T4>, T5>, T6> t) {
40+
return Tuple.of(
41+
t.getT1().getT1().getT1().getT1().getT1(),
42+
t.getT1().getT1().getT1().getT1().getT2(),
43+
t.getT1().getT1().getT1().getT2(),
44+
t.getT1().getT1().getT2(),
45+
t.getT1().getT2(),
46+
t.getT2());
47+
}
48+
}
Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
package com.github.lokic.javaplus;
22

3+
import com.github.lokic.javaplus.functional.tuple.TupleFlattened;
4+
import com.github.lokic.javaplus.functional.tuple.TupleFunctional;
35
import com.github.lokic.javaplus.tuple.Tuple;
46
import com.github.lokic.javaplus.tuple.Tuple2;
5-
import org.assertj.core.api.Assertions;
6-
import org.junit.Test;
7-
7+
import com.github.lokic.javaplus.tuple.Tuple3;
88
import java.util.List;
99
import java.util.function.Function;
1010
import java.util.stream.Collectors;
1111
import java.util.stream.Stream;
12+
import org.assertj.core.api.Assertions;
13+
import org.junit.Test;
1214

1315
public class JoinTest {
1416

1517
@Test
1618
public void test_innerJoin() {
17-
List<Tuple2<Integer, String>> list = Join.innerJoin(Stream.of(1, 2, 3, 4), Stream.of("2", "3", "5"))
18-
.on(String::valueOf, Function.identity())
19+
List<Tuple2<Integer, String>> list = Join.innerJoin(Stream.of(1, 2, 3, 4),
20+
Stream.of("2", "3", "5"))
21+
.on(String::valueOf, Function.identity())
22+
.stream()
1923
.collect(Collectors.toList());
2024

2125
Assertions.assertThat(list)
@@ -24,8 +28,10 @@ public void test_innerJoin() {
2428

2529
@Test
2630
public void test_innerJoin_repeatKey() {
27-
List<Tuple2<Integer, String>> list = Join.innerJoin(Stream.of(1, 2, 2, 3, 4), Stream.of("2", "3", "5"))
28-
.on(String::valueOf, Function.identity())
31+
List<Tuple2<Integer, String>> list = Join.innerJoin(Stream.of(1, 2, 2, 3, 4),
32+
Stream.of("2", "3", "5"))
33+
.on(String::valueOf, Function.identity())
34+
.stream()
2935
.collect(Collectors.toList());
3036

3137
Assertions.assertThat(list)
@@ -34,8 +40,10 @@ public void test_innerJoin_repeatKey() {
3440

3541
@Test
3642
public void test_leftOuterJoin() {
37-
List<Tuple2<Integer, String>> list = Join.leftOuterJoin(Stream.of(1, 2, 3, 4), Stream.of("2", "3", "5"))
38-
.on(String::valueOf, Function.identity())
43+
List<Tuple2<Integer, String>> list = Join.leftOuterJoin(Stream.of(1, 2, 3, 4),
44+
Stream.of("2", "3", "5"))
45+
.on(String::valueOf, Function.identity())
46+
.stream()
3947
.collect(Collectors.toList());
4048

4149
Assertions.assertThat(list)
@@ -44,8 +52,10 @@ public void test_leftOuterJoin() {
4452

4553
@Test
4654
public void test_leftOuterJoin_empty() {
47-
List<Tuple2<Integer, String>> list = Join.leftOuterJoin(Stream.of(1, 2, 3, 4), Stream.<String>empty())
48-
.on(String::valueOf, Function.identity())
55+
List<Tuple2<Integer, String>> list = Join.leftOuterJoin(Stream.of(1, 2, 3, 4),
56+
Stream.<String>empty())
57+
.on(String::valueOf, Function.identity())
58+
.stream()
4959
.collect(Collectors.toList());
5060

5161
Assertions.assertThat(list)
@@ -54,8 +64,10 @@ public void test_leftOuterJoin_empty() {
5464

5565
@Test
5666
public void test_rightOuterJoin() {
57-
List<Tuple2<Integer, String>> list = Join.rightOuterJoin(Stream.of(1, 2, 3, 4), Stream.of("2", "3", "5"))
58-
.on(String::valueOf, Function.identity())
67+
List<Tuple2<Integer, String>> list = Join.rightOuterJoin(Stream.of(1, 2, 3, 4),
68+
Stream.of("2", "3", "5"))
69+
.on(String::valueOf, Function.identity())
70+
.stream()
5971
.collect(Collectors.toList());
6072

6173
Assertions.assertThat(list)
@@ -65,12 +77,32 @@ public void test_rightOuterJoin() {
6577

6678
@Test
6779
public void test_fullOuterJoin() {
68-
List<Tuple2<Integer, String>> list = Join.fullOuterJoin(Stream.of(1, 2, 3, 4), Stream.of("2", "3", "5"))
80+
List<Tuple2<Integer, String>> list = Join.fullOuterJoin(Stream.of(1, 2, 3, 4),
81+
Stream.of("2", "3", "5"))
82+
.on(String::valueOf, Function.identity())
83+
.stream()
84+
.collect(Collectors.toList());
85+
86+
Assertions.assertThat(list)
87+
.containsExactly(Tuple.of(1, null), Tuple.of(2, "2"), Tuple.of(3, "3"),
88+
Tuple.of(4, null), Tuple.of(null, "5"));
89+
}
90+
91+
@Test
92+
public void test_joinStream_leftOuterJoin() {
93+
List<Tuple3<Integer, String, String>> list =
94+
Join.leftOuterJoin(Stream.of(1, 2, 3, 4), Stream.of("2", "3", "5"))
6995
.on(String::valueOf, Function.identity())
96+
.leftOuterJoin(Stream.of("1"))
97+
.on(TupleFunctional.function((a, b) -> String.valueOf(a)), Function.identity())
98+
.flattenStream(TupleFlattened::flatten3)
7099
.collect(Collectors.toList());
71100

72101
Assertions.assertThat(list)
73-
.containsExactly(Tuple.of(1, null), Tuple.of(2, "2"), Tuple.of(3, "3"), Tuple.of(4, null), Tuple.of(null, "5"));
102+
.containsExactly(
103+
Tuple.of(1, null, "1"),
104+
Tuple.of(2, "2", null),
105+
Tuple.of(3, "3", null),
106+
Tuple.of(4, null, null));
74107
}
75-
76108
}

0 commit comments

Comments
 (0)