Ответ 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 );
}
}
Заполните некоторые примеры данных. Синтаксис Set.of
, добавленный к Java 9, дает нам простой синтаксис литералов.
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
.
Вот таблица graphi c, которую я сделал и показывающая атрибуты различных Map
реализации в комплекте с Java.
Здесь мы решили использовать ConcurrentHashMap
. Альтернатива, ConcurrentSkipListMap
может быть лучше, если у вас есть большое количество объектов, или если вы хотите сохранить ключи (Year
в нашем случае) в определенном порядке.
Map < Year, List < Person > > yearToListOfPersonsMap = new ConcurrentHashMap <>();
Типы данных
Обратите внимание на правильное использование типов данных. Java предлагает класс Year
для представления всего года. Поэтому мы должны использовать это. Это делает наш код более самодокументируемым.
В классе Person
мы представляем дату рождения, используя LocalDate
. Этот класс предназначен только для даты без времени и без часового пояса.
Мультикарта
Мы извлечем год из даты рождения каждого человека в качестве ключа к нашей карте. Значением является List
из Person
объектов, к которым мы добавляем рассматриваемый объект person.
Если вы хотите исключить любые возможные дубликаты Person
объектов из коллекции, вы можете использовать Set
здесь, а не List
.
Метод Map::computeIfAbsent
, добавленный в Java 8, выполняет работу так называемой multimap , карты, где ключ ведет к набору значения, а не одно значение. В качестве альтернативы, вы можете использовать реализацию нескольких карт сторонних производителей, таких как 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}]}