Использование потоков лямбда в Java 8 - PullRequest
0 голосов
/ 10 января 2019

Я хотел бы оптимизировать приведенный ниже код, чтобы взять существующий ArrayList и создать новый список на основе приведенной ниже логики. Позволяет ли потоковая передача / лямбда в Java 8

for (ShipmentTracingDTO tracing : tracings) {
    if (tracing.getDestination()) {
        newTracings.add(tracing);
        break;
    }
    newTracings.add(tracing);
}

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Если бы мне понадобилась такая обработка, я бы разделил ее на два отдельных потока:

final int lastElemPosition = tracings.size() - 1;
final int firstElemWithGetDestinationTruePosition = IntStream.range(0, lastElemPosition)
    .filter(i -> tracings.get(i).getDestination())
    .findFirst()
    .orElse(lastElemPosition);
final List<ShipmentTracingDTO> desiredElements = IntStream.rangeClosed(0, firstElemWithGetDestinationTruePosition)
    .mapToObj(tracings::get)
    .collect(Collectors.toList());
0 голосов
/ 10 января 2019

Во-первых, я хотел бы отметить, что с исходным кодом, который вы хотите изменить, не так много ошибок. Просто потому, что в Java есть потоки, у вас нет для их использования.

Чтобы использовать потоки, я бы разбил решение на две фазы:

OptionalInt indexOfMatchingItem = IntStream.range(0, tracings.size())
        .filter(i -> tracings.get(i).getDestination())
        .findFirst();

List<ShipmentTracingDTO> newTracings = new ArrayList<>(
        indexOfMatchingItem
                .map(i -> tracings.subList(0, i + 1))
                .orElse(tracings));

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

Я создал новый ArrayList, чтобы на него не повлияли никакие последующие изменения в исходном списке tracings. Если tracings является неизменным, вы можете пропустить создание нового ArrayList.

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

Альтернативное (возможно, более читаемое, но менее производительное) решение:

List<ShipmentTracingDTO> newTracings =
        Stream.concat(
            tracings.stream().takeWhile(i -> !tracings.get(i).getDestination()),
            tracings.stream().dropWhile(i -> !tracings.get(i).getDestination()).limit(1)
        ).collect(toList());
0 голосов
/ 10 января 2019

Вы можете сделать это, используя IntStream.range и List.subList, возможно, как:

List<ShipmentTracingDTO> newTracings = tracings.subList(0, IntStream.range(0, tracings.size())
       .filter(i -> tracings.get(i).getDestination())
       .map(a -> a + 1) // to include the index of occurrence
       .findFirst()
       .orElse(tracings.size())); // else include all until last element

Примечание : Это просто представление tracings, и поэтому изменение базового списка tracings также отразится на изменениях в newTracings. Если вы хотите отделить их, вы можете создать new ArrayList<>() из решений.

Редактировать : В комментариях от Хольгера вы можете альтернативно использовать:

List<ShipmentTracingDTO> newTracings = IntStream.rangeClosed(1, tracings.size())
        .filter(i -> tracings.get(i - 1).getDestination()) // i-1 to include this as well
        .mapToObj(i -> tracings.subList(0, i)) // Stream<List<ShipmentTracingDTO>>
        .findFirst() // Optional<List<ShipmentTracingDTO>>
        .orElse(tracings); // or else the entire list
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...