Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有两个列表的Java8流_Java_Java 8_Java Stream - Fatal编程技术网

具有两个列表的Java8流

具有两个列表的Java8流,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个方法将2个列表作为参数,正如您在方法体中看到的那样,我想做一些过滤并将结果返回给调用方。我想用lambda表达式将这段代码转换成Java8流,但我想不出来。我最终为此创建了多个流,这超出了重构(IMHO)的目的。我想知道的是,我如何以一种简单的方式将其重构为一个流 public Set<CustomerTrack> getCustomerTracks(List<CusomerTrack> tracks, List<Customer> customers

我有一个方法将2个列表作为参数,正如您在方法体中看到的那样,我想做一些过滤并将结果返回给调用方。我想用lambda表达式将这段代码转换成Java8流,但我想不出来。我最终为此创建了多个流,这超出了重构(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;
}
公共设置getCustomerTracks(列出曲目,列出客户){
Set tracksToSave=new HashSet();
用于(客户:客户){
if(customer.getTrack()==null){
继续;
}
Long allowedTrackId=customer.getTrack().getId();
用于(CustomerTrack轨迹:轨迹){
if(Long.valueOf(track.getId()).equals(allowedTrackId)){
tracksToSave.add(曲目);
}
}
}
返回轨道保存;
}

看来这就是你想要的:

 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
,您都在迭代整个
曲目列表
;这具有
O(n*m)
复杂性。这通常被认为是不好的,你可以改进它

为了使它更好,您应该首先从
Customer
创建一个id的
HashSet
;有了这个
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()));
Set=customers.stream()
.filter(c->c.getTrack()!=null)
.map(c->c.getTrack().getId())
.collect(收集器.toSet());
设置tracksToSave=tracks.stream()
.filter(track->set.contains(track.getId())
.collect(Collectors.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());
Set tracksToSave=customers.stream()
.map(客户::getTrack)
.filter(轨迹->轨迹!=null)
.flatMap(曲目->{
tracks.stream.filter(it->Long.valueOf(it.getId()).equals(track.getId()))
.collect(收集器.toSet());

首先,您可以创建一组允许的ID:

  Set<Long> collect = customers.stream()
                .filter(customer -> customer.getTrack() != null)
                .map(customer -> customer.getTrack().getId())
                .collect(Collectors.toSet());
Set collect=customers.stream()
.filter(客户->客户.getTrack()!=null)
.map(客户->客户.getTrack().getId())
.collect(收集器.toSet());
然后你可以填充你的曲目集

 Set<CusomerTrack> tracksToSave = tracks.stream()
                .filter(track -> collect.contains(Long.valueOf(track.getId())))
                .collect(Collectors.toSet());
Set tracksToSave=tracks.stream()
.filter(track->collect.contains(Long.valueOf(track.getId()))
.collect(收集器.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);
});

有利于方法引用使用的另一种方式:

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)//保持非null跟踪
.map(Track::getId)//Track-to-trackId
.flatMap(trackId->tracks.stream()//收集与trackId匹配的轨迹
.filter(t->Long.valueOf(t.getId()).equals(trackId))
)
.收集(toSet());

您需要先过滤空值,然后使用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());

我真的建议您将轨迹放入id-->对象的hashmap中,现在您得到了O(n2)复杂度,这根本不是efificient@maslan关于你提到的问题,你有什么消息来源我可以读到吗?我想很好地理解:)(我想我现在理解这个问题了)。感谢您指出。问题很简单,如果
客户
中有ID,您就有一个
列表
;对于每个ID,您都要遍历
跟踪
列表以找到您需要的内容。遍历列表具有
O(n)
复杂性,因为您对每个元素都这样做,所以您的总体复杂性是
O(n*m)
。如果您首先从
客户
创建一个
ID集
,您将提高效率,因为
集中包含
,其复杂性为
O(1)
@Eugene(
哈希集
,不同于例如
树集
和O(log n))-我说的对吗?所以你仍然需要遍历一个集合(它是
O(n)
),但是现在在另一个集合中搜索是
O(1)
;从而使总时间为
O(n)+O(1)
,因为
O(1)
是常量,它可以被删除,从而使你的总解
O(n)
-比以前好多了。那不会编译,
flatMap
需要返回一个
,你返回一个
,dehasi的答案可能更好。我被Lambda语法弄糊涂了-谢谢Eugene:DHi Eugene,你能告诉我最有效的方法吗?@Yonetmen刚刚做了。。。(我没有编译这段代码,我真诚地希望我没有遗漏任何东西,比如逗号或括号)谢谢你的回答,但是
collect.contains(track.getId())
应该替换为
collect.contains(Long.valueOf(track.getId())
@Yonetmen为什么简单明了的
collect.contains(track.getId())
替换为
collect.contains(Long.valueOf(track.getId())
?@Holger在我的例子中
CustomerTrack
Id字段是字符串的一种类型。@Yonetmen这对于这个问题来说是一个有价值的信息。任何回答者都应该如何知道这个要求?为什么第一个
customer.getTrack().getId()
返回一个
Long
然后呢?@Holger好吧,这是我的错!我不应该指出它,因为它无关紧要。但既然你问了,我可以解释它。
g