Answer by ernest_k 正确且清晰。这里有更多代码,一个完整的例子。
首先,为Person定义一个类。
package work.basil.example;
import java.time.LocalDate;
import java.util.Objects;
public class Person
{
// ----------| Member fields |----------------------
public String name;
public LocalDate birthdate;
// ----------| Constructor |----------------------
public Person ( String name , LocalDate birthdate )
{
this.name = Objects.requireNonNull( name );
this.birthdate = Objects.requireNonNull( birthdate );
}
// ----------| Object |----------------------
@Override
public String toString ( )
{
return "Person{ " +
"name='" + name + '\'' +
" | birthdate=" + birthdate +
" }";
}
@Override
public boolean equals ( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
Person person = ( Person ) o;
return name.equals( person.name ) &&
birthdate.equals( person.birthdate );
}
@Override
public int hashCode ( )
{
return Objects.hash( name , birthdate );
}
}
填充一些示例数据。 Java 9 添加的Set.of 语法为我们提供了简单的文字语法。
Set < Person > persons = Set.of(
new Person( "Alice" , LocalDate.of( 1990 , Month.JANUARY , 23 ) ) ,
new Person( "Bob" , LocalDate.of( 2000 , Month.FEBRUARY , 24 ) ) ,
new Person( "Carol" , LocalDate.of( 1990 , Month.MARCH , 25 ) )
);
并发
定义我们要填充的Map。您提到并发是一个问题,即跨线程共享此映射。因此,我们应该使用与 Java 捆绑的两个实现 ConcurrentMap 接口的类之一。
这是我制作的图表,显示了与 Java 捆绑在一起的各种 Map 实现的属性。
这里我们选择使用ConcurrentHashMap。如果您有大量对象,或者如果您想按特定顺序维护密钥(在我们的例子中为 Year),则替代方案 ConcurrentSkipListMap 可能会更好。
Map < Year, List < Person > > yearToListOfPersonsMap = new ConcurrentHashMap <>();
数据类型
注意数据类型的适当使用。 Java 提供了一个Year 类来表示一整年。所以我们应该使用它。这样做可以让我们的代码更加自文档化。
在Person 类中,我们使用LocalDate 表示出生日期。该类适用于没有时间和时区的仅日期值。
多地图
我们将从每个人的生日中提取年份作为我们地图的关键。该值是Person 对象的List,我们将相关人员对象添加到其中。
如果您想从收集中消除任何可能的重复 Person 对象,您可以在此处使用 Set 而不是 List。
Java 8 中添加的Map::computeIfAbsent 方法完成了被称为multimap 的工作,这是一个映射,其中一个键指向一组值而不是单个值。或者,您可以使用来自第三方的 multipmap 实现,例如 Google Guava 库。
for ( Person person : persons )
{
yearToListOfPersonsMap.computeIfAbsent(
Year.from( person.birthdate ) ,
( ( Year key ) -> new ArrayList <>() )
).add( person )
;
}
转储到控制台。
System.out.println( "yearToListOfPersonsMap = " + yearToListOfPersonsMap );
yearToListOfPersonsMap = {2000=[Person{ name='Bob' |生日=2000-02-24 }], 1990=[人{姓名='爱丽丝'|生日=1990-01-23 },人{姓名='卡罗尔'|生日=1990-03-25 }]}