9

我正在填充一个哈希图,以使我的对象按其属性之一分组。我发现在将我的对象添加到列表之前检查列表(值)是否存在是“丑陋的”。

一个例子会更明确:

// Need a map to group Person by age.
// Person = {age: int}
Map<Integer, List<Person>> myHashMap = new HashMap();

for (Person person : persons) {
   int age = person.getAge();
   List<Person> personsOfSameAge = myHashMap.get(age);
   if (personsOfSameAge != null) {
       personsOfSameAge.add(person);
   } else {
       personsOfSameAge = new ArrayList();
       personsOfSameAge.add(person);
       myHashMap.put(age, personsOfSameAge);
   }
}

有没有更好的编码方法?

myHashMap.addToValueListOrCreateValueList(myObject);
4

4 回答 4

14

在 Java 8 中,您的整个代码可以这样编写(正如其他好的答案所建议的那样):

Map<Integer, List<Person>> myHashMap = new HashMap();

for (Person person : persons) {
   myHashMap.computeIfAbsent(age,age->new ArrayList<Person>()).add(person);
}

但是您可以通过使用收集到Mapwith的流来更短Collectors.groupingBy()

Map<Integer, List<Person>> myMap = persons.stream().collect(Collectors.groupingBy(Person:getAge));

附带说明一下,您的实际 Java 7 代码也可以改进。当然,没有 Java 8 那么多,但如果你不能使用 Java 8,这可能会很有趣。
在您的实际代码中,这是重复的:

personsOfSameAge.add(person);

并且您使用两个条件语句(ifelse),而只有if在您首先处理特殊情况时才足够:Map.
这是修改后的版本:

Map<Integer, List<Person>> myHashMap = new HashMap<>();

for (Person person : persons) {
   int age = person.getAge();
   List<Person> personsOfSameAge = myHashMap.get(age);
   if (personsOfSameAge == null) {
       personsOfSameAge = new ArrayList();
       myHashMap.put(age, personsOfSameAge);
   }          
   personsOfSameAge.add(person);                
}
于 2018-02-01T13:42:13.880 回答
7

是的,Java 8 中有:

List<Person> personsOfSameAge = myHashMap.computeIfAbsent(age,age->new ArrayList<Person>());
personsOfSameAge.add(person);

要不就

myHashMap.computeIfAbsent(age,age->new ArrayList<Person>()).add(person);
于 2018-02-01T13:29:22.930 回答
1

像这样的东西?

  List<Person> newList = Optional.ofNullable( myHashMap.get(age)).orElse(new ArrayList<>());
  newList.add(person);
  myHashMap.put(age, newList);
于 2018-02-01T13:30:55.807 回答
1

尽管问题涉及在 Java 8 中执行此操作,但我将其发布为另一种方式。

您可以使用Google Guava 的 MultiMap

Multimap<String, Person> myHashMap = ArrayListMultimap.create();
for (Person person : persons) {
   myHashMap.put(person.getAge(), person);
}

但是,您必须注意一个区别:Java 的 map 返回null一个不存在的键,而 Google Guava 的 MultiMap 返回一个empty List.

来自MultiMap的get(key)的javadoc

返回与此多图中的键关联的值的视图集合(如果有)。请注意,当 containsKey(key) 为 false 时,这将返回一个空集合,而不是 null。对返回集合的更改将更新底层多图,反之亦然

于 2018-02-01T17:25:49.120 回答