我想要一个类似于scala分组函数的东西。基本上,一次选择两个元素并处理它们。以下是相同的参考:
将列表拆分为具有固定元素数量的多个列表
Lambda确实提供了诸如groupingBy和partitioningBy之类的东西,但它们似乎都没有与Scala中的分组函数相同。任何指示将不胜感激。
您可以创建自己的收集器。如下所示:
class GroupingCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> {
private final int elementCountInGroup;
public GroupingCollector(int elementCountInGroup) {
this.elementCountInGroup = elementCountInGroup;
}
@Override
public Supplier<List<List<T>>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<List<T>>, T> accumulator() {
return (lists, integer) -> {
if (!lists.isEmpty()) {
List<T> integers = lists.get(lists.size() - 1);
if (integers.size() < elementCountInGroup) {
integers.add(integer);
return;
}
}
List<T> list = new ArrayList<>();
list.add(integer);
lists.add(list);
};
}
@Override
public BinaryOperator<List<List<T>>> combiner() {
return (lists, lists2) -> {
List<List<T>> r = new ArrayList<>();
r.addAll(lists);
r.addAll(lists2);
return r;
};
}
@Override
public Function<List<List<T>>, List<List<T>>> finisher() {
return lists -> lists;
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
}
然后你可以这样使用它:
List<List<Integer>> collect = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).collect(new GroupingCollector<>(3));
System.out.println(collect);
将打印:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
这听起来像是一个更好地处理的问题,就像低
级流操作一样,就像流
API 本身提供的操作一样。(相对)简单的解决方案可能如下所示:
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
而不是处理< code>IntStream.range(0,1000)的一千个项目。这也使得能够使用无限的源代码流:
chunked(Stream.iterate(0, i->i+1), 2).anyMatch(list->list.toString().equals("[6, 7]")));
如果您对完全物化的集合感兴趣,而不是应用后续的< code>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());
您可以使用番石榴库。
<code>列表
问题内容: 我有这个清单(): 我想要这样的东西: 换句话说,我想使用值作为分隔符将列表拆分为子列表,以获得列表列表()。我正在寻找Java 8解决方案。我已经尝试过,但是我不确定这是我要找的东西。谢谢! 问题答案: 我目前想出的唯一解决方案是实现自己的自定义收集器。 在阅读解决方案之前,我想添加一些有关此的注释。我将这个问题更多地当作编程练习,我不确定是否可以使用并行流来完成。 因此,您必须意识
我有一个对象(Pos)与此模型的集合: 对象列表如下所示: 我想按beforeChangement或afterChangement==”字段拆分此对象列表要使用此格式(列表列表)
我有一个列表(原始列表)类型MyType的元素。我的类型是: 因此,我想在列表中单独列出每组元素,其中每组元素都具有相同的IDRISULECEElement。 例如,一个列表列表,主列表的每个列表只包含同一组的元素。 例如,我有一个包含以下元素的原始列表: 项目1(1,1,1); 项目2(1,2,2); 项目3(1,3,3); 项目4(2,4,4); 项目5(2,5,5); 项目6(2,6,6);
我有一个包含字典作为元素的单列的。这是以下代码的结果: 我需要将此列拆分为尽可能多的列(我有太多的行和列,并且我无法更改函数),因此输出将是一个包含列,,的数据帧,<代码>功能50。这样做的最佳方式是什么? 一个具体而简单的例子: 但当我尝试用pd.Series或pd.DataFrame包装它时,它说如果数据是标量值,则必须提供索引。提供索引=['feature1','feature2'],我会得
问题:如何将列表拆分为两个子列表,其中元素由元素中的选项卡分隔? 上下文:我想读取一个由制表符分隔的文件到Pandas DataFrame中。这些文件看起来像: 列1\t 123 列2\t 列3\t文本 这意味着每行有一列,后面跟着一个选项卡,然后是该列的一个值(有时没有值)。 我的想法是读取文件并将每行保存为列表的元素,然后将列表分成两个,将选项卡前的第一部分作为一个列表,选项卡后的第二部分作为
如何将这列列表拆分为两列? 期望的结果: