Вступление
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 для форматирования вывода по своему вкусу.