【问题标题】:How to compare given keys from array list with HashMap keys?如何将数组列表中的给定键与 HashMap 键进行比较?
【发布时间】:2019-05-21 15:07:40
【问题描述】:

在我的 WebApplication 中,我必须检查来自 requestBody 的许多传入查询参数。为了不在每个方法中编写相同的代码,我想编写一个返回布尔值的函数。当接收到所有必需的参数并且 entrySet 的值不为 null 时,该方法应返回 true(否则为 false),我可以稍后在程序中使用传入的查询参数。

因此,我将所有传入参数打包到一个 HashMap 中。此外,我在该方法中添加了一个特定列表,该列表提供了检查所需的参数(键)。

queryParams 示例图:

Map queryParams = new HashMap();

queryParams.put("id", "1");
queryParams.put("name", "Jane");
queryParams.put("lastname", "Doe");

示例数组:

String[] keys = {"id", "name", "lastname"};

方法的最新版本:



public static Boolean checkRequestParams(Request request, String[] keys) {
        Map params = (JsonUtil.fromJson(request.body(), HashMap.class));

        Iterator it = params.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry) it.next();
            for (int i = 0; i < keys.length; i++) {
                if (pair.getKey().equals(keys[i])) {
                    return true;
                }

            }

数组提供的键是客户端发送的 QueryParams。不,我想比较它们并检查 Hashmap 中的键是否等于数组中的给定键,以及 Map 中键的值是否不为空。

我尝试了很多变化。要么我得到了 nullPointerExceptions,要么我总是得到一个 null 返回。

【问题讨论】:

  • 你使用getValue()而不是getKey()有什么原因吗?
  • 不要使用原始类型并提供您作为输入传递的数据和您期望的数据。范围太广了。
  • 谢谢,是的,这是一个错误,已修复。
  • 这一切听起来就像是渴望成为 JSR-303 验证。
  • {"id, name, lastname"};应该是 {"id", "name", "lastname"}

标签: java arrays hashmap compare


【解决方案1】:

我可能错了,但据我了解,您想要验证以下条件:

  1. HashMap 键必须属于以下关键字列表{"id", "name", "lastname"}
  2. HashMap 中的任何值都不应等于 null。

你可能会使用类似这样的东西:

map.entrySet()
   .stream()
   .allMatch(entry -> keys.contains(entry.getKey()) && entry.getValue() != null)

所以我们遍历entrySet 并检查entry key 是否属于定义的set 以及value 是否不为null。 这是一个更详细的示例:

Set<String> keys = Set.of("id", "name", "lastname");
Map<String,List<Integer>> map = Map.of("id", List.of(1,2,3), "name", List.of(4,5,6));

map.entrySet()
        .stream()
        .allMatch(entry -> keys.contains(entry.getKey()) && entry.getValue() != null);

Map<String,List<Integer>> map1 = Map.of("id", List.of(1,2,3), "not in the keys", List.of(4,5,6));
map1.entrySet()
        .stream()
        .allMatch(entry -> keys.contains(entry.getKey()) && entry.getValue() != null);

请注意,我正在使用集合工厂方法创建 MapListSet,它们已添加到 java-9,但从 java-8 开始可以使用流 api。

至于你的代码,你总是会得到true,因为只要有一个满足条件的entrySet,方法就会返回结果。

for (int i = 0; i < keys.length; i++) {
                if (pair.getKey().equals(keys[i])) {
                    return true; // one single match found return true. 
                }

            }

您可以尝试反转条件并在出现不匹配时立即返回 false。

for (int i = 0; i < keys.length; i++) {
                if (!pair.getKey().equals(keys[i]) || pair.getValue() == null) {
                    return false; // mismatch found, doesn't need to verify 
                    // remaining pairs. 
                }

            }
return true; // all pairs satisfy the condition. 

我希望你觉得这很有用。

【讨论】:

  • 你想测试什么,keys是否包含map的所有键或者map是否包含keys的所有元素?
  • map是否包含keys的所有元素。
  • @Hubi 那么它与这个答案相反。
