Как отфильтровать карту по ключу или значению в Java

Введение Реализации карты в Java представляют структуры, которые отображают ключи в значения. Карта не может содержать повторяющиеся ключи, и каждый может быть сопоставлен не более чем с одним значением. Карта<K,V> реализации являются общими и допускают отображение любых K (ключ) и V (значение). Интерфейс карты также включает методы для некоторых основных операций (таких как put (), get (), containsKey (), containsValue (), size () и т. Д.), Массовых операций (таких как putAll () и clear ()) и представления коллекций (например, keySet (), entr

Вступление

Map в Java представляют структуры, которые отображают ключи в значения . Map не может содержать повторяющиеся ключи, и каждый может быть сопоставлен не более чем с одним значением. Реализации Map<K,V> являются общими и K (ключ) и V (значение).

Интерфейс Map также включает методы для некоторых основных операций (таких как put() , get() , containsKey() , containsValue() , size() и т. Д.), putAll() и clear() ) и представления коллекций (такие как keySet() , entrySet() и values() ).

Наиболее известными Map используемыми для общих целей, являются: HashMap , TreeMap и LinkedHashMap .

В этой статье мы рассмотрим, как фильтровать карту по ее ключам и значениям :

Фильтрация карты с помощью расширенных циклов 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 для форматирования вывода по своему вкусу.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus