1
1
package com .github .lokic .javaplus .join ;
2
2
3
+ import com .github .lokic .javaplus .Functions ;
3
4
import com .github .lokic .javaplus .NullData ;
4
5
import com .github .lokic .javaplus .tuple .Tuple ;
5
6
import com .github .lokic .javaplus .tuple .Tuple2 ;
13
14
14
15
public class JoinType <T1 , T2 > {
15
16
16
- private final Stream <Tuple2 <T1 , T2 >> leftWrappedStream ;
17
- private final Stream <Tuple2 <T1 , T2 >> rightWrappedStream ;
17
+ private final Stream <Tuple2 <Integer , Tuple2 < T1 , T2 > >> leftWrappedStream ;
18
+ private final Stream <Tuple2 <Integer , Tuple2 < T1 , T2 > >> rightWrappedStream ;
18
19
private final Predicate <Tuple2 <T1 , T2 >> joinMatcher ;
19
20
20
21
JoinType (Stream <T1 > left , Stream <T2 > right , Predicate <Tuple2 <T1 , T2 >> joinMatcher ) {
21
- this .leftWrappedStream = left .map (l -> Tuple .of (Objects .requireNonNull (l ), null ));
22
- this .rightWrappedStream = right .map (r -> Tuple .of (null , Objects .requireNonNull (r )));
22
+ this .leftWrappedStream = left .map (l -> Tuple .of (Objects .requireNonNull (l ), ( T2 ) null )). map ( Functions . mapWithIndex ( Tuple :: of ));
23
+ this .rightWrappedStream = right .map (r -> Tuple .of (( T1 ) null , Objects .requireNonNull (r ))). map ( Functions . mapWithIndex ( Tuple :: of ));
23
24
this .joinMatcher = joinMatcher ;
24
25
}
25
26
26
27
public <K > JoinStream <Tuple2 <T1 , T2 >> on (Function <T1 , K > leftKey , Function <T2 , K > rightKey ) {
27
28
Stream <Tuple2 <T1 , T2 >> stream = Stream .concat (leftWrappedStream , rightWrappedStream )
28
29
.collect (Collectors .toMap (
29
- t -> matchKey (t , leftKey , rightKey ),
30
+ t -> matchKey (t . getT2 () , leftKey , rightKey ),
30
31
Collections ::singletonList ,
31
32
(a , b ) -> {
32
- List <Tuple2 <T1 , T2 >> li = new ArrayList <>();
33
+ List <Tuple2 <Integer , Tuple2 < T1 , T2 > >> li = new ArrayList <>();
33
34
li .addAll (a );
34
35
li .addAll (b );
35
36
return li ;
@@ -39,7 +40,9 @@ public <K> JoinStream<Tuple2<T1, T2>> on(Function<T1, K> leftKey, Function<T2, K
39
40
.values ()
40
41
.stream ()
41
42
.flatMap (this ::cartesian )
42
- .filter (this .joinMatcher );
43
+ .sorted (this ::compare )
44
+ .filter (t -> joinMatcher .test (t .getT2 ()))
45
+ .map (Tuple2 ::getT2 );
43
46
return new JoinStream <>(stream );
44
47
}
45
48
@@ -49,18 +52,21 @@ public <K> JoinStream<Tuple2<T1, T2>> on(Function<T1, K> leftKey, Function<T2, K
49
52
* @param li
50
53
* @return
51
54
*/
52
- private Stream <Tuple2 <T1 , T2 >> cartesian (List <Tuple2 <T1 , T2 >> li ) {
53
- Map <Boolean , List <Tuple2 <T1 , T2 >>> map = li .stream ()
54
- .collect (Collectors .partitioningBy (this :: isLeft , this .toListOrNullList ()));
55
- List <Tuple2 <T1 , T2 >> left = map .get (true );
56
- List <Tuple2 <T1 , T2 >> right = map .get (false );
55
+ private Stream <Tuple2 <Tuple2 < Integer , Integer >, Tuple2 < T1 , T2 >>> cartesian (List <Tuple2 <Integer , Tuple2 < T1 , T2 > >> li ) {
56
+ Map <Boolean , List <Tuple2 <Integer , Tuple2 < T1 , T2 > >>> map = li .stream ()
57
+ .collect (Collectors .partitioningBy (t -> isLeft ( t . getT2 ()) , this .toListOrNullList ()));
58
+ List <Tuple2 <Integer , Tuple2 < T1 , T2 > >> left = map .get (true );
59
+ List <Tuple2 <Integer , Tuple2 < T1 , T2 > >> right = map .get (false );
57
60
return left .stream ()
58
61
.flatMap (l -> right .stream ()
59
62
.map (r -> this .merge (l , r )));
60
63
}
61
64
62
- private Tuple2 <T1 , T2 > merge (Tuple2 <T1 , T2 > l , Tuple2 <T1 , T2 > r ) {
63
- return Tuple .of (l == null ? null : l .getT1 (), r == null ? null : r .getT2 ());
65
+
66
+ private Tuple2 <Tuple2 <Integer , Integer >, Tuple2 <T1 , T2 >> merge (Tuple2 <Integer , Tuple2 <T1 , T2 >> l , Tuple2 <Integer , Tuple2 <T1 , T2 >> r ) {
67
+ return Tuple .of (
68
+ Tuple .of (l == null ? null : l .getT1 (), r == null ? null : r .getT1 ()),
69
+ Tuple .of (l == null ? null : l .getT2 ().getT1 (), r == null ? null : r .getT2 ().getT2 ()));
64
70
}
65
71
66
72
private boolean isLeft (Tuple2 <T1 , T2 > t ) {
@@ -93,4 +99,30 @@ private <T> Collector<T, List<T>, List<T>> toListOrNullList() {
93
99
}
94
100
);
95
101
}
102
+
103
+ private int compare (Tuple2 <Tuple2 <Integer , Integer >, Tuple2 <T1 , T2 >> a , Tuple2 <Tuple2 <Integer , Integer >, Tuple2 <T1 , T2 >> b ) {
104
+ Tuple2 <Integer , Integer > ta = a .getT1 ();
105
+ Tuple2 <Integer , Integer > tb = b .getT1 ();
106
+
107
+ int cmp = compare (ta .getT1 (), tb .getT1 ());
108
+ if (cmp == 0 ) {
109
+ return compare (ta .getT2 (), tb .getT2 ());
110
+ }
111
+ return cmp ;
112
+ }
113
+
114
+
115
+ private int compare (Integer a , Integer b ) {
116
+ if (a == null && b == null ) {
117
+ return 0 ;
118
+ }
119
+ if (a == null ) {
120
+ return 1 ;
121
+ }
122
+ if (b == null ) {
123
+ return -1 ;
124
+ }
125
+ return Integer .compare (a , b );
126
+ }
127
+
96
128
}
0 commit comments