Java вложенная карта / список - фильтр по содержимому списка, возвращающий родительский объект - PullRequest
0 голосов
/ 22 июня 2019

У меня есть два строковых аргумента для моей функции - «Пицца» и «Чипсы».Я хотел бы использовать потоки, чтобы вернуть автора, чей ключ "foods" имеет содержимое, соответствующее этим двум строкам

List<String> collection = Arrays.asList("Pizza", "Chips");


private static List<Map<String, Object>> authors = Arrays.asList(
    ImmutableMap.of("id", "author-1",
                            "firstName", "Adam",
                            "lastName", "Awldridge",
                            "foods", Arrays.asList("Pizza", "Chips")),
    ImmutableMap.of("id", "author-2",
                        "firstName", "Bert",
                        "lastName", "Bruce",
                        "foods", Arrays.asList("Pizza", "Fish")),
        ... // other authors
        );

Это моя попытка с потоками:

return authors
                    .stream()
                    .filter(authors.stream()
                            .flatMap(author -> author.get("foods"))
                            .findAny(queryFoods))
                    .findFirst().orElse(null);

Я хочуверните первого автора, чьи продукты соответствуют моему запросу.Я думаю, что основная трудность заключается в организации данных - к сожалению, я не могу заставить работать следующий кастинг.

.flatMap(author -> (List<String>) author.get("foods"))

Кроме того, это может слишком часто передаваться авторам (я должен использовать .filter в потокеЯ только что сделал с

authors.stream()

Ответы [ 3 ]

2 голосов
/ 22 июня 2019

Здесь вы не можете напрямую трактовать значение ключа питания как список. Это просто объект. Итак, сначала вам нужно сделать экземпляр проверки, и если это экземпляр List, то вы можете проверить, содержит ли он значения, которые есть в вашей коллекции.

Map<String,Object> firstAuthor =  authors
                                        .stream()
                                        .filter(author -> {
                                            Object foods = author.get("foods");
                                            if(foods instanceof List) {
                                                List foodsList = (List) foods;
                                                return foodsList.containsAll(collection);
                                            }
                                            return false;
                                        })
                                       .findFirst().orElse(null);

ВЫВОД: {id = author-1, firstName = Adam, lastName = Awldridge, продукты = [Пицца, чипсы]}

Приведенный выше код даст вам требуемого автора, если он существует, или же ноль. [Здесь я предположил, что вы хотите проверить, есть ли у автора все продукты питания, которые присутствуют в созданном вами объекте коллекции. Если вы хотите проверить только один из элементов, вы можете использовать метод contains () из java.util.List вместо метода containsAll () . Кроме того, вам придется перебирать объект коллекции, чтобы проверять каждый элемент в коллекции.]

1 голос
/ 22 июня 2019

Я бы решил это путем фильтрации в потоке:

Map<String,Object> author =  authors.stream()
                                    .filter(a -> a.containsKey("foods"))
                                    .filter(a -> a.get("foods") instanceof List)
                                    .filter(a -> ((List) a.get("foods")).containsAll(collection))
                                    .findFirst().orElse(null);
0 голосов
/ 22 июня 2019

Может быть, это то, что вы хотите?

         authors
                    .stream()
                    .filter(a -> a.get("foods").stream().anyMatch(x -> "Pizza".equals(x)))
                    .findFirst().orElse(null);


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...