Java 数据分桶

2023-11-20 14:45:15 浏览数 (1)

作用:将一个集合的数据分成多个集合,指定不重复字段后数据将会被分成多个集合,每个集合中指定的唯一标识唯一存在。其中 segment 指定每个集合中元素的数量,不一定满足每个集合的元素达到 segment 的数量,但是每个集合都是不重复的数据。

代码语言:scss复制
@Data
public class GroupNode<T> {

    private List<T> data;

    private Integer point;

    private Integer size;
}

 public static <T, R> List<List<T>> uniqueGroup(List<T> source, int segment, Function<T, R> function) {
//        根据条件分组
        Map<R, List<T>> mapGroup = source.stream().collect(Collectors.groupingBy(function));
        List<GroupNode<T>> groupNodeList = new ArrayList<>();
//        计算每个分组的size
        for (R v1 : mapGroup.keySet()) {
            GroupNode<T> groupNode = new GroupNode<>();
            groupNode.setData(mapGroup.get(v1));
            groupNode.setPoint(0);
            groupNode.setSize(mapGroup.get(v1).size());
            groupNodeList.add(groupNode);
        }
        List<GroupNode<T>> singleList = groupNodeList.stream().filter(p -> p.getSize().equals(1)).collect(Collectors.toList());
        List<GroupNode<T>> multiplyList = groupNodeList.stream().filter(p -> !p.getSize().equals(1)).collect(Collectors.toList());
        List<List<T>> result = new ArrayList<>();

        int size = 0;

        do {
            size = 0;
            List<T> tmp = new ArrayList<>();
//            先填充有重复数据的
            for (GroupNode<T> node : multiplyList) {
                if (node.getPoint() >= node.getSize()) {
                    continue;
                }
                if (tmp.size() >= segment) {
                    continue;
                }
                size  ;
                tmp.add(node.getData().get(node.getPoint()));
                node.setPoint(node.getPoint()   1);
            }
            if (size < 1) {
                break;
            }
//            补充数据达到 segment
            if (tmp.size() < segment && singleList.size() > 0) {
//                    [m,n)
                int index = segment - tmp.size();
                if (index > singleList.size()) {
                    index = singleList.size();
                }
                tmp.addAll(singleList.subList(0, index).stream().map(p -> p.getData().get(0)).collect(Collectors.toList()));
                if (index < singleList.size()) {
                    singleList = singleList.subList(index, singleList.size());
                } else {
                    singleList = Collections.emptyList();
                }
            }
            if (tmp.size() > 0) {
                result.add(tmp);
            }
        } while (size > 0);

//        多数据的填充完后如果唯一的数据还有就直接分组了
        while (singleList.size() > 0) {
            List<T> tmp = new ArrayList<>();
            if (singleList.size() > segment) {
                tmp.addAll(singleList.subList(0, segment).stream().map(p -> p.getData().get(0)).collect(Collectors.toList()));
                singleList = singleList.subList(segment, singleList.size());
            } else {
                tmp.addAll(singleList.subList(0, singleList.size()).stream().map(p -> p.getData().get(0)).collect(Collectors.toList()));
                singleList = Collections.emptyList();
            }
            result.add(tmp);
        }

        return result;
    }

如果是基本数据类型的集合,使用该方法进行分组。

代码语言:c#复制
public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("1");
        list.add("1");
        list.add("1");
        list.add("1");
        list.add("1");
        list.add("5");
        list.add("6");
        list.add("7");
        System.out.println(uniqueGroup(list, 2, Function.identity()));
    }

如果是对象类型,直接指定相应的 key 就行。

代码语言:typescript复制
 public static void main(String[] args) {
        List<GroupNode<String>> list = new ArrayList<>();
        System.out.println(uniqueGroup(list, 2, GroupNode::getPoint));
    }

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