在java lambda表达式中,如何通过在列表的每三个元素后添加新行来打印列表?

在java lambda表达式中,如何通过在列表的每三个元素后添加新行来打印列表?,java,arraylist,lambda,java-8,Java,Arraylist,Lambda,Java 8,假设我有一个如下的列表 Collection<?> mainList = new ArrayList<String>(); mainList=//some method call// a,b,c d,e,f g,h,i 我得到的结果是 a,b,c,d,e,f,g,h,i 在java中,如何通过在列表中的每三个元素后添加新行来打印此列表,以便打印结果如下 Collection<?> mainList = new ArrayList<String>

假设我有一个如下的列表

Collection<?> mainList = new ArrayList<String>();
mainList=//some method call//
a,b,c
d,e,f
g,h,i
我得到的结果是

a,b,c,d,e,f,g,h,i
在java中,如何通过在列表中的每三个元素后添加新行来打印此列表,以便打印结果如下

Collection<?> mainList = new ArrayList<String>();
mainList=//some method call//
a,b,c
d,e,f
g,h,i
注意:这类似于。但是,在读取文件本身时会对文件进行格式化。
我想在打印输出时执行此操作。

旁注:在实际代码中,如果替换

Collection mainList=new ArrayList()

Collection mainList=new ArrayList()

如果操纵
字符串
s,则创建
字符串
集合
,而不是
集合


但是文件的格式化是在读取自身时完成的。我想 在打印输出时执行此操作

获取连接的字符串后,应使用
replaceAll(“(\\w*,\\w*,\\w*,)”,“$1”+System.lineSeparator())
执行此操作。
Iit将搜索并替换所有由
分隔的3个或更多字符组成的序列,
字符由相同的内容($1->组捕获)替换,但将其与行分隔符连接。

除此之外:

String collect = mainList.stream().collect(Collectors.joining(","));    
可通过以下方式简化:

String collect = String.join(",", mainList);    
示例代码:

public static void main(String[] args) {
  Collection<String> mainList = Arrays.asList("a","b","c","d","e","f","g","h","i", "j");
  String formattedValues = String.join(",", mainList).replaceAll("(\\w*,\\w*,\\w*,)", "$1" + System.lineSeparator());
  System.out.println(formattedValues);
}
publicstaticvoidmain(字符串[]args){
集合mainList=Arrays.asList(“a”、“b”、“c”、“d”、“e”、“f”、“g”、“h”、“i”、“j”);
String formattedValues=String.join(“,”,mainList).replaceAll(“\\w*,\\w*,\\w*,)”,“$1”+System.lineSeparator());
System.out.println(格式化值);
}
输出:

a、 b,c,

d、 e,f

g、 h,我,

j


如果您想坚持使用Java Stream API,那么您的问题可以通过将初始列表划分为大小为3的子列表,然后将每个子列表表示为字符串并将结果与
\n
连接来解决

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

final class PartitionListExample {

    public static void main(String[] args) {

        final Collection<String> mainList = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i");
        final AtomicInteger idx = new AtomicInteger(0);
        final int size = 3;

        // Partition a list into list of lists size 3
        final Collection<List<String>> rows = mainList.stream()
                .collect(Collectors.groupingBy(
                        it -> idx.getAndIncrement() / size
                ))
                .values();

        // Write each row in the new line as a string
        final String result = rows.stream()
                .map(row -> String.join(",", row))
                .collect(Collectors.joining("\n"));

        System.out.println(result);
    }
}
从下面的示例中获得更多信息 通过使用
收集器,在
中加入(“,”
)。groupingBy
收集器,并在最后使用
字符串。加入(“\n”,行)
,而不是触发另一个流缩减,从而得出了一个更短的解决方案

        final Collection<String> rows = mainList.stream()
                .collect(Collectors.groupingBy(
                        it -> idx.getAndIncrement() / size,
                        Collectors.joining(",")
                ))
                .values();

        // Write each row in the new line as a string
        final String result = String.join("\n", rows);

        System.out.println(result);
    }
final Collection rows=mainList.stream()
.collect(收集器.groupingBy(
它->idx.getAndIncrement()/size,
收集者。加入(“,”)
))
.values();
//将新行中的每一行作为字符串写入
最终字符串结果=String.join(“\n”,行);
系统输出打印项次(结果);
}
最后说明
请记住,这不是以所需格式打印元素列表的最有效方法。但是,如果要创建最终结果,任何元素的分区列表都为您提供了灵活性,并且非常容易阅读和理解。

