【问题标题】:Java nested Map/List - filter by list contents, returning parent objectJava 嵌套 Map/List - 按列表内容过滤,返回父对象
【发布时间】:2019-06-21 22:22:14
【问题描述】:

我的函数有两个字符串参数——“Pizza”和“Chips”。我想使用流来返回其“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()

【问题讨论】:

  • 您希望作者匹配您查询中的所有食物还是一个匹配就足够了?
  • 我只查找所有匹配项

标签: java list dictionary java-stream


【解决方案1】:

这里不能直接把foods key 的值当作List。它只是一个对象。所以,首先你需要做一个 check 的实例,如果它是 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, foods=[Pizza, Chips]}

上面的代码将给你所需的作者,如果它存在,否则为空。 [在这里,我假设您要检查作者是否拥有您创建的集合对象中存在的所有食物。如果您只想检查其中一项,则可以使用 java.util.List 中的 contains() 方法而不是 containsAll() 方法。此外,您必须遍历集合对象以检查集合中的每个项目。]

【讨论】:

  • 太完美了。我的解决方法是使用“containsAllFoods”静态方法(返回布尔值)创建一个“作者”类——我可以在我的过滤器中使用它。然而,这让事情有点奇怪,因为我必须这样做 author.getMap.get("foods")。
  • 它也可以这样工作,或者你可以做的是在它之外有一个方法,它为作者提供食物列表和你想要检查的食物集合。你它不会与你的 Author 类耦合。
【解决方案2】:

我会通过在流中过滤来解决它:

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 个条目) - 所以我只是选错了(我应该使用 (List),而不是 (List).
【解决方案3】:

也许这就是你想要的?

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


【讨论】:

  • 我希望所有食物(“Pizza”和“Chips”都在 a.get("foods") 中 - 我将编写我的解决方案作为答案。
猜你喜欢
  • 2017-03-08
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
相关资源
最近更新 更多