J'ai une liste de type Integer, par exemple :
[1, 1, 2, 3, 3, 3]
Je voudrais une méthode pour retourner tous les doublons, par exemple :
[1, 3]
Quelle est la meilleure façon de procéder ?
J'ai une liste de type Integer, par exemple :
[1, 1, 2, 3, 3, 3]
Je voudrais une méthode pour retourner tous les doublons, par exemple :
[1, 3]
Quelle est la meilleure façon de procéder ?
La méthode add
de Set
renvoie un booléen indiquant si une valeur existe déjà (true si elle n'existe pas, false si elle existe déjà, cf. Définir la documentation ).
Donc, il suffit d'itérer à travers toutes les valeurs :
public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{
final Set<Integer> setToReturn = new HashSet<>();
final Set<Integer> set1 = new HashSet<>();
for (Integer yourInt : listContainingDuplicates)
{
if (!set1.add(yourInt))
{
setToReturn.add(yourInt);
}
}
return setToReturn;
}
Pourquoi avez-vous setToReturn ? Ne pouvez-vous pas simplement utiliser set1.add(votreInt) et retourner set1 ?
Non, vous ne pouvez pas, car l'ensemble 1 contient toutes les valeurs (y compris celles qui ne sont pas en double).
La documentation indique que add() "ajoute l'élément spécifié à cet ensemble s'il n'est pas déjà présent", ce qui donne l'impression que lorsque add renvoie false, rien n'a été ajouté.
J'avais également besoin d'une solution à ce problème. J'ai utilisé la solution de Leifg et l'ai rendue générique.
private <T> Set<T> findDuplicates(Collection<T> collection) {
Set<T> duplicates = new LinkedHashSet<>();
Set<T> uniques = new HashSet<>();
for(T t : collection) {
if(!uniques.add(t)) {
duplicates.add(t);
}
}
return duplicates;
}
Je sais que c'est 3 ans plus tard, mais pourquoi un LinkedHashedSet, c'est-à-dire pourquoi se soucier de l'ordre ?
@AhmadRagab vous avez raison, LinkedHashSet n'est pas nécessaire, sauf si vous vous souciez de l'ordre dans lequel les doublons ont été trouvés (ce que je pense avoir fait à l'époque).
int[] nums = new int[] {1, 1, 2, 3, 3, 3};
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {
if (nums[i] == nums[i+1]) {
System.out.println("duplicate item "+nums[i+1]+" at Location"+(i+1) );
}
}
Évidemment, vous pouvez en faire ce que vous voulez (par exemple, les placer dans un Set pour obtenir une liste unique de valeurs en double) au lieu de les imprimer... Cela présente également l'avantage d'enregistrer l'emplacement des éléments en double.
Et ne me lancez pas sur l'utilisation int
comme type de variable ici. Cela signifie que pour chaque itération, un Integer est déboîté une fois et un int est boxé quatre fois !
Je pense que vous pouvez facilement obtenir une ConcurrentModificationException lorsque vous essayez de supprimer un élément de la liste tout en l'itérant.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
La liste d'entrée est-elle garantie d'être triée (comme dans votre exemple) ?
8 votes
Triez la liste, puis parcourez-la en conservant les valeurs actuelles et antérieures. si actuelle == antérieure, vous avez un doublon.
0 votes
Non, la liste n'est pas nécessairement triée.