Java – Stream – 收集每N个元素

我正在努力学习java – stream。 我能够做简单的迭代/过滤/地图/收集等。

当我试图收集每个3个元素并按照此示例中所示进行打印时,[收集每3个元素并打印等等…]

List list = Arrays.asList("a","b","c","d","e","f","g","h","i","j"); int count=0; String append=""; for(String l: list){ if(count>2){ System.out.println(append); System.out.println("-------------------"); append=""; count=0; } append = append + l; count++; } System.out.println(append); 

输出:

 abc ------------------- def ------------------- ghi ------------------- j 

我没有得到任何线索如何使用流这样做。 我应该实现自己的collections家来实现这一目标吗?

您实际上可以使用IntStream来模拟列表的分页。

 List list = Arrays.asList("a","b","c","d","e","f","g","h","i","j"); int pageSize = 3; IntStream.range(0, (list.size() + pageSize - 1) / pageSize) .mapToObj(i -> list.subList(i * pageSize, Math.min(pageSize * (i + 1), list.size()))) .forEach(System.out::println); 

哪个输出:

 [a, b, c] [d, e, f] [g, h, i] [j] 

如果要生成字符串,可以使用String.join因为您直接处理List

 .mapToObj(i -> String.join("", list.subList(i * pageSize, Math.min(pageSize * (i + 1), list.size())))) 

您可以创建自己的Collector 。 最简单的方法是调用Collector.of()

由于您的用例需要按顺序处理值,因此这是一种不支持并行处理的实现。

 public static Collector>, List>> blockCollector(int blockSize) { return Collector.of( ArrayList>::new, (list, value) -> { List block = (list.isEmpty() ? null : list.get(list.size() - 1)); if (block == null || block.size() == blockSize) list.add(block = new ArrayList<>(blockSize)); block.add(value); }, (r1, r2) -> { throw new UnsupportedOperationException("Parallel processing not supported"); } ); } 

测试

 List input = Arrays.asList("a","b","c","d","e","f","g","h","i","j"); List> output = input.stream().collect(blockCollector(3)); output.forEach(System.out::println); 

产量

 [a, b, c] [d, e, f] [g, h, i] [j] 

如果您的项目中有Guava,则可以使用Iterables.partition方法:

 import com.google.common.collect.Iterables; import com.google.common.collect.Streams; ... Stream> stream = Streams.stream(Iterables.partition(list, 3)); 

我这样解决了:

  List list = Arrays.asList("a","b","c","d","e","f","g","h","i","j"); int groupBy = 3; AtomicInteger index = new AtomicInteger(0); Map> groups = list.stream() .collect(Collectors.groupingBy(cdm -> index.getAndIncrement()/groupBy)); System.out.println(groups); 

它准备一个地图,其中行号是键,行上的字符串在键中。

我认为赌注的方法是使用奇妙的TagEx Valeev图书馆StreamEx 。 解决方案适合一行))

 StreamEx.ofSubLists(list, 3).toList();