代码语言:scss复制作用:将一个集合的数据分成多个集合,指定不重复字段后数据将会被分成多个集合,每个集合中指定的唯一标识唯一存在。其中 segment 指定每个集合中元素的数量,不一定满足每个集合的元素达到 segment 的数量,但是每个集合都是不重复的数据。
@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腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!