我有一个方法采用2个列表作为参数,正如您在方法主体中看到的那样,我想进行一些过滤并将结果返回给调用方。我想将此代码转换为带有lambda表达式的Java 8流,但我无法弄清楚。我最终为此创建了多个流,这超出了此重构(IMHO)的目的。我想知道的是,我如何以一种简单的方式将其重构为一个流?
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;
}
答案 0 :(得分:5)
似乎这就是您所追求的:
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)
的复杂性。通常认为这很糟糕,您可以改善它。
要使其变得更好,您首先要从HashSet
创建一个Customer
个ID;有了HashSet
之后,您现在就可以使用您感兴趣的ID调用contains
,因为contains
的时间复杂度为O(1)
(实际上称为 amortized 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()));
答案 1 :(得分:1)
首先,您可以创建一组允许的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());
答案 2 :(得分:1)
支持方法引用用法的另一种方式:
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());
答案 3 :(得分:0)
您可以尝试这样的事情
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());
答案 4 :(得分:0)
这里的重要运算符是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());
答案 5 :(得分:0)
尝试这个
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);
});
答案 6 :(得分:0)
您需要先过滤null值,然后再使用customerTrack列表对其进行过滤。
希望这个答案对您有帮助。
'exclude'