Найти индекс элемента в потоке Java 8 foreach - PullRequest
1 голос
/ 13 мая 2019

По этому поводу уже есть некоторые сообщения, я их просмотрел, но те не решили мою проблему:

У меня есть метод и некоторая логика, я должен оптимизировать код с использованием потоков .

Мой метод: (здесь я пытаюсь распечатать электронные письма в формате)

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 ]

2 голосов
/ 14 мая 2019

Если вы хотите оптимизировать свой код, вам не следует переключаться на 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 голос
/ 13 мая 2019

Это самое лучшее, что вы можете сделать.Это довольно уродливо, потому что потоки не знают индексов списка.Это не очень хороший кандидат для преобразования в использование потоков.

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);
}
0 голосов
/ 13 мая 2019

Вы можете только распараллелить и, следовательно, ускорить форматирование строк, но не объединение отформатированных частей, поскольку они должны быть в порядке.

Вы также можете объединить отформатированные части через поток, ноцикл 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".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...