簡體   English   中英

使用 Java Streams,我可以根據與具有相同變量的輔助對象列表共享的變量過濾對象列表嗎?

[英]With Java Streams, can I filter a list of objects based on a variable that is shared with a secondary list of objects with that same variable?

我想知道是否有一種方法可以將以下代碼簡單地轉換為某種流來使用,而不是使用 for 循環?

我基本上是想過濾掉某一組游泳者,同時還要確保這些游泳者不在“參加名單”中。

List<Swimmer> swimmingList = //List generated from db;
List<SwimmerAttending> attendingList = //List generated from db;

for(SwimmerAttending s : attendinglist)
   {
     swimmingList = swimmingList.stream()
                                  .filter(i-> i.getSwimerNumber() > 1000 && !s.getSwimmerNumber().equals(i.getSwimmerNumber()))
                                  .collect(Collectors.toList());   
   }

所以我很好奇是否有一種更簡單的方法可以只使用 Streams 來做到這一點? 謝謝。

您的代碼可以簡化,更重要的是,可以使代碼在線性時間 O(n) 內運行,而不是二次時間 O(n^2),目前,因為您在循環內有一個循環(流迭代仍然是一個循環,盡管是一個隱藏的循環)。

要獲得線性時間,您應該將您的出席列表轉換為一組,然后可以在恆定時間內檢查。 像這樣:

swimmingList = //List generated from db;
attendingList = //List generated from db;

Set<Integer> attendingSet = 
   attendingList.stream()
                .map(s -> s.getSwimmerNumber())
                .collect(Collectors.toCollection(HashSet::new));

swimmingList = swimmingList.stream()
                           .filter(i -> i.getSwimmerNumber() > 1000 
                                    && !attendingSet.contains(i.getSwimmerNumber()))
                           .collect(Collectors.toList());

到集合的轉換是線性的(一個循環)並且濾波器也是線性的,這構成了一個全線性算法。

如果您的游泳列表有 1000 個條目,而您的參加列表有 1000 個條目,您的原始代碼將迭代每個參加列表條目,並且對於每個參加者,迭代 1000 個游泳列表條目,總共進行 1,000,000 次迭代。 新代碼將遍歷參加列表一次(1000 次迭代),然后遍歷游泳列表一次(1000 次迭代),並在一個集合上進行成員資格檢查,該集合是 HashSet 上的常量時間,從而使操作總數僅為2000。

您可以先將attendinglist名單映射到他們的游泳運動員號碼:

List<Integer> attendingSwimmerNumbers = 
    attendingList.stream()
        .map(SwimmerAttending::getSwimmerNumber)
        .collect(Collectors.toList());

然后我們可以使用contains來檢查每個游泳者的號碼是否在上面的列表contains

 swimmingList = swimmingList.stream()
                              .filter(i-> i.getSwimmerNumber() > 1000 && attendingSwimmerNumbers.contains(i.getSwimerNumber()))
                              .collect(Collectors.toList());  

這一切都是假設swimmingListattendingList存儲不同類型的對象。 如果它們存儲相同的類型,那么覆蓋SwimmerAttending equals以檢查游泳者編號的相等性可能是有意義的。 然后您可以直接在attendingList上使用contains

 swimmingList = swimmingList.stream()
                              .filter(i-> i.getSwimmerNumber() > 1000 && attendingList.contains(i))
                              .collect(Collectors.toList()); 

暫無
暫無

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

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