多维度进行分组

1,524 阅读1分钟

背景

在技术群里有人抛出这么一个问题:

请教一个问题。如何优雅地对一个List进行多维度分组? 比如有一个List orders,然后需要按照订单的字段1,字段2, 字段3,......,字段N进行分组,最终分组结果希望是List<List>这种形式。也就是说最终的这个list会被划分成字段1的取值种类数 乘以 字段2的取值种类数 乘以 ...... 乘以字段N的取值种类数,这么多部分。

如果大家碰到这样的需求, 要如何写代码?

我的实现

// 把具体分组维度放到list中
List<Function<Order, String>> list = new ArrayList<>();
list.add(Order::getCompany);
list.add(Order::getId);

final List<List<Order>> results = new ArrayList<>();

for (Function<Order, String> function : list) {
    Map<String, List<Order>> map = original.stream().collect(Collectors.groupingBy(function));
    List<Order> temp = new ArrayList<>();
    for (Map.Entry<String, List<Order>> entry : map.entrySet()) {
        List<Order> value = entry.getValue();
        temp.add(value.get(0));
    }
    results.add(temp);
}

大家是否还有更优雅的实现方式?

最后

附完整Demo

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        new Main().group();
    }

    public void group() {
        List<Order> original = new ArrayList<>();
        Order order = new Order();
        order.setId("1");
        order.setCompany("111");
        original.add(order);
        order = new Order();
        order.setId("2");
        order.setCompany("222");
        original.add(order);

        order = new Order();
        order.setId("1");
        order.setCompany("333");
        original.add(order);

        order = new Order();
        order.setId("3");
        order.setCompany("222");
        original.add(order);

        List<Function<Order, String>> list = new ArrayList<>();
        list.add(Order::getCompany);
        list.add(Order::getId);

        final List<List<Order>> results = new ArrayList<>();
        for (Function<Order, String> function : list) {
            Map<String, List<Order>> map = original.stream().collect(Collectors.groupingBy(function));
            List<Order> temp = new ArrayList<>();
            for (Map.Entry<String, List<Order>> entry : map.entrySet()) {
                List<Order> value = entry.getValue();
                temp.add(value.get(0));
            }
            results.add(temp);
        }

        results.forEach(System.out::println);
    }

    static class Order {
        private String id;
        private String company;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getCompany() {
            return company;
        }

        public void setCompany(String conpany) {
            this.company = conpany;
        }

        @Override
        public String toString() {
            return "Order{" +
                    "id='" + id + '\'' +
                    ", company='" + company + '\'' +
                    '}';
        }
    }
}