Java 8 stream with two Lists

  • A+

I have a method takes 2 lists as parameters and as you can see in the method body I want to do some filtering and returning the result to the caller. I wanted to convert this code to the Java 8 stream with lambda expressions but I couldn't figure that out. I ended up creating more than one stream for this and it beats the purpose of this refactoring (IMHO). What I wanted to know is that how I do, in a simple way, refactor this into just one stream?

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; } 


Seems that this is what you are after:            .filter(c -> c.getTrack() != null)           .map(c -> c.getTrack().getId())           .flatMap(id -> -> Long.valueOf(track.getId()).equals(id)))           .collect(Collectors.toSet()); 

Just note that for each id you are iterating the entire list of tracks; this has O(n*m) complexity. This is generally see as bad and you can improve it.

To make it better you would first create a HashSet of ids from Customer; having that HashSet you can now call contains on it with the ids you are interested in, since contains has a time complexity of O(1) (it's really called amortized complexity of O(1)). So now your complexity becomes O(n) + O(1), but since O(1) is a constant, it's really O(n) - much better that what you had before. In code:

Set<Long> set =             .filter(c -> c.getTrack() != null)             .map(c -> c.getTrack().getId())             .collect(Collectors.toCollection(HashSet::new));  Set<CusomerTrack> tracksToSave =             .filter(track -> set.contains(Long.valueOf(track.getId()))             .collect(Collectors.toSet())); 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: