Удаление одной коллекции из другой

Рейтинг: 1Ответов: 2Опубликовано: 11.02.2023

Суть. удалить из коллекции элементы значение value которых > 300, создал отдельную коллекцию, где храню элементы > 300, не могу найти способ как удалить одну коллекцию из другой.

public static HashMap<String, Integer> magSort(HashMap<String, Integer> shopCart) {
    HashMap <String, Integer> delete = new HashMap<>();
    for (Map.Entry<String, Integer> item:shopCart.entrySet()){
        if (item.getValue() > 300) {
            delete.put(item.getKey(), item.getValue());
        }
    }

        return shopCart;
    }

P.s очень пытался найти решение сам к сожалению не смог, думал можно как то с помощью RemoveAll или stream, но не получалось реализовать.

Ответы

▲ 1Принят

Создавать дополнительную коллекцию для того, чтобы удалить одну из другой, вовсе не обязательно. Можно воспользоваться, например, дефолтным методом removeIf(), который определён в интерфейсе Collection начиная с версии Java 8.

Однако применяется он не к самой "мапе", а к множеству её записей, которое можно получить методом entrySet(). Вот пример, как можно произвести удаление записей, значение в которых больше 300, с использованием метода removeIf():

HashMap<String, Integer> source = new HashMap<>(Map.of("1", 300, "2", 100, "3", 450,
                "4", 50, "5", 500, "6", 142, "7", 301));
source.entrySet().removeIf(entry -> entry.getValue() > 300);
System.out.println(source);

В результате получаем:

{1=300, 2=100, 4=50, 6=142}
▲ 1

Хотел бы дополнить ответ @Byb в том плане, что операции по удалению можно применить и к набору ключей, который возвращается методом Map::keySet, и к коллекции значений, возвращаемой методом Map::values.

Следует также заметить, что метод magSort, возвращающий мапу, подразумевает, что входная мапа не должна меняться, то есть следовало бы создать новую мапу, что легко выполняется при помощи Stream API (условие в фильтре должно тогда быть противоположным -- в новой мапе остаются элементы, чьи значения меньше или равны 300):

public static Map<String, Integer> magSort(Map<String, Integer> shopCart) {
    return shopCart.entrySet().stream()
        .filter(e -> e.getValue() <= 300)
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

Пример использования removeAll для множества значений при помощи метода, модифицирующего входной параметр и потому имеющего тип void:

public static void remAllOver300(Map<String, Integer> shopCart) {
    Set<Integer> over300 = shopCart.values().stream()
        .filter(n -> n > 300)
        .collect(Collectors.toSet());
    
    shopCart.values().removeAll(over300);
}

Тесты:

var data = new HashMap<>(Map.of(
    "1", 300, "2", 100, "3", 450,
    "4", 50, "5", 500, "6", 142, "7", 301
));

var filtered = magSort(data);
System.out.println("magSort: " + filtered);

var data2 = new HashMap<>(data);
var data3 = new HashMap<>(data);

System.out.println("input:   " + data);
Predicate<Integer> over300 = v -> v > 300;
data.values().removeIf(over300);
System.out.println("values:  " + data);

// 
Predicate<String> valOver300 = k -> data2.get(k) > 300;
data2.keySet().removeIf(valOver300);
System.out.println("keys:    " + data2);

remAllOver300(data3);
System.out.println("remAll:  " + data3);

Результат:

magSort: {1=300, 2=100, 4=50, 6=142}
input:   {1=300, 2=100, 3=450, 4=50, 5=450, 6=142, 7=301}
values:  {1=300, 2=100, 4=50, 6=142}
keys:    {1=300, 2=100, 4=50, 6=142}
remAll:  {1=300, 2=100, 4=50, 6=142}