字段填充工具
# 使用方法
@Slf4j
public class TestFiller {
/**
* 模拟dao 根据用户id列表查询用户
*
* @param ids
* @return
*/
private static List<User> mockDaoQueryUserListByIds(Collection<Integer> ids) {
return ids.stream().map(i -> User.builder().id(i).userName("陈追风" + i + "号").build()).collect(Collectors.toList());
}
public static void main(String[] args) {
StopWatch clock = new StopWatch();
/**
* Customer {id = 1, createUserId = x, updateUserId = x, createUserName = null, updateUserName = null}
*/
Random random = new Random();
clock.start("创建客户列表");
List<Customer> customers = IntStream.rangeClosed(1, 100)
.mapToObj(i -> Customer.builder().id(i).createUserId(random.nextInt(50)).updateUserId(random.nextInt(50)).build())
.collect(Collectors.toList());
clock.stop();
clock.start("开始填充");
Filler.fill(
() -> customers,
Customer::getCreateUserId, Customer::setCreateUserName,
Customer::getUpdateUserId, Customer::setUpdateUserName,
userIds -> Filler.list2Map(mockDaoQueryUserListByIds(userIds), User::getId, User::getUserName)
);
/**
* Customer {id = 1, createUserId = x, updateUserId = x, createUserName = 陈追风x号, updateUserName = 陈追风x号}
*/
clock.stop();
System.out.println(clock.prettyPrint());
System.out.println(clock.getLastTaskTimeMillis());
System.out.println(customers);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# util
import com.google.common.collect.ImmutableMap;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 填充工具类
*/
public class Filler {
static class FillerWorker<IN, R, ID> {
/**
* @param data 源
* @param getter DATA_getter
* @param setter DATA_setter
* @param function DATA_provider
*/
void fill(Supplier<Collection<IN>> data,
Function<IN, ID> getter,
BiConsumer<IN, R> setter,
Function<Collection<ID>, Map<ID, R>> function) {
Collection<IN> collection = data.get();
Collection<ID> ids = collection.stream().map(getter).filter(Objects::nonNull).collect(Collectors.toSet());
Map<ID, R> map = function.apply(ids);
collection.forEach(in ->
Optional.ofNullable(map.get(getter.apply(in)))
.ifPresent(r -> setter.accept(in, r)));
}
/**
* @param data 源
* @param propertiesMap DATA_getter:DATA_setter
* @param function DATA_provider
*/
void fill(Supplier<Collection<IN>> data,
Map<Function<IN, ID>, BiConsumer<IN, R>> propertiesMap,
Function<Collection<ID>, Map<ID, R>> function) {
Collection<IN> collection = data.get();
Collection<ID> ids = propertiesMap.keySet().stream()
.map(getter -> collection.stream().map(getter).filter(Objects::nonNull))
.flatMap(Stream::distinct)
.collect(Collectors.toSet());
Map<ID, R> map = function.apply(ids);
propertiesMap.forEach((getter, setter) ->
collection.forEach(in ->
Optional.ofNullable(map.get(getter.apply(in)))
.ifPresent(r -> setter.accept(in, r))));
}
/**
* @param data 源
* @param propertiesMap DATA_getter:{R_getter:R_setter}
* @param provider DATA_provider
*/
void fillMultiValue(Supplier<Collection<IN>> data,
Map<Function<IN, ID>, Map<Function<R, String>, BiConsumer<IN, String>>> propertiesMap,
Function<Collection<ID>, Map<ID, R>> provider) {
Collection<IN> collection = data.get();
Collection<ID> ids = propertiesMap.keySet().stream()
.map(getter -> collection.stream().map(getter).filter(Objects::nonNull))
.flatMap(Stream::distinct)
.collect(Collectors.toSet());
Map<ID, R> map = provider.apply(ids);
propertiesMap
.forEach((getter, setters) -> collection
.forEach(in -> setters
.forEach((rGetter, rSetter) -> Optional.ofNullable(map.get(getter.apply(in)))
.ifPresent(r -> rSetter.accept(in, rGetter.apply(r))))));
}
/**
* @param data 源
* @param providerMap DATA_getter:DATA_provider
* @param setter Setter
*/
void fillOne(Supplier<Collection<IN>> data,
BiConsumer<IN, R> setter,
Map<Function<IN, ID>, Function<Collection<ID>, Map<ID, R>>> providerMap) {
Collection<IN> collection = data.get();
Map<Function<IN, ID>, Map<ID, R>> getterMap = providerMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, map -> map.getValue().apply(collection.stream().map(map.getKey()).collect(Collectors.toSet()))));
collection.forEach(in -> getterMap.forEach((getter, val) -> Optional.ofNullable(val.get(getter.apply(in))).ifPresent(r -> setter.accept(in, r))));
// getterMap.forEach((getter, val) -> collection.forEach(in -> Optional.ofNullable(val.get(getter.apply(in))).ifPresent(r -> setter.accept(in, r))));
}
/**
* @param data 源
* @param threeTuples DATA_getter:DATA_provider:DATA_setter
*/
void fillOne3(Supplier<Collection<IN>> data,
Collection<ThreeTuple<IN, R, ID>> threeTuples) {
Collection<IN> ins = data.get();
threeTuples.forEach(threeTuple -> {
Collection<ID> ids = ins.stream().map(threeTuple.getGetter()).collect(Collectors.toSet());
Map<ID, R> map = threeTuple.getProvider().apply(ids);
ins.forEach(in -> Optional.ofNullable(map.get(threeTuple.getGetter().apply(in))).ifPresent(r -> threeTuple.getSetter().accept(in, r)));
});
}
}
/**
* @param data 源
* @param setter setter
* @param providerMap getter:DATA_provider
*/
public static <IN, R, ID> void fillOne(Supplier<Collection<IN>> data,
BiConsumer<IN, R> setter,
Map<Function<IN, ID>, Function<Collection<ID>, Map<ID, R>>> providerMap) {
new FillerWorker<IN, R, ID>().fillOne(data, setter, providerMap);
}
/**
* 填充多个值
*
* @param data 源
* @param getter getter
* @param valueMap valueMapping
* @param provider DATA_provider
*/
public static <IN, R, ID> void fillMultiValue(Supplier<Collection<IN>> data,
Function<IN, ID> getter,
Map<Function<R, String>, BiConsumer<IN, String>> valueMap,
Function<Collection<ID>, Map<ID, R>> provider) {
new FillerWorker<IN, R, ID>().fillMultiValue(data, ImmutableMap.of(getter, valueMap), provider);
}
/**
* 填充多个值
*
* @param data
* @param propertiesMap 属性映射map
* @param function 数据源
* @param <IN> 输入
* @param <R> 设置值的类型
*/
public static <IN, R, ID> void fillMultiValue(Supplier<Collection<IN>> data,
Map<Function<IN, ID>, Map<Function<R, String>, BiConsumer<IN, String>>> propertiesMap,
Function<Collection<ID>, Map<ID, R>> function) {
new FillerWorker<IN, R, ID>().fillMultiValue(data, propertiesMap, function);
}
/**
* 对象属性填充 IN { id, R(null) } -> IN { id, R(value) }
*
* @param data
* @param getter 对象数据来源 eg:id / type
* @param setter 对象设值字段
* @param queryData 根据数据来源 转换值 id -> R
* @param <IN> 输入
* @param <R> 设置值的类型
*/
public static <IN, R, ID> void fill(Supplier<Collection<IN>> data,
Function<IN, ID> getter,
BiConsumer<IN, R> setter,
Function<Collection<ID>, Map<ID, R>> queryData) {
new FillerWorker<IN, R, ID>().fill(data, getter, setter, queryData);
}
/**
* 对象属性填充 IN { id, R(null) } -> IN { id, R(value) }
*
* @param data
* @param queryData 根据数据来源 转换值 id -> DB -> R
* @param propertiesMap 字段映射(getter -> 值来源,setter -> 对象设值字段)
* @param <IN> 输入
* @param <R> 设置值的类型
*/
public static <IN, R, ID> void fill(IN data,
Function<Collection<ID>, Map<ID, R>> queryData,
Map<Function<IN, ID>, BiConsumer<IN, R>> propertiesMap) {
new FillerWorker<IN, R, ID>().fill(() -> Collections.<IN>singleton(data), propertiesMap, queryData);
}
/**
* 对象属性填充 IN { id, R(null) } -> IN { id, R(value) }
*
* @param data
* @param queryData 根据数据来源 转换值 id -> DB -> R
* @param propertiesMap 字段映射(getter -> 值来源,setter -> 对象设值字段)
* @param <IN> 输入
* @param <R> 设置值的类型
*/
public static <IN, R, ID> void fill(Supplier<Collection<IN>> data,
Function<Collection<ID>, Map<ID, R>> queryData,
Map<Function<IN, ID>, BiConsumer<IN, R>> propertiesMap) {
new FillerWorker<IN, R, ID>().fill(data, propertiesMap, queryData);
}
/**
* 对象属性填充 IN { id, R(null) } -> IN { id, R(value) }
*
* @param data
* @param queryData 根据数据来源 转换值 id -> R
* @param k1 getter1 -> 值来源
* @param v1 setter1 -> 对象设值字段
* @param k2 getter2 -> 值来源
* @param v2 setter2 -> 对象设值字段
* @param <IN> 输入
* @param <R> 设置值的类型
*/
public static <IN, R, ID> void fill(Supplier<Collection<IN>> data,
Function<IN, ID> k1, BiConsumer<IN, R> v1,
Function<IN, ID> k2, BiConsumer<IN, R> v2,
Function<Collection<ID>, Map<ID, R>> queryData) {
new FillerWorker<IN, R, ID>().fill(data, ImmutableMap.of(k1, v1, k2, v2), queryData);
}
/**
* 对象属性填充 IN { id, R(null) } -> IN { id, R(value) }
*
* @param data
* @param queryData 根据数据来源 转换值 id -> R
* @param k1 getter1 -> 值来源 1
* @param v1 setter1 -> 对象设值字段 1
* @param k2 getter2 -> 值来源 2
* @param v2 setter2 -> 对象设值字段 2
* @param k3 getter3 -> 值来源 3
* @param v3 setter3 -> 对象设值字段 3
* @param <IN> 输入
* @param <R> 设置值的类型
*/
public static <IN, R, ID> void fill(Supplier<Collection<IN>> data,
Function<IN, ID> k1, BiConsumer<IN, R> v1,
Function<IN, ID> k2, BiConsumer<IN, R> v2,
Function<IN, ID> k3, BiConsumer<IN, R> v3,
Function<Collection<ID>, Map<ID, R>> queryData) {
new FillerWorker<IN, R, ID>().fill(data, ImmutableMap.of(k1, v1, k2, v2, k3, v3), queryData);
}
/**
* List -> Map
*/
public static <K, V, T> Map<K, V> list2Map(List<T> list, Function<T, K> keyMapper, Function<T, V> valueMapper) {
return list.stream().collect(Collectors.toMap(keyMapper, valueMapper));
}
/**
* List -> Map
*/
public static <K, T> Map<K, T> list2Map(List<T> list, Function<T, K> keyMapper) {
return list2Map(list, keyMapper, Function.identity());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# kotlin 版本
/**
* 填充工具类
*
* @author pursue
*/
object FillerKt {
/**
* @param collection 源
* @param getter DATA_getter
* @param setter DATA_setter
* @param f DATA_provider
*/
fun <IN, R, ID> fill(
collection: Collection<IN>,
getter: (IN) -> ID,
setter: (IN, R) -> Unit,
f: (Collection<ID>) -> Map<ID, R>
) {
val ids = collection.map(getter).toSet()
val map = f.invoke(ids)
collection.forEach { map[getter.invoke(it)]?.let { r -> setter.invoke(it, r) } }
}
fun <IN, R, ID> fill(
collection: Collection<IN>,
p: Pair<(IN) -> ID, (IN, R) -> Unit>,
f: (Collection<ID>) -> Map<ID, R>
) {
val ids = collection.map(p.first).toSet()
val map = f.invoke(ids)
collection.forEach { map[p.first.invoke(it)]?.let { r -> p.second.invoke(it, r) } }
}
/**
* @param collection 源
* @param transformMap DATA_getter: DATA_setter
* @param dataProviderMap DATA_provider
*/
fun <IN, R, ID> fill(
collection: Collection<IN>,
transformMap: Map<(IN) -> ID, (IN, R) -> Unit>,
dataProviderMap: (Collection<ID>) -> Map<ID, R>
) {
val ids = transformMap.keys
.map { collection.map(it) }
.flatMap { it.distinct() }
val fMap = dataProviderMap.invoke(ids)
transformMap.forEach { (getter, setter) ->
collection.forEach { item ->
fMap[getter.invoke(item)]?.let { r -> setter.invoke(item, r) }
}
}
}
fun <IN, R, ID, R2> fill(
collection: Collection<IN>,
transformMap: Map<(IN) -> ID, (IN, R) -> Unit>,
dataProvider: (Collection<ID>) -> Collection<R2>,
dataProviderKeySelector: (R2) -> ID,
dataProviderValueTransform: (R2) -> R,
) {
val ids = transformMap.keys
.map { collection.map(it) }
.flatMap { it.distinct() }
val fMap = dataProvider.invoke(ids)
.associateBy(dataProviderKeySelector, dataProviderValueTransform)
transformMap.forEach { (getter, setter) ->
collection.forEach { item ->
fMap[getter.invoke(item)]?.let { r -> setter.invoke(item, r) }
}
}
}
fun <IN, R, ID, R2> fill(
collection: Collection<IN>,
pairTransform: Pair<(IN) -> ID, (IN, R) -> Unit>,
dataProvider: (Collection<ID>) -> Collection<R2>,
pair: Pair<(R2) -> ID, (R2) -> R>
) {
val ids = collection.map(pairTransform.first)
val fMap = dataProvider.invoke(ids)
.associateBy(pair.first, pair.second)
collection.forEach { item ->
fMap[pairTransform.first.invoke(item)]?.let { r -> pairTransform.second.invoke(item, r) }
}
}
fun <IN, R, ID, R2> fill(
collection: Collection<IN>,
pairTransforms: Collection<Pair<(IN) -> ID, (IN, R) -> Unit>>,
dataProvider: (Collection<ID>) -> Collection<R2>,
pair: Pair<(R2) -> ID, (R2) -> R>
) {
val ids = pairTransforms.map { it.first }
.map { collection.map(it) }
.flatMap { it.distinct() }
val fMap = dataProvider.invoke(ids)
.associateBy(pair.first, pair.second)
pairTransforms.forEach { (f, s) ->
collection.forEach { item ->
fMap[f.invoke(item)]?.let { r -> s.invoke(item, r) }
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
Last Updated: 2023/02/14, 18:02:00