【问题标题】:Java Hashmap: get all keys greater than X valueJava Hashmap:获取大于X值的所有键
【发布时间】:2019-07-13 07:58:18
【问题描述】:
 import java.util.*;
 import static java.lang.String.format;

 public class Dumpground {

     private static final String[] fruits = new String[]{"apples", "bananas", "grapes", "oranges", "watermelons", "kiwis"};
     static Map<String, Long> expirationMap;

     public static void main(String[] args) {
         long expiration = 1L;
         expirationMap = new HashMap<>();
         for (String fruit : values()){
             expirationMap.put(fruit, expiration);
             expiration++;
         }
         for (Map.Entry<String, Long> item : expirationMap.entrySet()) {
               String key = item.getKey();
               Long value = item.getValue();
               System.out.println(format("key: %s, value: %s", key, value));
           }


     }

     public static String[] values() {return fruits;}
 }

输出

key: oranges, value: 4
key: watermelons, value: 5
key: kiwis, value: 6
key: bananas, value: 2
key: apples, value: 1
key: grapes, value: 3

我正在尝试找到一种巧妙的方法来 grep 其值大于 X 的所有键

例如,如果 X == 3,它应该返回橙子、西瓜和猕猴桃

显而易见的方法是遍历 map 并比较值,但是有没有简单、简洁的方法呢?

【问题讨论】:

标签: java java-8 hashmap java-stream


【解决方案1】:

这将使用流来解决问题:

expirationMap.entrySet().stream().filter(e -> e.getValue() > 3)
             .forEach(e -> {
                 System.out.println("key " + e.getKey() + "value" + e.getValue());
              });

【讨论】:

    【解决方案2】:

    流,是的。使用

    expirationMap.entrySet().stream()
        .filter(entry -> entry.getValue() > 3L)
        .map(Entry::getKey)
        .collect(Collectors.toList());
    

    获取键列表。

    我们需要对映射条目进行流式传输,而不仅仅是值或键,因为我们需要比较一个(值)并返回另一个(键)。好的,一个不需要,正如 cmets 中所指出的那样。

    filter方法获取值并与3比较,丢弃不大于3的元素;然后我们使用map 方法将条目映射到它们的值。最后,我们将结果收集到List

    【讨论】:

    • 我们需要对地图条目进行流式传输...但这不是必须的。详见my answer
    • @nullpointer 适用于大多数地图,例如HashMapTreeMap,仅遍历键并为每个键执行查找是相当低效的,而 Map.Entry 提供对值的免费访问。
    • @Holger 免费访问价值..这仍然意味着O(1)(与查找相同)不是吗?在这种情况下,将条目映射到键是否不会再次产生一些成本?我知道,理想情况下,差异应该是最不担心的,只是想详细说明这些概念。
    • @nullpointer O(1) 并不意味着“免费”。它仅表示成本与其他变量无关,例如包含元素的数量。 HashMap.Entry.getValue() 只读取一个字段,HashMap.get(…) 计算哈希码,读取数组条目,在键上调用 equals,可能还必须处理冲突,这两者之间仍然存在差异。这适用于这里的每一个键。更不用说TreeMap,其中查找是O(log n)
    【解决方案3】:

    仅使用 set 和 key 查找略有不同的变体:

    Set<String> greppedKeys = expirationMap.keySet().stream() // keyset only
            .filter(key -> expirationMap.get(key) > 3L) // X here being 3L
            .collect(Collectors.toSet()); // all keys would be unique anyway
    

    【讨论】:

      【解决方案4】:

      另一种可读方法见下文。

      expirationMap.forEach((key, value) -> {
           if (value > x) {
               System.out.println(format("key: %s, value: %s", key, value));
           }
      });
      

      .forEach 部分将遍历映射的 entrySet() 并将每个条目的键和值分别提取到 (key, value) 上。

      【讨论】:

        【解决方案5】:

        除了其他人所做的之外,另一种方法是使用 Interface Predicate&lt;T&gt;,其默认方法 test(T t) 可用于评估大于 3 的值。

          Predicate<Long> filterGreater3 = f-> f>3;
          expirationMap.entrySet()
                       .stream()
                       .filter(x->filterGreater3.test(x.getValue()))
                       .forEach(System.out::println);
        

        【讨论】:

          猜你喜欢
          • 2016-03-09
          • 2012-08-07
          • 2016-03-08
          • 2014-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-01
          • 2010-11-25
          相关资源
          最近更新 更多