在 HashMap 中添加到 List 的快捷方式

新手上路,请多包涵

我经常需要获取对象列表并根据对象中包含的值将它们分组到 Map 中。例如。按国家/地区列出用户和组。

我的代码通常如下所示:

 Map<String, List<User>> usersByCountry = new HashMap<String, List<User>>();
for(User user : listOfUsers) {
    if(usersByCountry.containsKey(user.getCountry())) {
        //Add to existing list
        usersByCountry.get(user.getCountry()).add(user);

    } else {
        //Create new list
        List<User> users = new ArrayList<User>(1);
        users.add(user);
        usersByCountry.put(user.getCountry(), users);
    }
}

但是我不禁认为这很尴尬,一些大师有更好的方法。到目前为止,我能看到的最接近的是 Google Collections 中的 MultiMap

有没有标准的方法?

谢谢!

原文由 Damo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 764
2 个回答

从 Java 8 开始,您可以使用 Map#computeIfAbsent()

 Map<String, List<User>> usersByCountry = new HashMap<>();

for (User user : listOfUsers) {
    usersByCountry.computeIfAbsent(user.getCountry(), k -> new ArrayList<>()).add(user);
}

或者,直接使用 Stream API 的 Collectors#groupingBy()ListMap

 Map<String, List<User>> usersByCountry = listOfUsers.stream().collect(Collectors.groupingBy(User::getCountry));

在 Java 7 或更低版本中,你能得到的最好的结果如下:

 Map<String, List<User>> usersByCountry = new HashMap<>();

for (User user : listOfUsers) {
    List<User> users = usersByCountry.get(user.getCountry());
    if (users == null) {
        users = new ArrayList<>();
        usersByCountry.put(user.getCountry(), users);
    }
    users.add(user);
}

Commons Collections 有一个 LazyMap ,但它没有参数化。 Guava 没有 LazyMapLazyList ,但您可以使用 Multimap ,如 下面的 polygenelubricants 的回答所示

原文由 BalusC 发布,翻译遵循 CC BY-SA 4.0 许可协议

番石榴的 Multimap 确实是最合适的数据结构,事实上,有 Multimaps.index(Iterable<V>, Function<? super V,K>) 实用方法可以完全满足您的需求:采用 Iterable<V> (其中 a List<V> 是),并应用 Function<? super V, K> 获取 Multimap<K,V> 的密钥。

这是文档中的示例:

例如,

   List<String> badGuys
      = Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde");
  Function<String, Integer> stringLengthFunction = ...;
  Multimap<Integer, String> index
      = Multimaps.index(badGuys, stringLengthFunction);
  System.out.println(index);

印刷

 {4=[Inky], 5=[Pinky, Pinky, Clyde], 6=[Blinky]}

在你的情况下,你会写一个 Function<User,String> userCountryFunction = ...

原文由 polygenelubricants 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题