Получение разницы между двумя наборами

Так что, если у меня есть два набора:

Set<Integer> test1 = new HashSet<Integer>();
test1.add(1);
test1.add(2);
test1.add(3);

Set<Integer> test2 = new HashSet<Integer>();
test2.add(1);
test2.add(2);
test2.add(3);
test2.add(4);
test2.add(5);

Есть ли способ сравнить их и вернуть только набор из 4 и 5?

Ответ 1

Попробуйте это

test2.removeAll(test1);

Установить # removeAll

Удаляет из этого набора все его элементы, которые содержатся в указанной коллекции (дополнительная операция). Если указанная коллекция также является набором, эта операция эффективно модифицирует этот набор, так что его значение представляет собой асимметричную разность наборов двух наборов.

Ответ 2

Если вы используете библиотеку Guava (бывшая коллекция Google), есть решение:

SetView<Number> difference = com.google.common.collect.Sets.difference(test2, test1);

Возвращенный SetView является Set, это живое представление, которое вы можете либо сделать неизменным, либо скопировать в другой набор. test1 и test2 остаются нетронутыми.

Ответ 3

Да:

test2.removeAll(test1)

Хотя это будет мутировать test2, поэтому создайте копию, если вам нужно ее сохранить.

Кроме того, вы, вероятно, имели в виду <Integer> вместо <int>.

Ответ 4

Если вы используете Java 8, вы можете попробовать что-то вроде этого:

public Set<Number> difference(final Set<Number> set1, final Set<Number> set2){
    final Set<Number> larger = set1.size() > set2.size() ? set1 : set2;
    final Set<Number> smaller = larger.equals(set1) ? set2 : set1;
    return larger.stream().filter(n -> !smaller.contains(n)).collect(Collectors.toSet());
}

Ответ 5

Java 8

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

// computes the difference without modifying the sets
public static <T> Set<T> differenceJava8(final Set<T> setOne, final Set<T> setTwo) {
     Set<T> result = new HashSet<T>(setOne);
     result.removeIf(setTwo::contains);
     return result;
}

И если мы все еще находимся в какой-то предыдущей версии, тогда мы можем использовать removeAll как:

public static <T> Set<T> difference(final Set<T> setOne, final Set<T> setTwo) {
     Set<T> result = new HashSet<T>(setOne);
     result.removeAll(setTwo);
     return result;
}

Ответ 6

Вы можете использовать CollectionUtils.disjunction, чтобы получить все различия, или CollectionUtils.subtract, чтобы получить разницу в первой коллекции.

Вот пример того, как это сделать:

    var collection1 = List.of(1, 2, 3, 4, 5);
    var collection2 = List.of(2, 3, 5, 6);
    System.out.println(StringUtils.join(collection1, " , "));
    System.out.println(StringUtils.join(collection2, " , "));
    System.out.println(StringUtils.join(CollectionUtils.subtract(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.retainAll(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.collate(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.disjunction(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.intersection(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.union(collection1, collection2), " , "));