Как сравнить данные ключи из списка массивов с ключами HashMap? - PullRequest
1 голос
/ 21 мая 2019

В моем 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 заданным ключам в массиве и не равны ли значения ключей на карте.

Я пробовал много вариантов.Либо я получил nullPointerExceptions, либо я всегда получаю нулевое возвращение.

Ответы [ 4 ]

1 голос
/ 21 мая 2019

Я могу ошибаться, но, как я понял, вы хотите проверить следующее условие:

  1. Ключи HashMap должны принадлежать следующему списку ключевых слов {"id", "name", "lastname"}.
  2. Никакое значение из HashMap не должно быть равно нулю.

Вы можете использовать что-то похожее на это:

map.entrySet()
   .stream()
   .allMatch(entry -> keys.contains(entry.getKey()) && entry.getValue() != 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);

Обратите внимание, что я использую фабричные методы коллекций для создания Map, List и Set, который был добавлен в java-9, но в потоковом APIдоступен с версии Java-8.

Что касается вашего кода, вы всегда получите 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. 

Надеюсь, вы найдете это полезным.

0 голосов
/ 21 мая 2019

Вы возвращаете true для первого соответствующего ключа, тогда как вы хотите проверить, присутствуют ли все ключи. Кроме того, ваш код неполон, поэтому невозможно провести полную диагностику.

Но в любом случае нет смысла перебирать карту здесь. Просто используйте

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);
}
0 голосов
/ 21 мая 2019

Просто используя 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));
    }


}

Но я бы порекомендовал вам использовать систему валидации, если ваш проект позволяет ее более точную валидацию.

0 голосов
/ 21 мая 2019

Не должно возвращаться немедленно, если найдено совпадение, так как мы хотим проверить «все необходимые» параметры.Попробуйте что-то вроде:

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;
}
...