在Java8流foreach中查找元素的索引

在Java8流foreach中查找元素的索引,java,collections,java-stream,Java,Collections,Java Stream,已经有一些帖子看起来与此相关,我浏览了它们,但它们并没有解决我的问题: 我有一个方法和一些逻辑,我必须使用streams进行代码优化 我的方法是:(这里我试图以格式化的方式打印电子邮件) 公共静态StringBuilder printEmailsListFormat(ArrayList a){ StringBuilder sb=新的StringBuilder(); 对于(int i=0;i{ 字符串格式=“%-45s”; 如果(i%3==0)格式+=“\n”; 返回String.format(f

已经有一些帖子看起来与此相关,我浏览了它们,但它们并没有解决我的问题:

我有一个方法和一些逻辑,我必须使用streams进行代码优化

我的方法是:(这里我试图以格式化的方式打印电子邮件)

公共静态StringBuilder printEmailsListFormat(ArrayList a){
StringBuilder sb=新的StringBuilder();
对于(int i=0;i

我必须优化此代码。

这是您所能做的最好的了。这很难看,因为流不知道列表索引。对于转换为使用流来说,它不是一个很好的候选者

public static StringBuilder printEmailsListFormat(ArrayList<String> a) {
    return IntStream.range(0, a.size())
        .mapToObj(i -> {
            String format = "%-45s";
            if (i % 3 == 0) format += "\n";
            return String.format(format, a.get(i));
        })
        .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);
}
公共静态StringBuilder printEmailsListFormat(ArrayList a){
返回IntStream.range(0,a.size())
.mapToObj(i->{
字符串格式=“%-45s”;
如果(i%3==0)格式+=“\n”;
返回String.format(format,a.get(i));
})
.collect(StringBuilder::new、StringBuilder::append、StringBuilder::append);
}

您只能并行化并因此加快字符串的格式化,但不能将格式化部分串联起来,因为它们必须按顺序排列

您也可以通过流连接格式化的部分,但是for循环更快。 所以你会得到:

// just some example values
ArrayList<String> a = new ArrayList(Arrays.asList("string1", "string2", "string3", "string4", "string5"));
// formatting them in parallel
List<String> formatted = a.parallelStream().map(s -> String.format("%-45s", s)).collect(Collectors.toList());
// concatenating them in order
StringBuilder sb = new StringBuilder();
for (ListIterator<String> i = formatted.listIterator(); i.hasNext();) {
    sb.append(i.next());
    if (i.previousIndex() % 3 == 0) {
        sb.append("\n");
    }
}
System.out.println("output: " + sb);
请考虑使用Stase.GETFACTS(“Leal.S隔除器”)代替“\n”。

< P>如果您想优化代码,就不应该切换到流API。相反,将其更改为使用单个
格式化程序,而不是每个元素使用一个格式化程序(隐藏在
String.format
)并避免使用
String.format
创建的临时字符串:

public static StringBuilder printEmailsListFormat(List<String> a) {
    StringBuilder sb = new StringBuilder();
    Formatter formatter = new Formatter(sb);
    for(int i = 0; i < a.size(); i++) {
        formatter.format("%-45s", a.get(i));
        if(i % 3 ==0) sb.append("\n");
    }
    return sb;
}

优化到底是什么?这是目前可用的最快的方法。您到底需要优化什么?演出可读性?我有一个第一个建议:不要指定一个不打印任何内容的方法
printmailslistformat
“我必须使用流进行优化”。但是为什么呢?当使用分支条件时,流不是很合适。他们也不知道列表索引。虽然这是可能的,但对于转换为使用流来说,这不是一个很好的候选者。如果您想优化任何内容,请将第一个
sb.append
移动到
If/else
之前。您不能使用
收集器。改为加入
?还有,三元
格式=(i%3==0)?“…”:“…\n”可能更快。@tobias_k他的原始方法返回了字符串生成器。我想他以后可能会添加更多信息,所以我保持不变。我不认为在格式中添加
“\n”
而不是结果字符串有什么意义。如果您使用
.mapToObj(i->{String s=String.format(“%-45s”,a.get(i));如果(i%3==0)s+=“\n”;return s;})
,该怎么办?除此之外,您可以在此处省略
收集器,即只使用
.collect(StringBuilder::new,StringBuilder::append,StringBuilder::append)
output: string1                                      
string2                                      string3                                      string4                                      
string5        
public static StringBuilder printEmailsListFormat(List<String> a) {
    StringBuilder sb = new StringBuilder();
    Formatter formatter = new Formatter(sb);
    for(int i = 0; i < a.size(); i++) {
        formatter.format("%-45s", a.get(i));
        if(i % 3 ==0) sb.append("\n");
    }
    return sb;
}
static final String EMPTY_CELL = String.format("%45s", ""); //JDK11: " ".repeat(45);

public static StringBuilder printEmailsListFormat(List<String> a) {
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < a.size(); i++) {
        String s = a.get(i);
        sb.append(s);
        if(s.length() < EMPTY_CELL.length())
            sb.append(EMPTY_CELL, s.length(), EMPTY_CELL.length());
        if(i % 3 ==0) sb.append("\n");
    }
    return sb;
}