簡體   English   中英

在java 8中使用streams,lambda

[英]Using streams, lambda in java 8

我想優化下面的代碼來獲取現有的ArrayList並根據以下邏輯創建一個新列表。 Java 8中的streaming / lambda是否可以實現?

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

你可以使用IntStream.rangeList.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<>()

編輯 :在Holger的評論中,您可以選擇使用:

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

如果我需要這樣的處理,我會把它分成兩個獨立的流:

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

首先,我要指出您想要更改的原始代碼沒有太大問題。 正因為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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM