java - 有没有办法在一行中将分组列表连接到 Java 8 中的集合中?

标签 java java-8 java-stream

我处于一种奇怪的情况,其中有一个 JSON API,它采用一个包含邻域字符串的数组作为键和一个餐厅字符串数组作为值,这些值被 GSON 解析为 Restaurant 对象(使用 String 定义为邻域和 List<String> 与餐厅)。系统将该数据存储在 map 中,其键是社区名称,值是该社区中的一组餐厅名称。因此,我想实现一个函数,该函数从 API 获取输入,按社区对值进行分组并连接餐馆列表。

受 Java 8 的限制,我不能使用更新的构造(例如 flatMapping)在一行中完成所有操作,而我发现的最佳解决方案是这个,它使用中间映射在连接这些列表之前存储一组列表放入一个 Set 中,作为最终映射中的值存储:

public Map<String, Set<String>> parseApiEntriesIntoMap(List<Restaurant> restaurants) {
    if(restaurants == null) {
      return null;
    }
    Map<String, Set<String>> restaurantListByNeighborhood = new HashMap<>();
    // Here we group by neighborhood and concatenate the list of restaurants into a set
    Map<String, Set<List<String>>> map =
        restaurants.stream().collect(groupingBy(Restaurant::getNeighborhood,
                              Collectors.mapping(Restaurant::getRestaurantList, toSet())));
    map.forEach((n,r) -> restaurantListByNeighborhood.put(n, Sets.newHashSet(Iterables.concat(r))));

    return restaurantListByNeighborhood;
  }

我觉得必须有一种方法可以摆脱那个中间 map 并在一条线上做所有事情......有人有更好的解决方案可以让我这样做吗?

最佳答案

您可以使用 Java-8 简单地使用 toMapmergeFunction定义为:

public Map<String, Set<String>> parseApiEntriesIntoMap(List<Restaurant> restaurants) {
    // read below about the null check
    return restaurants.stream()
            .collect(Collectors.toMap(Restaurant::getNeighborhood,
                    r -> new HashSet<>(r.getRestaurantList()), (set1, set2) -> {
                        set1.addAll(set2);
                        return set1;
                    }));
}

除此之外,应该确保您的方法中第一 block 代码的检查和结果
if(restaurants == null) {
  return null;
}

另一方面,当处理空 Collection s 和 Map ,它应该是多余的,因为上面的代码会根据流的性质为空列表返回空 Map 并收集操作本身。

注意:此外,如果您可能需要与 flatMapping 相关的代码在您 future 的升级中,您可以使用提供的实现 in this answer.

或者不使用流的解决方案,在这种情况下,看起来类似于使用 Map.merge 的方法。 .它将使用类似的 BiFunction作为:
public Map<String, Set<String>> parseApiEntriesIntoMap(List<Restaurant> restaurants) {
    Map<String, Set<String>> restaurantListByNeighborhood = new HashMap<>();
    for (Restaurant restaurant : restaurants) {
        restaurantListByNeighborhood.merge(restaurant.getNeighborhood(),
                new HashSet<>(restaurant.getRestaurantList()),
                (strings, strings2) -> {
                    strings.addAll(strings2);
                    return strings;
                });
    }
    return restaurantListByNeighborhood;
}

关于java - 有没有办法在一行中将分组列表连接到 Java 8 中的集合中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58906647/

相关文章:

java - Java 的 Stream.flatMap() 的(某种)逆操作是什么?

java - Spring Data JPA + Hibernate + Log4j2 创建entityManagerFactory Bean时出现ClassLoadingException

java - Apache Commons Net FTPClient 和 listFiles()

java - 正则表达式: Find pattern in string

java - 在 map java8 上用 lambda 计数器

Java 8 流 API : get all nodes after specific Node

java - 显示从第 100 列开始的 jtable - java

Java 列表流 anyMatch 返回错误结果

java - Parallel Stream.forEach 抛出的异常

Java 8 Stream of Super Classes, Parent Files, Component Parents, 链表等