2014-11-05 326 views
4

我遇到了难以解决Streams API中的问题。那么,从我能说的一个单一的电话中,它是可以解决的,但不是优雅的。下面,我们要获取FeatureContentWeight对象流,按特征和内容进行分组,并根据特征和内容获取最大权重。因为我不需要维护地图,所以我最终从地图中获取了值。问题是,我只想要其中有3项以上的组。因此,我希望特征和内容对的每个特征和内容的最大权重已超过给定的计数。在SQL中,这只是一个简单的HAVING子句。在Streams API中,它看起来并不重要,但我现在只在Streams API上工作了几天。Java 8 Streams API HAVING子句在GroupingBy中等价吗?

任何想法赞赏。

List<FeatureContentWeight> nearestNeighbors = neighborPostings 
    .stream() 
    .collect(
    groupingBy(
     p -> FeatureContent.Create(p.getFeatureId(), p.getContentId()), 
     collectingAndThen(maxBy(comparingDouble(FeatureContentWeight::getWeight)),Optional::get))).values(); 

回答

3

从你的描述看来,你想过滤分组结果的地图。因此,您可以对分组结果应用toMap收集器,然后过滤其values()以仅保留长度为3或更长的收集器。您也可以跳过地图创建并使用收集器,但这可能会更加尴尬。最后,为了转换地图,我发现Guava的帮助函数(例如Maps.filterValues())有时会提供比Java 8更短且更易读的语法(流语法对于列表很好,但对于映射它有时会变得很糟糕)。如果你对Java的8可以使用封闭与番石榴,所以你可以写这样的:

Map<A,B> unfiltered = <Java 8 grouping> 
return Maps.filterValues(unfiltered, list -> list.size() > 3); 
+0

这是很好评论。我同意partitionBy听起来像是满足条件的一个很好的选择。也很高兴看到有人同意在Streams API中使用地图可能有点令人沮丧。我发现自己经常获取条目集或值,然后转换为流等。它变得冗长。同时,我喜欢Streams API,而不是C#Linq,它完全不透明。 – 2014-11-05 19:08:31

+0

@TheOldHag我不知道C#,但我发现Scala的函数转换语法相当不错,无论是列表还是地图。它比Java 8中的冗长,因为它从一开始就被设计成语言,而不是稍后添加,因此没有任何与保留语言中向后兼容性相关的问题。 – 2014-11-05 20:12:14

2

正如你已经注意到了,不幸的是,JDK的API Stream在没有流GROUP BY操作(即使有一个流操作)。 collect()是一个终端操作,将组和聚合收集到具体的Map中。

但是,如article showing SQL clauses and their equivalents in Java 8 Streams中所述,您可以重新传输Map.entrySet()并对其执行进一步的操作。

应用到你的代码(我在这里做一些假设):

Map<FeatureContentWeight, Double> nearestNeighbors = neighborPostings 
    .stream() 

    // GROUP BY featureId, contentId 
    .collect(
     groupingBy(
      p -> FeatureContent.Create(p.getFeatureId(), p.getContentId()) 
     ) 
    ) 

    // HAVING count(*) >= 3 
    .entrySet() 
    .stream() 
    .filter(e -> e.getValue().size() >= 3) 

    // SELECT grp, MAX(weight) 
    .map(e -> e.getValue().stream().collect(
     maxBy(comparingDouble(w -> w.getWeight)) 
    )); 
0

resultMap.values()removeIf(LST - > lst.size()< 3)

+1

能否详细说明一下?并使用3x'格式编码 – Rumid 2017-11-16 13:36:39