Как переделать цикл в стрим?

Есть метод, который получает данные из класса и собирает в нужном формате в лист. Я реализовал это с помощью цикла, но необходимо использовать прелести JAVA 8 API, поэтому пытался заменить цикл на работу с .stream(), но пока безуспешно. Как это можно сделать?

private ArrayList<String> collectReport() {
    String timeFormat = "m:ss.SSS";
    String reportFormat = "%d. %s | %s | %s";
    int counter = 0;
    ArrayList<String> list = new ArrayList<>();
    for (ReportRecord dataRecord : recordList) {
        String name = dataRecord.getName();
        String team = dataRecord.getTeam();
        String time = LocalTime.ofNanoOfDay(dataRecord.getTimeDiff()).format(DateTimeFormatter.ofPattern(timeFormat));

       list.add(String.format(reportFormat, (1 + counter++), name, team, time));
        if (counter == 15) {
            list.add("—".repeat(60));
        }
    }
    return list;
}

Ответы (1 шт):

Автор решения: Nowhere Man

Имеет смысл создать отдельный метод для преобразования в строку элемента списка recordList, затем использовать IntStream для получения стрима индексов и преобразования индексов в строки.

private String recordToString(int index) {
    String timeFormat = "m:ss.SSS";
    String reportFormat = "%d. %s | %s | %s";

    ReportRecord dataRecord = recordList.get(index);

    String name = dataRecord.getName();
    String team = dataRecord.getTeam();
    String time = LocalTime.ofNanoOfDay(dataRecord.getTimeDiff()).format(DateTimeFormatter.ofPattern(timeFormat));

    return String.format(reportFormat, 1 + index, name, team, time);
}

// вернуть только строки исходного списка
private List<String> collectReport() {
    return IntStream.range(0, recordList.size())
        .mapToObj(this::recordToString)
        .collect(Collectors.toList());
}

Разделители можно добавить отдельно.

В Java 16 и выше можно использовать метод Stream::toList для получения немодифицируемого списка строк.


Однако, если строки-разделители обязательно должны быть в результирующем списке в качестве отдельного элемента, можно слегка модифицировать представленный метод recordToString, чтобы он возвращал стрим строк, к которым затем потребуется применить операцию Stream::flatMap.

Также, для получения конкретной реализации ArrayList<String> можно использовать коллектор Collectors.toCollection(ArrayList::new) вместо привычного Collectors.toList().

private Stream<String> recordToStream(int index) {
    String timeFormat = "m:ss.SSS";
    String reportFormat = "%d. %s | %s | %s";
    String delimiter = "-".repeat(60);

    ReportRecord dataRecord = recordList.get(index);

    String name = dataRecord.getName();
    String team = dataRecord.getTeam();
    String time = LocalTime.ofNanoOfDay(dataRecord.getTimeDiff()).format(DateTimeFormatter.ofPattern(timeFormat));

    String result = String.format(reportFormat, 1 + index, name, team, time);
    return (1 + index) % 15 == 0 
        ? Stream.of(result, delimiter) 
        : Stream.of(result);
}

// вернуть строки исходного списка с разделителями
private ArrayList<String> collectReport() {
    return IntStream.range(0, recordList.size())
        .mapToObj(this::recordToStream) // Stream<Stream<String>>
        .flatMap(s -> s) // Stream<String>, вариант .flatMap(Function.identity())
        .collect(Collectors.toCollection(ArrayList::new));
}
→ Ссылка