Java 8 Stream / Collectors按地图分组

时间:2016-08-12 11:10:45

标签: java java-8 java-stream

我有两张地图

  1. scoreMap<String,Float>以组名作为键及其名称 得分为值
  2. thresholdMap<Float,String>有一个阈值     作为价值的关键和相关评论。
  3. 我需要想出来     Map<String,List<String>>来自此。请注意,Map<comment,List of groups its applicable to>Map<group, comment>也可以。
  4. 逻辑只是从score获取scoresMap,并将其与threshold地图中的threshold进行比较。根据它的位置(即高于高,高和中,或低于中),从thresholdMap中选择相关的注释。

    可能是这样的:

    BiFunction<Map<String,Float>, Map<Float,String>, Map<String,String>> or
    BiFunction<Map<String,Float>, Map<Float,String>, Map<String,List<String>>>
    

    我还没有弄清楚如何groupingBy使用检查3个条件的Predicate,所以没有其他样本Stream代码道歉!非流代码看起来像这样(不使用地图):

    if(orgScorePct >= HI_THRESHOLD) 
        return "ORG_HI_SCORE_COMMENT";
    if(orgScorePct < HI_THRESHOLD && orgScorePct > MED_THRESHOLD) 
        return "ORG_MED_SCORE_COMMENT";
    return "ORG_LOW_SCORE_COMMENT";
    

1 个答案:

答案 0 :(得分:2)

首先,使用TreeMap作为阈值会更容易:因为它是键上的有序映射,确定给定值的正确阈值注释只是一个问题获得该值的floorEntry。天花板入口对应于具有恰好在给定的下方的钥匙的入口。类似地,有ceilingEntry来检索在给定的密钥之后具有密钥的条目。

考虑到这一点,我们可以拥有以下内容(包含示例数据):

Map<String,Float> scoreMap = new HashMap<>();
TreeMap<Float,String> thresholdMap = new TreeMap<>();

scoreMap.put("name1", 1.0f);
scoreMap.put("name2", 2.0f);
scoreMap.put("name3", 3.0f);
scoreMap.put("name4", 5.0f);

thresholdMap.put(0.5f, "comment0");
thresholdMap.put(1.5f, "comment1");
thresholdMap.put(4.5f, "comment2");

Map<String,List<String>> result =
    scoreMap.entrySet()
            .stream()
            .collect(Collectors.groupingBy(
                e -> thresholdMap.floorEntry(e.getValue()).getValue(),
                Collectors.mapping(Map.Entry::getKey, Collectors.toList())
            ));

这导致{comment2=[name4], comment1=[name3, name2], comment0=[name1]}这是正确的:"comment2"的阈值为4.5,只有"name4"得分大于此值; "comment1"的阈值为1.5,"name2""name3"的得分均为1.5到4.5之间等。

如果没有楼层入口,请小心:可能是分数没有相应的阈值;例如,在上面的数据中,得分为0会导致问题。要处理这种情况,您需要检查floorEntry是否返回null并通过返回默认值来相应地处理它。