【解决方案2】:

只要使用 vanilla Java,你就可以尝试这样的事情。

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ValidatorExample {

    public boolean checkRequestParams(Map<String, Object> request, List<String> keys) {
        return isEqualCollection(request.keySet(), keys)
                && !containsAnyNull(request.values());
    }

    private boolean isEqualCollection (Collection<?> a,Collection<?> b){
        return a.size() == b.size()
                && a.containsAll(b)
                && b.containsAll(a);
    }

    private boolean containsAnyNull(Collection<?> collection){
        return collection.contains(null);
    }

    public static void main(String[] args) {
        ValidatorExample validatorExample = new ValidatorExample();
        List<String> keys = Arrays.asList("id", "name", "lastname");

        Map<String, Object> parametersOk = new HashMap<>();
        parametersOk.put("id", "idValue");
        parametersOk.put("name", "nameValue");
        parametersOk.put("lastname", "lastnameValue");
        // True expected
        System.out.println(validatorExample.checkRequestParams(parametersOk, keys));

        Map<String, Object> parametersWithInvalidKey = new HashMap<>();
        parametersWithInvalidKey.put("id", "id");
        parametersWithInvalidKey.put("name", "nameValue");
        parametersWithInvalidKey.put("lastname", "lastnameValue");
        parametersWithInvalidKey.put("invalidKey", "invalidKey");
        // False expected
        System.out.println(validatorExample.checkRequestParams(parametersWithInvalidKey, keys));

        Map<String, Object> parametersWithNullValue = new HashMap<>();
        parametersWithNullValue.put("id", null);
        parametersWithNullValue.put("name", "nameValue");
        parametersWithNullValue.put("lastname", "lastnameValue");
        // False expected
        System.out.println(validatorExample.checkRequestParams(parametersWithNullValue, keys));
    }


}

但如果您的项目允许更准确的验证,我建议您使用验证框架。

【讨论】:

    【解决方案3】:

    如果找到匹配项,则不应立即返回,因为我们要测试“所有必需”参数。尝试类似:

    String[] keys = {"id, "name", "lastname"};
    public static Boolean checkRequestParams(Request request, String[] keys) {
        Map params = (JsonUtil.fromJson(request.body(), HashMap.class));
        for (int i = 0; i < keys.length; i++) {
            Iterator it = params.entrySet().iterator();
            boolean found = false;
            while (it.hasNext()) {
                Map.Entry pair = (Map.Entry) it.next();
                if (pair.getKey().equals(keys[i])) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                return false;
            }
        }
        return true;
    }
    

    【讨论】:

      【解决方案4】:

      您在第一个匹配键上返回true,而您想检查是否存在 所有 键。此外,您的代码不完整,因此无法提供完整的诊断。

      但无论如何,在这里迭代 map 是没有意义的。只需使用

      public static Boolean checkRequestParams(Request request, String[] keys) {
          Map<?,?> params = JsonUtil.fromJson(request.body(), HashMap.class);
          for(String key: keys) {
              if(params.get(key) == null) return false;
          }
          return true;
      }
      

      这将确保每个键都存在并且不映射到null(因为“不映射到null”已经暗示存在)。

      当不考虑到null 的显式映射的可能性时,您可以像这样简单地检查所有键的存在

      public static Boolean checkRequestParams(Request request, String[] keys) {
          Map<?,?> params = JsonUtil.fromJson(request.body(), HashMap.class);
          return params.keySet().containsAll(Arrays.asList(keys));
      }
      

      或者,如果任何映射值为null,即使其键不是强制键之一,您也可以认为映射无效。那么,就很简单了

      public static Boolean checkRequestParams(Request request, String[] keys) {
          Map<?,?> params = JsonUtil.fromJson(request.body(), HashMap.class);
          return params.keySet().containsAll(Arrays.asList(keys))
              && !params.values().contains(null);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-24
        • 2020-10-17
        • 2017-06-21
        • 1970-01-01
        相关资源
        最近更新 更多