web-dev-qa-db-fra.com

Obtenir la différence entre deux ensembles

Donc si j'ai deux sets:

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

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

Existe-t-il un moyen de les comparer et de ne renvoyer qu'un ensemble de 4 et 5?

114
David Tunnell

Essaye ça 

test2.removeAll(test1);

Set # removeAll

Supprime de cet ensemble tous les éléments contenus dans la collection spécifiée (opération facultative). Si la collection spécifiée est également un ensemble, cette opération modifie effectivement cet ensemble afin que sa valeur corresponde à la différence d'ensemble asymétrique des deux ensembles.

145
Prabhaker

Si vous utilisez la bibliothèque Guava (anciennement Google Collections), il existe une solution:

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

La SetView retournée est une Set, il s'agit d'une représentation en direct que vous pouvez rendre immuable ou copier dans un autre jeu. test1 et test2 sont laissés intacts.

93
Mikhail Golubtsov

Oui:

test2.removeAll(test1)

Bien que cela mute test2, créez-en une copie si vous devez la conserver.

En outre, vous vouliez probablement parler de <Integer> au lieu de <int>.

13
arshajii

Si vous utilisez Java 8, vous pouvez essayer quelque chose comme ceci:

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());
}
3
Josh M

Java 8

Nous pouvons utiliser removeIf qui prend un prédicat pour écrire une méthode d’utilité comme:

// 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;
}

Et si nous en sommes encore à une version antérieure, nous pouvons utiliser removeAll comme:

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;
}
2
i_am_zero

Vous pouvez utiliser CollectionUtils.disjunction pour obtenir toutes les différences ou CollectionUtils.subtract pour obtenir la différence dans la première collection.

Voici un exemple de comment faire cela:

    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), " , "));
1
pwipo