【问题标题】:how can I filter map entries based on set of entries如何根据条目集过滤地图条目
【发布时间】:2012-06-28 14:25:22
【问题描述】:

我正在使用 google guava 12 并有一张地图:

Map<OccupancyType, BigDecimal> roomPrice;

我有一套:

Set<OccupancyType> policy;

如何根据policy 过滤roomPrice map 中的条目并返回过滤后的映射?

filteredMap 需要具有来自policy 的所有值。如果 roomPrice 地图没有政策条目,我想输入默认值。

【问题讨论】:

标签: java map set guava predicate


【解决方案1】:

无需使用 Guava,Maps.filterKeys() 也可以为大型地图产生性能非常差的结果。

// (new map can be initialized to better value to avoid resizing)
Map<OccupancyType, BigDecimal> filteredMap = new HashMap<>(roomPrice.size());
for (OccupancyType key: policy) {
    // contains() and get() can usually be combined
    if (roomPrice.contains(key)) {
       filteredMap.put(key, roomPrice.get(key));
    }
}

【讨论】:

    【解决方案2】:

    既然你有一组键,你应该使用Maps.filterkeys(),Guava 还提供了一组非常好的谓词,你可以开箱即用。在您的情况下,Predicates.in() 之类的东西应该可以工作。

    所以基本上你会得到:

    Map<OccupancyType, BigDecimal> filteredMap
        = Maps.filterKeys(roomPrice, Predicates.in(policy));
    

    希望对你有帮助。

    【讨论】:

    • 谢谢!我对 Predicates 还是很陌生,不确定它将如何生成一个适用于我的地图的谓词。另外,有什么方法可以确保filteredMap 应该具有策略中的所有值。如果 roomPrice 地图没有政策条目,我想输入默认值。
    • 如果你有一个带有“默认”条目的地图,你可以这样做:filteredMap.putAll(Maps.difference(filteredMap, defaultMap).entriesOnlyOnRight());
    • 另外,你可以看看这篇文章:scaramoche.blogspot.de/2010/08/… 它有一些很好的谓词用法示例。
    • Maps.filterKeys() 通常是一个糟糕的解决方案,因为它会为 contains() 或 size() 等方法生成复杂度为 O(n) 的原始 Map 的 liveView。更好地使用来自stackoverflow.com/questions/28856781的答案
    【解决方案3】:
    • 覆盖并实现 equalshashcode in OccupancyType
    • 循环通过roomPrice的密钥集并收集 过滤器中包含的元素。

    类似这样的:

    Map<OccupancyType, BigDecimal> filteredPrices = new HashMap<OccupancyType, BigDecimal>();
    for(OccupancyType key : roomPrice.keySet()) {
        if(policy.contains(key) {
            filteredPrices.put(key, roomPrice.get(key));
        }
    }
    

    更新

    好的,在 Google Guava 上阅读了一些内容后,您应该可以执行以下操作:

    Predicate<OccupancyType> priceFilter = new Predicate<OccupancyType>() {
        public boolean apply(OccupancyType i) {
            return policy.contains(i);
        }
    };
    

    然后

    return Maps.filterValues(roomPrice, priceFlter);
    

    应该可以解决问题。

    【讨论】:

    • 谢谢!我知道那行得通,但我也在学习使用番石榴。我希望使用来自 google-guava 的 Maps.filterEntries(...)[link](docs.guava-libraries.googlecode.com/git-history/release/javadoc/…, com.google.common.base.Predicate))[/link] 之类的东西。您是否有任何想法我可以如何做到以上?
    • 好的,我在阅读后更新了我的答案,让我知道它是否有效!
    • 你不觉得应该是Maps.filterEntries(roomPrice, priceFilter);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多