Рубрики
Без рубрики

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

В этом уроке мы рассмотрим, как фильтровать карту по ключу или значению в Java 8, используя расширенный цикл for и метод API потока “filter ()” с примерами.

Автор оригинала: Branko Ilic.

Вступление

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

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

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

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

  • Отфильтруйте карту с помощью расширенных циклов поиска
  • Отфильтруйте карту по ключам с помощью Stream.filter()
  • Отфильтруйте карту по значениям с помощью функции Stream.filter()

Отфильтруйте карту с помощью расширенных циклов поиска

Давайте заполним Хэш-карту некоторыми парами ключ-значение:

Map employeeMap = new HashMap<>();

employeeMap.put(35, "Mark");
employeeMap.put(40, "John");
employeeMap.put(23, "Michael");
employeeMap.put(31, "Jim");
employeeMap.put(25, "Kevin");

Карта содержит ключи типа Целое число и значения типа Строка . Они представляют возраст и имя сотрудников.

Мы отфильтруем эту карту по ключам и значениям и сохраним результаты в Коллекции , например, в другой Карте реализации или даже в другой Хэш-карте .

Давайте перейдем к LinkedHashMap , который сохраняет порядок вставки:

Map linkedHashMap = new LinkedHashMap<>();

for (Map.Entry employee : employeeMap.entrySet()) {
    if(employee.getKey() > 30){
        linkedHashMap.put(employee.getKey(), employee.getValue());
    }
}
    
System.out.println("Filtered Map: " + linkedHashMap);

Здесь мы прошли через entrySet() карты сотрудников и добавили каждого сотрудника в LinkedHashMap с помощью метода put () . Это будет работать точно так же для реализации HashMap , но не сохранит порядок вставки:

Filtered Map: {35=Mark, 40=John, 31=Jim}

Фильтрация по значениям сводится во многом к тому же подходу, хотя мы будем проверять значение каждой записи и использовать его в условии:

Map linkedHashMap = new LinkedHashMap<>();

for (Map.Entry employee : employeeMap.entrySet()) {
    if(employee.getValue().equals("Mark")){
        linkedHashMap.put(employee.getKey(), employee.getValue());
    }
}

System.out.println("Filtered Map: " + linkedHashMap);

И это привело бы к:

Filtered Map: {35=Mark}

Это ручной способ фильтрации карты – повторение и выбор нужных элементов. Давайте теперь рассмотрим более понятный и удобный способ – через API Stream.

Поток.фильтр()

Более современным способом фильтрации карт было бы использование API потока из Java 8, что делает этот процесс намного более читабельным. Метод filter() класса Stream , как следует из названия, фильтрует любую Коллекцию на основе заданного условия.

Например, учитывая Коллекцию имен, вы можете отфильтровать их на основе таких условий, как – содержащие определенные символы или начинающиеся с определенного символа.

Отфильтруйте карту по ключам с помощью Stream.filter()

Давайте воспользуемся потоковым API, чтобы отфильтровать эту же карту при тех же условиях. Мы передадим () /набор данных() карты и соберем() его обратно в Карту :

Map 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 и соберите значения в новую карту , с их соответствующими ключами и значениями, предоставленными через getKey() и GetValue() ссылки на методы:

Filtered map: {35=Mark, 40=John, 31=Jim}

Отфильтруйте карту по значениям с помощью функции Stream.filter()

Теперь давайте заполним другую карту, и вместо пары <Целое число, строка> ключ-значение мы будем использовать пару <Строка, строка> :

Map cityMap = new HashMap<>();

cityMap.put("Tokyo", "Japan");
cityMap.put("Berlin", "Germany");
cityMap.put("Kyoto", "Japan");
cityMap.put("Belgrade", "Serbia");
cityMap.put("Madrid", "Spain");

На этот раз у нас есть пары город-страна , где ключами являются отдельные города, а значениями-страны, в которых они расположены. Значения не обязательно должны быть уникальными. Киото и Токио , которые являются уникальными ключами могут иметь одно и то же значениеЯпония .

Сортировка этой карты по значениям, опять же, сводится к тому же подходу, что и раньше – мы просто будем использовать значение с помощью метода GetValue() в условии фильтрации:

Map 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)

Теперь это приводит к отфильтрованной карте, которая содержит оба Токио и Киото :

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Filtered map: {Tokyo=Japan, Kyoto=Japan}

Вы можете проявить творческий подход к результатам и результатам здесь. Например, вместо того, чтобы помещать эти элементы в новую карту и возвращать ее, мы можем манипулировать полученным значением и в других структурах. Например, мы могли бы отфильтровать ключи, которые имеют Япония и Сербия в качестве значений, и объединить ключи в одну Строку :

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);

Здесь мы использовали другой Коллектор , чем раньше. Collectors.joining() возвращает новый Коллектор , который объединяет элементы в Строку . Кроме разделителя последовательности символов , который мы передали, мы могли бы также указать префикс последовательности символов и суффикс последовательности символов для каждого присоединенного элемента.

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

Filtered map: Belgrade, Tokyo, Kyoto

Вывод

В этой статье мы рассмотрели, как фильтровать карту в Java. Сначала мы рассмотрели, как использовать расширенные циклы для проектов до Java 8, после чего мы погрузились в API Steam и использовали метод filter () .

Фильтрация карт по значениям или ключам преобразуется в простую однострочную задачу с помощью API потока, и у вас есть широкий выбор Коллекторов , чтобы отформатировать вывод по своему вкусу.