另一种方法是创建自定义的
收集器

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class PartitionListInPlace {

    static class MyCollector implements Collector<String, List<List<String>>, String> {

        private final List<List<String>> buckets;
        private final int bucketSize;

        public MyCollector(int numberOfBuckets, int bucketSize) {
            this.bucketSize = bucketSize;
            this.buckets = new ArrayList<>(numberOfBuckets);
            for (int i = 0; i < numberOfBuckets; i++) {
                buckets.add(new ArrayList<>(bucketSize));
            }
        }

        @Override
        public Supplier<List<List<String>>> supplier() {
            return () -> this.buckets;
        }

        @Override
        public BiConsumer<List<List<String>>, String> accumulator() {
            return (buckets, element) -> buckets
              .stream()
              .filter(x -> x.size() < bucketSize)
              .findFirst()
              .orElseGet(() -> {
                  ArrayList<String> nextBucket = new ArrayList<>(bucketSize);
                  buckets.add(nextBucket);
                  return nextBucket;
              })
              .add(element);
        }

        @Override
        public BinaryOperator<List<List<String>>> combiner() {
            return (b1, b2) -> {
                throw new UnsupportedOperationException();
            };
        }

        @Override
        public Function<List<List<String>>, String> finisher() {
            return buckets -> buckets.stream()
              .map(x -> x.stream()
                .collect(Collectors.joining(", ")))
              .collect(Collectors.joining(System.lineSeparator()));
        }

        @Override
        public Set<Characteristics> characteristics() {
            return new HashSet<>();
        }
    }


    public static void main(String[] args) {
        Collection<String> mainList = Arrays.asList("a","b","c","d","e","f","g","h","i", "j");

        String formattedValues = mainList
          .stream()
          .collect(new MyCollector(mainList.size() / 3, 3));
        System.out.println(formattedValues);
    }
}

在我看来,你的问题比结果更重要。这里真正的问题是:如何以X为单位获取流中的元素?在
收集器
中没有找到这样的东西,这让我非常惊讶。您可能可以创建自己的
收集器
,生成
列表作为输出。@T.J.Crowder显然Guava和Apache Commons中有一些类可以这样做-@T.J.Crowder
收集器。groupingBy(谓词)。values()
可以将列表划分为子列表。我已经建立了我的答案。@SzymonStepniak:啊,我应该想到把计数器放在一个这样的容器里。我不得不怀疑,
.collect
是一个终端操作,而你显然只在这个专栏创建任务中使用它们,为什么还要为使用流的开销而烦恼呢?在输出上使用字符串处理看起来像是对meThe
replaceAll
的恶意攻击。如果您至少能详细说明用法,那就太好了。详细说明我的评论-正则表达式是内容敏感的,如果单个元素不再匹配,则需要修改,从而使此代码变得脆弱。虽然可能需要更多的代码,但应首先使用结构化数据将元素分组为三组,而不是作为后处理步骤。@Alnitak,我的答案基于op要求。我们还可以用
\w*
替换
\w
。根据设计原因,代码是脆弱的。如果不需要,为什么还要增加复杂性呢?@Downvoter我可以理解,这种解决问题的方法可能不是每个人都选择的,但它是正确的,而且是有效的。请阅读它:“每当你遇到一篇非常草率、不费力气的帖子,或者一个明显而且可能是危险的错误答案时,请使用你的反对票。”JOOI(我不是流方面的专家)为什么不使用
rows=list.stream().collect(Collectors.groupingBy(s->idx.getAndIncrement()/3))
-我看不到
AbstractMap
SimpleEntry
操作添加了什么。我已经试过了,它显然对我有效,但可能有副作用或我不知道的问题。@Alnitak很好,谢谢!它没有任何副作用,但由于创建了中间的不可变项,所以更加冗长。正如您所观察到的,可以通过直接调用
.groupingBy(s->idx.getAndIncrement()/size)
来简化它。谢谢你的意见!不客气-还有对
Collectors.toList()
的新调用是什么?我觉得在我的实验中没有必要-
。groupingBy
已经返回了一个`Map@Alnitak它也可以避免,因为
。groupingBy()
在未指定
下游时使用它。再次感谢!:)为了获得更多乐趣,请使用
收集器。加入(“,”
作为
中的
下游功能
a, b, c
d, e, f
g, h, i
j