Как получить список значений из Map
Есть
Map<Person, List <Item>> mapOfPersons
Как получить List<Item> одного Person? У Person есть уникальный id.
Я не понимаю как мне достать person из Map по id. Я пробую делать нечто подобное:
mapOfPersons.get(mapOfPersons.entrySet().stream()
.filter(x -> x.getKey().getId().equals(personId)
.collect(Collectors.toList())
)
но возвращается null
Ответы (2 шт):
Можно либо искать ключ типа Person, соответствующий заданному id:
List<Item> itemsForId = mapOfPersons.get(
mapOfPersons.keySet().stream() // Stream<Person>
.filter(p -> Objects.equals(personId, p.getId()))
.findFirst() // Optional<Person>
//.get() // вернуть по personId, может быть NoSuchElementException
.orElse(null) // вернуть null, если personId не найден
);
Здесь в случае использования Optional.get может быть выброшено NoSuchElementException, если не будет найден ключ по заданному personId. Если воспользоваться orElse(null), то в зависимости от разновидности мапы может быть выброшено NullPointerException.
Поэтому может быть безопаснее сразу искать требуемый список через стрим Map.Entry:
List<Item> itemsForId = mapOfPersons.entrySet()
.stream() // Stream<Map.Entry<Person, List<Item>>>
.filter(e -> Objects.equals(personId, e.getKey().getId()))
.map(Map.Entry::getValue) // Stream<List<Item>>
.findFirst() // Optional<List<Item>>
.orElse(null); // вернуть null, если personId не найден
Переопределяем в Person методы hash и equals так, чтобы равенство проверялось по полю id
public class Person {
private final long id;
private String name = null;
public Person(long id, String name) {
this.id = id;
this.name = name;
}
public Person(long id) {
this.id = id;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return String.format("Person(id=%d, name='%s')", id, name);
}
}
public class Item {
private final String name;
public Item(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return String.format("Item(name='%s'", name);
}
}
Далее, когда нужно получить значение по Person с нужным id, создаем новый объект Person с этим id, и просто через get получаем значение:
Map<Person, List<Item>> mapOfPersons = new HashMap<>();
Person person1 = new Person(1, "Person 1");
Person person2 = new Person(2, "Person 2");
mapOfPersons.put(person1, Arrays.asList(new Item("Item 11"), new Item("Item 12")));
mapOfPersons.put(person2, Arrays.asList(new Item("Item 21"), new Item("Item 22")));
System.out.println(mapOfPersons.get(new Person(1)));
System.out.println(mapOfPersons.get(new Person(2)));
Вывод:
[Item(name='Item 11', Item(name='Item 12']
[Item(name='Item 21', Item(name='Item 22']
Если Person более сложный объект (если в нем больше чем пара полей), то имеет смысл в Map в качестве ключей использовать не объект целиком, а просто id.