带有两个列表的 Java 8 流
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/52477960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 stream with two Lists
提问by gozluklu_marti
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?
我有一个方法需要 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;
}
采纳答案by Eugene
Seems that this is what you are after:
似乎这就是你所追求的:
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());
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.
请注意,对于每个,id
您正在迭代整个列表tracks
;这有O(n*m)
复杂性。这通常被视为不好,您可以改进它。
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 amortizedcomplexity 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:
为了使它更好,您首先HashSet
要从Customer
; 中创建一个ids 。有了它,HashSet
您现在contains
可以使用您感兴趣的 id调用它,因为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()));
回答by Eugene
You could try something like this
你可以试试这样的
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());
回答by Nigel Nop
The important Operator here is flatMap
这里重要的运算符是 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());
回答by dehasi
Firstly you can create a Set of allowed Ids:
首先,您可以创建一组允许的 ID:
Set<Long> collect = customers.stream()
.filter(customer -> customer.getTrack() != null)
.map(customer -> customer.getTrack().getId())
.collect(Collectors.toSet());
Then you can filler your track collection
然后你可以填充你的曲目收藏
Set<CusomerTrack> tracksToSave = tracks.stream()
.filter(track -> collect.contains(Long.valueOf(track.getId())))
.collect(Collectors.toSet());
回答by Hadi J
Try this one
试试这个
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);
});
回答by davidxxx
An additional way favoring method reference usage :
有利于方法引用使用的另一种方式:
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());
回答by Usman Ali
You need to filter the null values first and then filter it with the list of customerTrack.
您需要先过滤空值,然后使用 customerTrack 列表过滤它。
Hope this answer helps you.
希望这个回答对你有帮助。
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());