在java 8中将列表拆分为具有固定数量元素的多个列表
我想要一些类似于 scala 分组函数的东西。基本上,一次选择2个元素并处理它们。以下是相同的参考:
Lambdas确实提供了分组By和分区By之类的东西,但它们似乎都不像Scala中的分组函数那样。任何指示将不胜感激。
我想要一些类似于 scala 分组函数的东西。基本上,一次选择2个元素并处理它们。以下是相同的参考:
Lambdas确实提供了分组By和分区By之类的东西,但它们似乎都不像Scala中的分组函数那样。任何指示将不胜感激。
您可以使用番石榴库。
List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);
这听起来像是一个像低级操作一样更好地处理的问题,就像API本身提供的操作一样。(相对)简单的解决方案可能如下所示:Stream
Stream
public static <T> Stream<List<T>> chunked(Stream<T> s, int chunkSize) {
if(chunkSize<1) throw new IllegalArgumentException("chunkSize=="+chunkSize);
if(chunkSize==1) return s.map(Collections::singletonList);
Spliterator<T> src=s.spliterator();
long size=src.estimateSize();
if(size!=Long.MAX_VALUE) size=(size+chunkSize-1)/chunkSize;
int ch=src.characteristics();
ch&=Spliterator.SIZED|Spliterator.ORDERED|Spliterator.DISTINCT|Spliterator.IMMUTABLE;
ch|=Spliterator.NONNULL;
return StreamSupport.stream(new Spliterators.AbstractSpliterator<List<T>>(size, ch)
{
private List<T> current;
@Override
public boolean tryAdvance(Consumer<? super List<T>> action) {
if(current==null) current=new ArrayList<>(chunkSize);
while(current.size()<chunkSize && src.tryAdvance(current::add));
if(!current.isEmpty()) {
action.accept(current);
current=null;
return true;
}
return false;
}
}, s.isParallel());
}
简单测试:
chunked(Stream.of(1, 2, 3, 4, 5, 6, 7), 3)
.parallel().forEachOrdered(System.out::println);
优点是您不需要所有项目的完整集合即可进行后续流处理,例如
chunked(
IntStream.range(0, 1000).mapToObj(i -> {
System.out.println("processing item "+i);
return i;
}), 2).anyMatch(list->list.toString().equals("[6, 7]")));
将打印:
processing item 0
processing item 1
processing item 2
processing item 3
processing item 4
processing item 5
processing item 6
processing item 7
true
而不是处理一千个项目。这也允许使用无限源 s:IntStream.range(0, 1000)
Stream
chunked(Stream.iterate(0, i->i+1), 2).anyMatch(list->list.toString().equals("[6, 7]")));
如果您对完全具体化的集合感兴趣,而不是应用后续操作,则只需使用以下操作:Stream
List<Integer> list=Arrays.asList(1, 2, 3, 4, 5, 6, 7);
int listSize=list.size(), chunkSize=2;
List<List<Integer>> list2=
IntStream.range(0, (listSize-1)/chunkSize+1)
.mapToObj(i->list.subList(i*=chunkSize,
listSize-chunkSize>=i? i+chunkSize: listSize))
.collect(Collectors.toList());