skyouc
3 天以前 27f59f44345d044967e2048f09dbd704f90ce3db
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
package com.vincent.rsf.server.manager.utils;
 
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import lombok.Data;
 
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
 
/**
 * @author Ryan
 * @description 根据对象多个属性合并处理
 * @param
 * @return
 * @time 2025/4/25 10:55
 */
public class GroupMergeUtil {
    /**
     * 根据多个属性分组合并对象列表
     *
     * @param list       待分组的对象列表
     * @param mergers    合并函数,定义如何合并同一组中的对象
     * @param keyGetters 分组属性的getter方法数组
     * @param <T>        对象类型
     * @param <K>        分组键类型
     * @return 分组合并后的对象列表
     */
    @SafeVarargs
    public static <T, K> List<T> groupAndMerge(
            List<T> list,
            BinaryOperator<T> mergers,
            Function<T, K>... keyGetters) {
 
        return new ArrayList<>(list.stream()
                .collect(Collectors.toMap(
                        item -> new GroupingKeys<>(Arrays.stream(keyGetters)
                                .map(getter -> getter.apply(item))
                                .toArray()),
                        Function.identity(),
                        mergers))
                .values());
    }
 
    /**
     * @author Ryan
     * @description 用于存储多个分组键的内部类
     * @param
     * @return
     * @time 2025/4/25 10:56
     */
    private static class GroupingKeys<K> {
        private final Object[] keys;
        private final int hashCode;
 
        public GroupingKeys(Object[] keys) {
            this.keys = keys;
            this.hashCode = Arrays.deepHashCode(keys);
        }
 
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            GroupingKeys<?> that = (GroupingKeys<?>) o;
            return Arrays.deepEquals(keys, that.keys);
        }
 
        @Override
        public int hashCode() {
            return hashCode;
        }
    }
 
    // 示例使用
//    public static void main(String[] args) {
//        // 示例数据类
//        @Data
//        class Product {
//         private String category;
//            private String subCategory;
//            private String abc;
//
//            private String dbc;
//
//            private String brand;
//            private int quantity;
//            private double price;
//
//            public Product(String category, String abc, String dbc, String subCategory, String brand, int quantity, double price) {
//                this.category = category;
//                this.subCategory = subCategory;
//                this.abc = abc;
//                this.dbc = dbc;
//                this.brand = brand;
//                this.quantity = quantity;
//                this.price = price;
//            }
//
//            // getters...
////            public String getCategory() { return category; }
////            public String getSubCategory() { return subCategory; }
////            public String getBrand() { return brand; }
////            public int getQuantity() { return quantity; }
////            public double getPrice() { return price; }
//
//            @Override
//            public String toString() {
//                return String.format("[%s, %s, %s] - Qty: %d, Price: %.2f",
//                        category, subCategory, brand, quantity, price);
//            }
//        }
//
//        // 创建测试数据
//        List<Product> products = Arrays.asList(
//                new Product("Electronics", "Phone", "Apple", 10, 999.99),
//                new Product("Electronics", "Phone", "Samsung", 15, 899.99),
//                new Product("Electronics", "Phone", "Apple", 5, 999.99),
//                new Product("Electronics", "Tablet", "Apple", 8, 799.99),
//                new Product("Clothing", "Shirt", "Nike", 20, 29.99),
//                new Product("Clothing", "Shirt", "Nike", 10, 29.99),
//                new Product("Clothing", "Pants", "Adidas", 12, 49.99)
//        );
//
//        // 按 category, subCategory, brand 分组,合并 quantity 相加,price 取平均值
//        List<Product> mergedProducts = groupAndMerge(
//                products,
//                (p1, p2) -> new Product(
//                        p1.category,
//                        p1.subCategory,
//                        p1.brand,
//                        p1.quantity + p2.quantity,
//                        (p1.price + p2.price) / 2  // 这里简单平均,实际业务可能不同
//                ),
//                Product::getCategory,
//                Product::getSubCategory,
//                Product::getBrand
//        );
//
////        // 打印结果
////        System.out.println("合并后的产品列表:");
////        System.out.println(JSONArray.toJSONString(mergedProducts));
////        mergedProducts.forEach(item -> {
////            System.out.println(JSONObject.toJSONString(item));
////        });
////        mergedProducts.forEach(System.out::println);
//    }
}