【问题标题】:How to filter TreeMap<MyKey, Map<Key2,List<Kids>>> ,如何过滤 TreeMap<MyKey, Map<Key2,List<Kids>>> ,
【发布时间】:2020-10-15 03:15:42
【问题描述】:

FundingRank 和 SourceBucket 是枚举,但本质上是 int

enum FundingRank {
    LESS_THAN_0(0),
    LESS_THAN_1(1),
    LESS_THAN_100(100);

    private final int rank;
    FundingRank(int i) {
        this.rank = i;
    }
}

enum ScoreBucket {
    MORE_THAN_1000(1000),
    MORE_THAN_500(1000),
    MORE_THAN_100(100),
    MORE_THAN_10(10);

    private final int bucket;
    ScoreBucket(int i) {
        this.bucket = i;
    }
}

我有一个 TreeMap&lt;FundingRank, TreeMap&lt;scoreBucket, List&lt;Kids&gt;&gt; &gt; 持有类似的数据

fundingRank  scoreBucket List<Kids>
0              1000       List(with 1 elements) 
                500       List(with 2 elements)
                100       List(with 4 elements)
                 10       List(with 3 elements)
1             1000        List(with 4 elements)
                500       List(with 7 elements)
                100       List(with 4 elements)
                 10       List(with 3 elements)

现在,我想找到最少有 5 个孩子的元素最小 fundingRank 和最大 scoreBucket,如果不是,那么最小 fundingRank 和最大 scoreBucket

 myMap.entrySet().stream()
     .filter(e -> e.getvalue().entryset().stream()
         .filter(e2 ->e2.getvalue().size()).findfirst();


Output sorted map like this:

1 500  List(with 7 elements)
0 100  List(with 4 elements)
1 1000 List(with 4 elements)
1 100  List(with 4 elements)
0 10   List(with 3 elements)
...

所以,我正在尝试对 TreeMap> 进行排序,排序顺序定义为 MinFunding 排名和最大 ScoreBucket(阈值为 5,如果桶有 5 个孩子,则意味着如果有其他具有更多孩子的较小存储桶,得分较高的存储桶获胜,或者如果有较大的 FundingRank 具有更高的存储桶大小和更多的孩子,如果满足 5 个孩子的门槛,仍然是较低的fundingBucket行获胜),然后拿起第一排 希望现在很清楚

【问题讨论】:

  • 你能举一些例子来说明你想在这里实现什么吗?
  • 不明白你想要什么结果?并且至少 5 个孩子意味着总结一个 fundRank 的所有孩子?
  • List&lt;Kids&gt;nested TreeMap&lt;Key2, List&lt;Kids&gt;&gt; 中的值类型,我认为 OP 的意思是 List&lt;Kids&gt;.size() &gt;= 5MyKey 似乎是fundingRank,一个Integer,而Key2 似乎是scoreBucket,另一个Integer。然后我可能会完全离开,OP应该edit他们的问题并添加更多细节和清晰度。
  • 您的示例排序顺序与您的文本不匹配
  • @fps 目标:想要找到 [fundingRank, scoreBucket, list_Kids] 三元组的最小资金和最大分数,但前提是孩子的列表有超过 5 个元素,但如果没有ScoringBucket 有 >=5 个孩子,而不仅仅是返回 minFundingBucket 和 max ScoreBucket 以及相应的孩子列表

标签: java java-stream grouping treemap collectors


【解决方案1】:

如果您想找到最小FundingRank 和最大ScoreBucket[fundingRank, scoreBucket, list_Kids] 三胞胎,但只考虑超过 5 个孩子的三胞胎,您可以流式传输外部和内部地图的条目并使用自定义 @ 987654328@找到它:

Optional<Map.Entry<FundingRank, Map.Entry<ScoreBucket, Integer>>> triplet = 
    outerMap.entrySet().stream()
        .flatMap(outerEntry -> outerEntry.getValue().entrySet().stream()
            .map(innerEntry -> Map.entry(
                 outerEntry.getKey(), 
                 Map.entry(innerEntry.getKey(), innerEntry.getValue().size()))))
        .min(Comparator.comparingInt(t -> t.getValue().getValue() >= 5 ? 0 : 1)
            .thenComparing(t -> t.getKey())
            .thenComparing(t -> t.getValue().getKey(), Comparator.reverseOrder())
            .thenComparing(t -> t.getValue().getValue(), Comparator.reverseOrder()));

triplet.ifPresent(it -> /* do something with the triplet */);

这会将三元组创建为Map.Entry&lt;FundingRank, Map.Entry&lt;ScoreBucket, Integer&gt;&gt;,并根据给定的Comparator 找到最小三元组,(我希望)满足您的要求。

我们在Stream.min 中使用Comparator,它首先按01 排序,这是一个指定是否有超过5 个孩子的标志。如果有 5 个以上的孩子,则此标志为 0,因此有超过 5 个孩子的三胞胎首先出现。然后,比较器按FundingRank 升序排序,然后按ScoreBucket 降序排序,最后,如果出现平局,则由降序的实际孩子数打破(以防万一)。

这里我使用了 Java 9+ 的 Map.entry(...) 方法来创建条目。如果您使用的是 Java 8,则应使用 new AbstractMap.SimpleEntry(...) 创建条目。

【讨论】:

  • 冬青莫莉!调试也很愉快:D
  • 嗨@尤金!我不确定Comparator 链是否会在不添加见证类型的情况下编译...
猜你喜欢
  • 2021-05-30
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
相关资源
最近更新 更多