Java8分区列表
是否可以将纯Jdk8中的列表划分为相等的块(子列表) 我知道使用Guava类是可能的,但是我们可以用纯Jdk吗?我不想为我的项目添加新的JAR,只是为了一个用例 溶液: 迄今为止最好的解决方案是: 我也发现了,但它们仅适用于少数情况: 1.Collectors.partitioningBy()将列表拆分为2个子列表–如下所示:Java8分区列表,java,java-8,partitioning,Java,Java 8,Partitioning,是否可以将纯Jdk8中的列表划分为相等的块(子列表) 我知道使用Guava类是可能的,但是我们可以用纯Jdk吗?我不想为我的项目添加新的JAR,只是为了一个用例 溶液: 迄今为止最好的解决方案是: 我也发现了,但它们仅适用于少数情况: 1.Collectors.partitioningBy()将列表拆分为2个子列表–如下所示: intList.stream().collect(Collectors.partitioningBy(s -> s > 6)); List<Li
intList.stream().collect(Collectors.partitioningBy(s -> s > 6));
List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());
intList.stream().collect(收集器.partitionby(s->s>6));
列表子集=新的ArrayList(groups.values());
2.Collectors.groupingBy()将列表拆分为多个分区:
Map<Integer, List<Integer>> groups =
intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3));
List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());
映射组=
intList.stream().collect(收集器.groupingBy(s->(s-1)/3));
列表子集=新的ArrayList(groups.values());
3.按分隔符拆分:
List<Integer> intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8);
int[] indexes =
Stream.of(IntStream.of(-1), IntStream.range(0, intList.size())
.filter(i -> intList.get(i) == 0), IntStream.of(intList.size()))
.flatMapToInt(s -> s).toArray();
List<List<Integer>> subSets =
IntStream.range(0, indexes.length - 1)
.mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1]))
.collect(Collectors.toList());
List intList=Lists.newArrayList(1,2,3,0,4,5,6,0,7,8);
int[]索引=
Stream.of(IntStream.of(-1),IntStream.range(0,intList.size())
.filter(i->intList.get(i)==0),IntStream.of(intList.size())
.flatMapToInt(s->s).toArray();
列表子集=
IntStream.range(0,index.length-1)
.mapToObj(i->intList.subList(索引[i]+1,索引[i+1]))
.collect(Collectors.toList());
4.使用流+计数器:
final List number=Arrays.asList(1,2,3,4,5,6,7);
最终int chunkSize=3;
最终AtomicInteger计数器=新的AtomicInteger();
最终收集结果=numbers.stream()
.collect(Collectors.groupingBy(it->counter.getAndIncrement()/chunkSize))
.values();
使用子列表()
方法可以轻松完成:
List<String> collection = new ArrayList<>(21);
// fill collection
int chunkSize = 10;
List<List<String>> lists = new ArrayList<>();
for (int i = 0; i < collection.size(); i += chunkSize) {
int end = Math.min(collection.size(), i + chunkSize);
lists.add(collection.subList(i, end));
}
列表集合=新的ArrayList(21);
//填充集合
int chunkSize=10;
List lists=新建ArrayList();
for(int i=0;i
尝试使用此代码,它使用Java 8:
public static Collection<List<Integer>> splitListBySize(List<Integer> intList, int size) {
if (!intList.isEmpty() && size > 0) {
final AtomicInteger counter = new AtomicInteger(0);
return intList.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size)).values();
}
return null;
}
publicstaticcollection splitListBySize(List intList,int size){
如果(!intList.isEmpty()&&size>0){
最终AtomicInteger计数器=新的AtomicInteger(0);
返回intList.stream().collect(Collectors.groupingBy(it->counter.getAndIncrement()/size)).values();
}
返回null;
}
我用一个定制的收集器尝试了自己的解决方案。我希望有人会觉得它有用,或者帮助我改进它
class PartitioningCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> {
private final int batchSize;
private final List<T> batch;
public PartitioningCollector(int batchSize) {
this.batchSize = batchSize;
this.batch = new ArrayList<>(batchSize);
}
@Override
public Supplier<List<List<T>>> supplier() {
return LinkedList::new;
}
@Override
public BiConsumer<List<List<T>>, T> accumulator() {
return (total, element) -> {
batch.add(element);
if (batch.size() >= batchSize) {
total.add(new ArrayList<>(batch));
batch.clear();
}
};
}
@Override
public BinaryOperator<List<List<T>>> combiner() {
return (left, right) -> {
List<List<T>> result = new ArrayList<>();
result.addAll(left);
result.addAll(left);
return result;
};
}
@Override
public Function<List<List<T>>, List<List<T>>> finisher() {
return result -> {
if (!batch.isEmpty()) {
result.add(new ArrayList<>(batch));
batch.clear();
}
return result;
};
}
@Override
public Set<Characteristics> characteristics() {
return emptySet();
}
}
类分区收集器实现收集器{
私有最终整数批量大小;
私人最终名单批次;
公共分区收集器(int batchSize){
this.batchSize=batchSize;
this.batch=新的ArrayList(batchSize);
}
@凌驾
公共供应商(){
返回LinkedList::新建;
}
@凌驾
公共双消费者累加器(){
返回值(总计,元素)->{
批量添加(元素);
if(batch.size()>=batchSize){
总计。添加(新阵列列表(批次));
batch.clear();
}
};
}
@凌驾
公共二进制运算符组合器(){
返回(左、右)->{
列表结果=新建ArrayList();
结果:addAll(左);
结果:addAll(左);
返回结果;
};
}
@凌驾
公共函数完成器(){
返回结果->{
如果(!batch.isEmpty()){
结果.添加(新ArrayList(批次));
batch.clear();
}
返回结果;
};
}
@凌驾
公共集特征(){
返回emptySet();
}
}
我们需要将每2个元素分组为键和值对,因此将列表分成2个块,(counter.getAndIncrement()/2)每2次点击的结果相同,例如:
您可以根据分区列表大小调整块大小
Guava Lists类有一个partition()方法,正好可以做到这一点。请参见您可以查看Guava源代码并相应地执行它…?用普通java编写函数不是问题,但JDK8在流式处理和集合操作方面有一些很棒的特性,我认为它比编写自己的代码要快。但这只是我的假设。我将其标记为可能重复,因为Java-8解决方案也在那里可用。是的,我看到了这个问题,但我错过了Jdk8解决方案,谢谢:)还讨论了这个问题的要点,即操作系统不使用任何外部LIB。您好,欢迎来到StackOverflow。请在回答之前先阅读问题。它说他想使用纯Jdk8。这就是,没有像番石榴这样的图书馆。
class PartitioningCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> {
private final int batchSize;
private final List<T> batch;
public PartitioningCollector(int batchSize) {
this.batchSize = batchSize;
this.batch = new ArrayList<>(batchSize);
}
@Override
public Supplier<List<List<T>>> supplier() {
return LinkedList::new;
}
@Override
public BiConsumer<List<List<T>>, T> accumulator() {
return (total, element) -> {
batch.add(element);
if (batch.size() >= batchSize) {
total.add(new ArrayList<>(batch));
batch.clear();
}
};
}
@Override
public BinaryOperator<List<List<T>>> combiner() {
return (left, right) -> {
List<List<T>> result = new ArrayList<>();
result.addAll(left);
result.addAll(left);
return result;
};
}
@Override
public Function<List<List<T>>, List<List<T>>> finisher() {
return result -> {
if (!batch.isEmpty()) {
result.add(new ArrayList<>(batch));
batch.clear();
}
return result;
};
}
@Override
public Set<Characteristics> characteristics() {
return emptySet();
}
}
private final String dataSheet = "103343262,6478342944, 103426540,84528784843, 103278808,263716791426, 103426733,27736529279,
103426000,27718159078, 103218982,19855201547, 103427376,27717278645,
103243034,81667273413";
final int chunk = 2;
AtomicInteger counter = new AtomicInteger();
Collection<List<String>> chuncks= Arrays.stream(dataSheet.split(","))
.map(String::trim)
.collect(Collectors.groupingBy(i->counter.getAndIncrement()/chunk))
.values();
pairs =
"103218982" -> "19855201547"
"103278808" -> "263716791426"
"103243034" -> "81667273413"
"103426733" -> "27736529279"
"103426540" -> "84528784843"
"103427376" -> "27717278645"
"103426000" -> "27718159078"
"103343262" -> "6478342944"
IntStream.range(0,6).forEach((i)->System.out.println(counter.getAndIncrement()/2));
prints:
0
0
1
1
2
2