在Java 8 Steam foreach中找到元素的索引

时间:2019-05-13 12:19:28

标签: java collections java-stream

已经有一些与此相关的帖子了,我仔细阅读了这些帖子,但是这些帖子并没有解决我的问题:

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

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

public static StringBuilder printEmailsListFormat(ArrayList<String> a) {

    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < a.size(); i++) {
        if (i % 3 ==0)
        {
            sb.append(String.format("%-45s", a.get(i)));
            sb.append("\n");
        }
        else
            sb.append(String.format("%-45s", a.get(i)));
    }
    return sb;
}

我必须优化此代码,我尝试了半个小时,甚至没有运气。

可以帮我吗?

3 个答案:

答案 0 :(得分:2)

如果您要优化代码,则不应切换到Stream API。相反,请将其更改为使用单个Formatter,而不是为每个元素(隐藏在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;
}

鉴于这种情况下格式的简单性,您甚至可以完全消除Formatter

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;
}

答案 1 :(得分:1)

这是您可以做的最好的事情。这很丑陋,因为流不知道列表索引。转换为使用流不是一个很好的选择。

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);
}

答案 2 :(得分:0)

您只能并行化字符串并因此加快字符串的格式化速度,而不能并行化已格式化部分的串联,因为它们必须是有序的。

您也可以通过流连接格式化的部分,但是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);

输出为:

output: string1                                      
string2                                      string3                                      string4                                      
string5        

备注:考虑使用System.getProperty(“ line.separator”)而不是“ \ n”。