簡體   English   中英

帶有兩個列表的Java 8流

[英]Java 8 stream with two Lists

我有一個方法需要2個列表作為參數,你可以在方法體中看到我想做一些過濾並將結果返回給調用者。 我想用lambda表達式將此代碼轉換為Java 8流,但我無法弄清楚。 我最終為此創建了多個流,它擊敗了這個重構(恕我直言)的目的。 我想知道的是,我如何以簡單的方式將其重構為一個流?

public Set<CustomerTrack> getCustomerTracks(List<CusomerTrack> tracks, List<Customer> customers) {
    Set<CustomerTrack> tracksToSave = new HashSet<>();
    for (Customer customer : customers) {
        if (customer.getTrack() == null) {
            continue;
        }
        Long allowedTrackId = customer.getTrack().getId();
        for (CustomerTrack track : tracks) {
            if (Long.valueOf(track.getId()).equals(allowedTrackId)) {
                tracksToSave.add(track);
            }
        }
    }
    return tracksToSave;
}

似乎這就是你所追求的:

 customers.stream() 
          .filter(c -> c.getTrack() != null)
          .map(c -> c.getTrack().getId())
          .flatMap(id -> tracks.stream().filter(track -> Long.valueOf(track.getId()).equals(id)))
          .collect(Collectors.toSet());

請注意,對於每個id您將迭代整個tracks列表; 這具有O(n*m)復雜度。 這通常被認為是壞的,你可以改善它。

為了使它更好,你首先要從Customer創建一個HashSet的ID; 擁有該HashSet你現在可以使用你感興趣的id調用contains ,因為contains的時間復雜度為O(1) (它實際上稱為O(1) 攤銷復雜度)。 所以現在你的復雜性變成了O(n) + O(1) ,但是因為O(1)是一個常數,它實際上是O(n) - 比你以前的更好。 在代碼中:

Set<Long> set = customers.stream()
            .filter(c -> c.getTrack() != null)
            .map(c -> c.getTrack().getId())
            .collect(Collectors.toSet());

Set<CusomerTrack> tracksToSave = tracks.stream()
            .filter(track -> set.contains(track.getId())
            .collect(Collectors.toSet()));

首先,您可以創建一組允許的ID:

  Set<Long> collect = customers.stream()
                .filter(customer -> customer.getTrack() != null)
                .map(customer -> customer.getTrack().getId())
                .collect(Collectors.toSet());

然后你可以填充你的曲目集

 Set<CusomerTrack> tracksToSave = tracks.stream()
                .filter(track -> collect.contains(Long.valueOf(track.getId())))
                .collect(Collectors.toSet());

另一種有利於方法引用的方法:

Set<Track> tracks = 
customers.stream()
         .map(Customer::getTrack) // customer to track
         .filter(Objects::nonNull) // keep non null track
         .map(Track::getId)      // track to trackId
         .flatMap(trackId -> tracks.stream() // collect tracks matching with trackId
                                   .filter(t-> Long.valueOf(t.getId()).equals(trackId))
         )
         .collect(toSet());

你可以嘗試這樣的事情

customers
    .stream()
    .map(Customer::getTrack)
    .filter(Objects::nonNull)
    .map(CustomerTrack::getId)
    .flatMap(trackId -> tracks
                        .stream()
                        .filter(track -> Long.valueOf(track.getId()).equals(trackId)))
    .collect(Collectors.toSet());

這里重要的運算符是flatMap

Set<CustomerTrack> tracksToSave = customers.stream()
   .map(Customer::getTrack)
   .filter(track -> track != null)
   .flatMap(track -> {
      tracks.stream.filter(it -> Long.valueOf(it.getId()).equals(track.getId())))
   .collect(Collectors.toSet());

試試這個吧

customers.stream()
          .filter(customer -> customer.getTrack() != null)
          .map(c -> c.getTrack().getId())
          .forEach(allowedTrackId -> { 
           tracks.stream()
          .filter(track -> Long.valueOf(track.getId()).equals(allowedTrackId))
          .forEach(tracksToSave::add);
});

您需要先過濾空值,然后使用customerTrack列表對其進行過濾。

希望這個答案可以幫到你。

return customers.stream().map(cust-> cust.track).filter(track -> track != null).
            collect(Collectors.toList())
            .stream().filter(track-> customerTracks.stream()
                    .anyMatch(ele -> ele.getId() == 
track.getId())).collect(Collectors.toSet());

暫無
暫無

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

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