【问题标题】:Efficient way to find if map contains any of the keys from a list/iterable查找映射是否包含列表/可迭代项中的任何键的有效方法
【发布时间】:2012-12-13 15:49:38
【问题描述】:

我需要检查一个映射是否包含列表中的任何键,如果包含则返回第一个匹配值。想到的幼稚方法是在两个嵌套循环中进行:

Map<String, String> fields = new HashMap<String, String>();
fields.put("a", "value a");
fields.put("z", "value z");
String[] candidates = "a|b|c|d".split("|");
for (String key : fields.keySet()){
    for (String candidate : candidates) {
        if (key.equals(candidate)){
            return fields.get(key);
        }
    }
}

有没有更好更有效的方法,可能依赖于 Java 标准库?

【问题讨论】:

    标签: java arrays dictionary iteration


    【解决方案1】:
    for(String candidate : candidates) {
     if(fields.containsKey(candidate)) {
      return fields.get(candidate)
     }
    }
    

    如果 null 值可能在 map 中,并且只需要第一个检测到的键,则最好的方法。

    【讨论】:

      【解决方案2】:

      肯定是这样的:

      for (String candidate : candidates) {
           String result = fields.get(key);
           if (result != null) {
               return result;
           }
      }
      

      上面只对每个候选键执行 一个 映射查找。它避免了存在和提取的单独测试,因为提取不存在的键只会给你一个空值。请注意(感谢 Slanec)对于此解决方案,有效键的空值与不存在的键无法区分。

      我不太明白你为什么要进行大小写转换,顺便说一句。

      【讨论】:

      • 这是尽可能高效的方法,但如果 nullMap 中的允许值,则可能会变得棘手。
      • 有趣...我是否正确理解这个想法是只使用一次map.get() 而不是map.contains() + map.get(),因为这样可以避免第二次查找?这很整洁!
      • @NimChimpsky retainAll 具有描述性。
      • @ccpizza - 没错。请注意 Slanec 的警告。地图中的空值,但
      • @ccpizza 实际上,是的,一次,我想。在一个应用程序中,我们没有明确控制 hashmap 的内容,因为它是用户的配置,我们需要捕获设置被访问(但未更改)或重置为默认值的情况。 Anyway, there is a SO question for this.
      【解决方案3】:

      在 Java 8 中你可以这样:

      boolean exists = Arrays.stream(candidates).anyMatch(fields::containsKey);
      

      如果您只是想知道是否有任何候选人是地图的关键。

      如果你想知道第一个或任何你可以使用的:

      Arrays.stream(candidates).filter(fields::containsKey).findAny();
      

      Arrays.stream(candidates).filter(fields::containsKey).findFirst();
      

      根据上面的@Klapsa2503 回答

      【讨论】:

        【解决方案4】:

        我的看法:

        Map<String, String> fields = new HashMap<String, String>();
        fields.put("a", "value a");
        fields.put("z", "value z");
        String[] candidates = "a|b|c|d".split("|");
        for (String candidate : candidates) {
            if (fields.containsKey(candidate)) {
                return fields.get(candidate);
            }
        }
        

        【讨论】:

          【解决方案5】:

          在 Java 8 中你可以使用这个:

          return candidates.stream()
                      .filter(fields::containsKey)
                      .findFirst()
                      .map(fields::get)
                      .orElse(null);
          

          【讨论】:

            【解决方案6】:

            试试

            Set<String> keySet = new HashSet<String>(fields.keySet());    
            keySet.retainAll(list);
            

            所以keySet 应该具有列表中提到的 HashMap 中的所有键

            【讨论】:

            • 我相信这是最短的方法。但是,它可能不是最快的,因为循环在第一个找到的结果处结束,但这会继续工作直到结束。
            • @Slanec,是的,这取决于 OP 是想要获取所有密钥还是只获取第一个。
            【解决方案7】:

            试一试

                List list= Arrays.asList(1, 2, 3);
                HashMap map = new HashMap();
                map.put(1, 1);
                map.put(3, 3);
                Set set = new HashSet(map.keySet());
                set.retainAll(list);
                System.out.println(set);
                Object e = set.isEmpty() ? null : set.iterator().next();
                System.out.println(e);
            

            输出

            [1, 3]
            1
            

            【讨论】:

              【解决方案8】:
              Map<String, String> fields = new HashMap<String, String>();
              fields.put("a", "value a");
              fields.put("z", "value z");
              String[] candidates = "a|b|c|d".split("|");
              List<String> canList = Arrays.asList(candidates );
              for (String key : fields.keySet()){
              
              if (canList .contains(key)) {
              return fields.get(key);
              }
              
              }
              

              【讨论】:

              • 注意:canList.contains 在时间上是线性的。
              【解决方案9】:

              如果您假设映射的键已经是小写,则可以使用单个循环,就像您假设查找值是小写一样。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-07-16
                • 1970-01-01
                • 1970-01-01
                • 2012-03-20
                • 1970-01-01
                • 2021-12-18
                • 2022-10-23
                • 2017-02-04
                相关资源
                最近更新 更多