Вступление
Map
в Java представляют структуры, которые отображают ключи в
значения . Map
не может содержать повторяющиеся ключи, и каждый
может быть сопоставлен не более чем с одним значением. Реализации
Map<K,V>
являются общими и K
(ключ) и V
(значение).
Интерфейс Map
также включает методы для некоторых основных операций
(таких как put()
, get()
, containsKey()
, containsValue()
,
size()
и т. Д.), putAll()
и clear()
) и представления коллекций
(такие как keySet()
, entrySet()
и values()
).
Наиболее известными Map
используемыми для общих целей, являются:
HashMap
, TreeMap
и LinkedHashMap
.
В этой статье мы рассмотрим, как фильтровать карту по ее ключам и значениям :
- Фильтрация карты с помощью расширенных циклов for
- Фильтрация карты по ключам с помощью Stream.filter ()
- Отфильтруйте карту по значениям с помощью Stream.filter ()
Фильтрация карты с помощью расширенных циклов for
Давайте HashMap
несколькими парами ключ-значение:
Map<Integer, String> employeeMap = new HashMap<>();
employeeMap.put(35, "Mark");
employeeMap.put(40, "John");
employeeMap.put(23, "Michael");
employeeMap.put(31, "Jim");
employeeMap.put(25, "Kevin");
Map
имеет ключи типа Integer
и значения типа String
. Они
представляют возраст и имя сотрудников.
Мы отфильтруем эту карту по ключам и значениям и сохраним результаты в
Collection
, например в другой Map
или даже в другом HashMap
.
Давайте перейдем к LinkedHashMap
который сохраняет порядок вставки:
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
for (Map.Entry<Integer, String> employee : employeeMap.entrySet()) {
if(employee.getKey() > 30){
linkedHashMap.put(employee.getKey(), employee.getValue());
}
}
System.out.println("Filtered Map: " + linkedHashMap);
Здесь мы прошли entrySet()
в employeeMap
и добавили каждого
сотрудника в LinkedHashMap
помощью его метода put()
Это будет
работать точно так же для HashMap
, но не сохранит порядок вставки:
Filtered Map: {35=Mark, 40=John, 31=Jim}
Фильтрация по значениям сводится к тому же подходу, хотя мы будем проверять значение каждой записи и использовать это в условии:
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
for (Map.Entry<Integer, String> employee : employeeMap.entrySet()) {
if(employee.getValue().equals("Mark")){
linkedHashMap.put(employee.getKey(), employee.getValue());
}
}
System.out.println("Filtered Map: " + linkedHashMap);
И это выведет:
Filtered Map: {35=Mark}
Это ручной способ фильтрации карты - повторение и выбор желаемых элементов. Давайте теперь посмотрим на более читаемый и удобный способ - через Stream API.
Stream.filter ()
Более современный способ фильтрации карт - это использование Stream API
из Java 8, что делает этот процесс более читаемым. Метод filter()
Stream
, как следует из названия, фильтрует любую Collection
на
основе заданного условия.
Например, учитывая Collection
имен, вы можете отфильтровать их на
основе таких условий, как - содержащие определенные символы или
начинающиеся с определенного символа.
Фильтрация карты по ключам с помощью Stream.filter ()
Давайте воспользуемся Stream API, чтобы отфильтровать ту же карту при
тех же условиях. Мы будем stream()
entrySet()
карты и collect()
ее
обратно в Map
:
Map<Integer, String> filteredMap = employeeMap.entrySet()
.stream().filter(x->x.getKey() > 30)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println("Filtered map: " + filteredMap);
То, что делает этот код, очень похоже на то, что мы делали вручную - для
каждого элемента в наборе карты мы проверяем, превышает ли значение их
ключа 30
и собираем значения в новую Map
с соответствующими ключами
и значениями, предоставленными через getKey()
и getValue()
:
Filtered map: {35=Mark, 40=John, 31=Jim}
Отфильтруйте карту по значениям с помощью Stream.filter ()
Теперь давайте заполним другую карту и вместо пары ключ-значение
<Integer, String>
<String, String>
:
Map<String, String> cityMap = new HashMap<>();
cityMap.put("Tokyo", "Japan");
cityMap.put("Berlin", "Germany");
cityMap.put("Kyoto", "Japan");
cityMap.put("Belgrade", "Serbia");
cityMap.put("Madrid", "Spain");
На этот раз у нас есть пары город-страна , где ключи - это отдельные
города, а значения - страны, в которых они расположены. Значения не
обязательно должны быть уникальными. Kyoto
и Tokyo
, которые
являются уникальными ключами, могут иметь одно и то же значение -
Japan
.
Сортировка этой карты по значениям, опять же, сводится к тому же
подходу, что и раньше - мы просто будем использовать значение с помощью
getValue()
в условии фильтрации:
Map<String, String> filteredMap = citiesMap.entrySet()
.stream().filter(x->"Japan".equals(x.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println("Filtered map: " + filteredMap)
Теперь это приводит к отфильтрованной карте, которая содержит и Tokyo
и Kyoto
:
Filtered map: {Tokyo=Japan, Kyoto=Japan}
Здесь вы можете проявить творческий подход к результатам и результатам.
Например, вместо того, чтобы помещать эти элементы в новую карту и
возвращать ее, мы можем манипулировать полученным значением и в других
структурах. Например, мы могли бы отфильтровать ключи, которые имеют
значения Japan
и Serbia
, и объединить ключи в одну String
:
String filteredMap = citiesMap.entrySet()
.stream().filter(x-> x.getValue().equals("Japan") ||
x.getValue().equals("Serbia"))
.map(Map.Entry::getKey).collect(Collectors.joining(", "));
System.out.println("Filtered map: " + filteredMap);
Здесь мы использовали другой Collector
чем раньше.
Collectors.joining()
возвращает новый Collector
который объединяет
элементы в String
. Помимо CharSequence delimiter
, мы могли бы
также предоставить CharSequence prefix
CharSequence suffix
для
каждого присоединенного элемента.
Это приводит к String
, со всеми из отфильтрованных элементов,
разделенный ,
:
Filtered map: Belgrade, Tokyo, Kyoto
Заключение
В этой статье мы рассмотрели, как фильтровать Map
в Java. Сначала мы
рассмотрели, как использовать расширенные циклы for для проектов до
Java 8, после чего мы погрузились в API Steam и применили метод
filter()
.
Фильтрация карт по значениям или ключам превращается в простую
однострочную задачу с помощью Stream API, и у вас есть широкий выбор
Collector
для форматирования вывода по своему вкусу.