pursue wind pursue wind
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
  • 工具类

    • 字段填充工具
      • 使用方法
      • util
      • kotlin 版本
    • Excel
  • Java-集合框架

  • Java8

  • Java-多线程

  • Java计时新姿势√
  • Java中的BlockingQueue
  • Lambda表达式被首次调用时很慢?从JIT到类加载再到实现原理
  • 正则表达式
  • Java定时任务
  • JavaWeb

  • Java
  • 工具类
pursuewind
2023-02-13
目录

字段填充工具

# 使用方法

@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

# 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

# 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
Last Updated: 2023/02/14, 18:02:00
Excel

Excel→

Theme by Vdoing | Copyright © 2019-2023 pursue-wind | 粤ICP备2022093130号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜
  • 网络DJ