Identifier les doublons dans une liste

120

J'ai une liste de type Integer par exemple:

[1, 1, 2, 3, 3, 3]

Je voudrais une méthode pour renvoyer tous les doublons, par exemple:

[1, 3]

Quelle est la meilleure façon de procéder?

le plus frais
la source
2
La liste d'entrée est-elle garantie d'être triée (comme dans votre exemple)?
NPE le
7
triez la liste, puis parcourez-la en conservant les valeurs actuelles et antérieures. si courant == avant vous avez un doublon.
mcfinnigan le
Non, la liste n'est pas nécessairement triée.
plus frais du

Réponses:

183

La méthode addde Setretourne un booléen si une valeur existe déjà (true si elle n'existe pas, false si elle existe déjà, voir la documentation Set ).

Il suffit donc de parcourir 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;
}
leifg
la source
1
Pourquoi avez-vous setToReturn? Ne pouvez-vous pas simplement utiliser set1.add (yourInt) et retourner set1?
Phil le
3
Oui, exactement. Mais lorsqu'un élément n'est présent qu'une seule fois dans la liste spécifiée, l'élément est également ajouté. Regardez l'exemple de la question: Ma solution renverra [1,3] car le nombre 2 est inséré dans set1 mais pas dans setToReturn. Votre solution renverrait [1,2,3] (ce qui n'est pas obligatoire)
leifg
1
Je vous suggère d'utiliser for (Integer yourInt, pour éviter la boxe et le déballage inutiles, d'autant plus que votre entrée contient déjà des Integers.
Hosam Aly le
1
@JonasThelemann l'idée même d'un ensemble est qu'il ne peut PAS contenir de doublons. donc: peu importe la fréquence à laquelle vous ajouterez 3, il ne se terminera toujours qu'une seule fois.
leifg
1
En passant, dans le cas où HashSetvous devez également considérer le facteur de charge, par exemple lorsque vous spécifiez une capacité initiale de 100, parce que vous voulez ajouter ce nombre d'éléments, il est arrondi à la puissance suivante de 2 ( 128), ce qui implique que avec le facteur de charge par défaut de 0.75f, le seuil de redimensionnement sera 96, il y aura donc un redimensionnement avant que vous ayez ajouté des 100éléments. Heureusement, le redimensionnement n'est plus si cher. Avec les JRE à jour, le redimensionnement ne se répète plus, les éléments sont simplement répartis entre leurs deux emplacements de résultat possibles en fonction du bit pertinent.
Holger
50

J'avais également besoin d'une solution à cela. 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;
}
John Strickler
la source
1
Je sais que c'est 3 ans plus tard, mais pourquoi un LinkedHashedSet, c'est-à-dire pourquoi vous souciez-vous de la commande?
Ahmad Ragab
4
@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)
John Strickler
Merci pour le suivi!
Ahmad Ragab
Si vous avez tellement de données d'entrée que vous souhaitez utiliser cette solution optimale (au lieu de trier l'entrée), vous voudrez également pré-allouer la taille des objets HashSet (). Sans la préallocation, vous n'obtenez pas le temps d'insertion O (1) lors de l'insertion dans le HashSet (). Cela est dû au fait que le tableau de hachage interne est redimensionné à plusieurs reprises. Les inserts font alors une moyenne à quelque chose comme le temps O (log N). Cela signifie que le traitement de tous les N éléments devient O (N log N) alors qu'il aurait pu être O (N).
johnstosh
39

J'ai pris la solution de John Strickler et l'ai refaite pour utiliser l'API streams introduite dans JDK8:

private <T> Set<T> findDuplicates(Collection<T> collection) {
    Set<T> uniques = new HashSet<>();
    return collection.stream()
        .filter(e -> !uniques.add(e))
        .collect(Collectors.toSet());
}
Sébastien
la source
3
c'est un peu difficile à lire, non? Vous faites un effet secondaire dans le fonctionnement du flux, ce qui rend difficile de raisonner. Mais c'est juste moi qui pense au style fonctionnel. C'est concis et probablement le moyen le plus court;).
froginvasion
Pour les grandes listes, vous pouvez exécuter cette opération en parallèle sur plusieurs threads?
johnstosh
@froginvasion la distinct()méthode intégrée est également avec état. Impossible de penser à une opération distincte efficace (O (n)) qui n'est pas avec état.
wilmol le
18

Voici une solution utilisant Streams avec Java 8

// lets assume the original list is filled with {1,1,2,3,6,3,8,7}
List<String> original = new ArrayList<>();
List<String> result = new ArrayList<>();

Vous regardez simplement si la fréquence de cet objet est plus d'une fois dans votre liste. Appelez ensuite .distinct () pour n'avoir que des éléments uniques dans votre résultat

result = original.stream()
    .filter(e -> Collections.frequency(original, e) > 1)
    .distinct()
    .collect(Collectors.toList());
// returns {1,3}
// returns only numbers which occur more than once

result = original.stream()
    .filter(e -> Collections.frequency(original, e) == 1)
    .collect(Collectors.toList());
// returns {2,6,8,7}
// returns numbers which occur only once

result = original.stream()
    .distinct()
    .collect(Collectors.toList());
// returns {1,2,3,6,8,7}
// returns the list without duplicates
bonhomme de neige
la source
1
C'est bon en termes de lisibilité, mais c'est VRAIMENT mauvais pour les performances. Collections::frequencyest sur). Il doit parcourir toute la collection pour trouver la fréquence d'un article. Et nous appelons cela une fois pour chaque élément de la collection, ce qui crée ces extraits O(n^2). Vous remarquerez la différence dans toute collection de plus d'une poignée d'éléments. Je n'utiliserais jamais cela dans le code réel.
Pawan le
14

solution de base java 8:

List duplicates =    
list.stream().collect(Collectors.groupingBy(Function.identity()))
    .entrySet()
    .stream()
    .filter(e -> e.getValue().size() > 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());
بلال المصمودي
la source
la liste d'entrée est transformée en carte, (regroupement par les mêmes valeurs). puis les valeurs de la carte avec une valeur unique sont "supprimées" puis la carte à l'aide de la clé, puis la liste de la liste est transformée en une liste
بلال المصمودي
solution belle et rapide, directement modifiable en filtrage sur des getters spécifiques d'objet
arberg
11
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 faire ce que vous voulez avec eux (c'est-à-dire mettre dans un ensemble pour obtenir une liste unique de valeurs en double) au lieu d'imprimer ... Cela a également l'avantage d'enregistrer l'emplacement des éléments en double.

Ashkan Aryen
la source
7

Utilisation de Guava sur Java 8

private Set<Integer> findDuplicates(List<Integer> input) {
    // Linked* preserves insertion order so the returned Sets iteration order is somewhat like the original list
    LinkedHashMultiset<Integer> duplicates = LinkedHashMultiset.create(input);

    // Remove all entries with a count of 1
    duplicates.entrySet().removeIf(entry -> entry.getCount() == 1);

    return duplicates.elementSet();
}
Philipp Paland
la source
7

Cela fonctionne également:

public static Set<Integer> findDuplicates(List<Integer> input) {
    List<Integer> copy = new ArrayList<Integer>(input);
    for (Integer value : new HashSet<Integer>(input)) {
        copy.remove(value);
    }
    return new HashSet<Integer>(copy);
}
Adriaan Koster
la source
Cela fonctionne, mais c'est plutôt lent car appeler remove () sur une liste de tableaux est une recherche linéaire.
johnstosh
vrai. Notez que si votre entrée contient de nombreux doublons, la performance est inférieure à celle de quelques-uns seulement.
Adriaan Koster
6

Vous pouvez utiliser quelque chose comme ceci:

List<Integer> newList = new ArrayList<Integer>();
for(int i : yourOldList)
{
    yourOldList.remove(i);
    if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
}
Ing. Fouad
la source
2
Utiliser la liste ici est très inefficace
Alexander Farber
2
Et ne me lancez pas dans l'utilisation intcomme type de variable ici. Cela signifie que pour chaque itération, un entier est déballé une fois et un int est encadré quatre fois!
Sean Patrick Floyd
1
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
Jad B.
1
c'est 100% ConcurrentModificationException puisque vous parcourez une liste et supprimez des éléments à la volée.
theo231022
5

Lambas pourrait être une solution

Integer[] nums =  new Integer[] {1, 1, 2, 3, 3, 3};
List<Integer> list = Arrays.asList(nums);

List<Integer> dps = list.stream().distinct().filter(entry -> Collections.frequency(list, entry) > 1).collect(Collectors.toList());
APA
la source
1
Fonctionne, mais il exécute Collections.frequency pour chaque entrée et est donc lent.
arberg
4

Utilisez une MultiMap pour stocker chaque valeur sous la forme d'un ensemble clé / valeur. Ensuite, parcourez les clés et trouvez celles avec plusieurs valeurs.

John B
la source
3

Si vous utilisez les collections Eclipse , cela fonctionnera:

MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectByOccurrences(i -> i > 1).toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);

Mise à jour: à partir d'Eclipse Collections 9.2, vous pouvez désormais utiliserselectDuplicates

MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);

Vous pouvez également utiliser des collections primitives pour ce faire:

IntList list = IntLists.mutable.with(1, 1, 2, 3, 3, 3);
IntSet dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(IntSets.mutable.with(1, 3), dupes);

Remarque: je suis un committer pour les collections Eclipse.

Donald Raab
la source
2
public class practicese {
       public static void main(String[] args) {   

           List<Integer> listOf = new ArrayList<Integer>();
           listOf.add(3);
           listOf.add(1);
           listOf.add(2);
           listOf.add(3);
           listOf.add(3);
           listOf.add(2);
           listOf.add(1);

           List<Integer> tempList = new ArrayList<Integer>();
           for(Integer obj:listOf){
                if(!tempList.contains(obj)){
                    tempList.add(obj);

                }
            }
            System.out.println(tempList);

    }

}
Baisakha Chauhan
la source
J'aime cette réponse, il suffit d'ajouter un autre pour enregistrer le doublon dans une autre liste. merci
Tiago Machado
2

Similaire à certaines réponses ici, mais si vous voulez trouver des doublons en fonction d'une propriété:

  public static <T, R> Set<R> findDuplicates(Collection<? extends T> collection, Function<? super T, ? extends R> mapper) {
    Set<R> uniques = new HashSet<>();
    return collection.stream()
        .map(mapper)
        .filter(e -> !uniques.add(e))
        .collect(toSet());
  }
wilmol
la source
1

créer un Map<Integer,Integer>, itérer la liste, si un élément est dans la carte, augmenter sa valeur, sinon l'ajouter à la carte avec clé = 1
itérer la carte, et ajouter aux listes tous les éléments avec clé> = 2

public static void main(String[] args) {
        List<Integer> list = new LinkedList<Integer>();
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(3);
        Map<Integer,Integer> map = new HashMap<Integer, Integer>();
        for (Integer x : list) { 
            Integer val = map.get(x);
            if (val == null) { 
                map.put(x,1);
            } else {
                map.remove(x);
                map.put(x,val+1);
            }
        }
        List<Integer> result = new LinkedList<Integer>();
        for (Entry<Integer, Integer> entry : map.entrySet()) {
            if (entry.getValue() > 1) {
                result.add(entry.getKey());
            }
        }
        for (Integer x : result) { 
            System.out.println(x);
        }

    }
amit
la source
C'est plutôt bien. C'est la meilleure solution si vous avez besoin de connaître le nombre de doublons. Quelques notes: (1) vous n'avez pas besoin d'appeler remove () avant de faire put (). (2) Vous pouvez configurer la LinkedList à partir d'un tableau plutôt que d'utiliser des appels répétés add (). (3) Lorsque val! = Null, vous pouvez immédiatement ajouter x au résultat. Le résultat pourrait être un ensemble ou une liste selon que vous vouliez compter le nombre de doublons.
johnstosh
1

Version compacte et généralisée de la réponse principale, également ajout d'un chèque vide et d'une taille de jeu préallouée:

public static final <T> Set<T> findDuplicates(final List<T> listWhichMayHaveDuplicates) {
    final Set<T> duplicates = new HashSet<>();
    final int listSize = listWhichMayHaveDuplicates.size();
    if (listSize > 0) {
      final Set<T> tempSet = new HashSet<>(listSize);
      for (final T element : listWhichMayHaveDuplicates) {
        if (!tempSet.add(element)) {
          duplicates.add(element);
        }
      }
    }
    return duplicates;
  }
Christophe Roussy
la source
Avez-vous besoin du contrôle zéro? Le nouveau HashSet <> (0) retournera-t-il l'ensemble vide sensible?
johnstosh
@johnstosh ce code pourrait être simplifié, mais la vérification de zéro permet de ne lancer tempSetavec que listSizelorsque cela est nécessaire. C'est une optimisation mineure mais je l'aime bien.
Christophe Roussy
1

J'ai pris la réponse de Sebastian et y ai ajouté un extracteur de clé -

    private <U, T> Set<T> findDuplicates(Collection<T> collection, Function<? super T,? extends U> keyExtractor) {
        Map<U, T> uniques = new HashMap<>(); // maps unique keys to corresponding values
        return collection.stream()
            .filter(e -> uniques.put(keyExtractor.apply(e), e) != null)
            .collect(Collectors.toSet());
    }
Ashish Tyagi
la source
1

Une alternative thread-safe est la suivante:

/**
 * Returns all duplicates that are in the list as a new {@link Set} thread-safe.
 * <p>
 * Usually the Set will contain only the last duplicate, however the decision
 * what elements are equal depends on the implementation of the {@link List}. An
 * exotic implementation of {@link List} might decide two elements are "equal",
 * in this case multiple duplicates might be returned.
 * 
 * @param <X>  The type of element to compare.
 * @param list The list that contains the elements, never <code>null</code>.
 * @return A set of all duplicates in the list. Returns only the last duplicate.
 */
public <X extends Object> Set<X> findDuplicates(List<X> list) {
    Set<X> dups = new LinkedHashSet<>(list.size());
    synchronized (list) {
        for (X x : list) {
            if (list.indexOf(x) != list.lastIndexOf(x)) {
                dups.add(x);
            }
        }
    }
    return dups;
}
Sinistre
la source
0

Essayez ceci pour trouver les éléments en double dans la liste:

ArrayList<String> arrayList1 = new ArrayList<String>(); 

arrayList1.add("A"); 
arrayList1.add("A"); 
arrayList1.add("B"); 
arrayList1.add("B"); 
arrayList1.add("B"); 
arrayList1.add("C"); 

for (int x=0; x< arrayList1.size(); x++) 
{ 
System.out.println("arrayList1 :"+arrayList1.get(x)); 
} 
Set s=new TreeSet(); 
s.addAll(arrayList1); 
Iterator it=s.iterator(); 
while (it.hasNext()) 
{ 
System.out.println("Set :"+(String)it.next()); 
} 
Tushar Ahirrao
la source
Oui, cela trouve l'ensemble, mais il ne trouve pas la liste ou l'ensemble des éléments qui sont des doublons.
johnstosh
0

Cela devrait fonctionner pour les fichiers triés et non triés.

public void testFindDuplicates() {

    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(3);
    list.add(3);

    Set<Integer> result = new HashSet<Integer>();
    int currentIndex = 0;
    for (Integer i : list) {
        if (!result.contains(i) && list.subList(currentIndex + 1, list.size()).contains(i)) {
            result.add(i);
        }
        currentIndex++;
    }
    assertEquals(2, result.size());
    assertTrue(result.contains(1));
    assertTrue(result.contains(3));
}
James DW
la source
L'appel de contains () sur la subList de ArrayList est coûteux car il s'agit d'une recherche linéaire. Cela convient donc pour 10 articles, mais pas pour 10 millions.
johnstosh
0

C'est un problème où les techniques fonctionnelles brillent. Par exemple, la solution F # suivante est à la fois plus claire et moins sujette aux bogues que la meilleure solution Java impérative (et je travaille quotidiennement avec Java et F #).

[1;1;2;3;3;3] 
|> Seq.countBy id 
|> Seq.choose (fun (key,count) -> if count > 1 then Some(key) else None)

Bien sûr, cette question concerne Java. Ma suggestion est donc d'adopter une bibliothèque qui apporte des fonctionnalités fonctionnelles à Java. Par exemple, il pourrait être résolu en utilisant ma propre bibliothèque comme suit (et il y en a plusieurs autres qui valent la peine d'être examinés):

Seq.of(1,1,2,3,3,3)
.groupBy(new Func1<Integer,Integer>() {
    public Integer call(Integer key) {
        return key;
    }
}).filter(new Predicate<Grouping<Integer,Integer>>() {
   public Boolean call(Grouping<Integer, Integer> grouping) {
        return grouping.getGrouping().count() > 1;
   }
}).map(new Func1<Grouping<Integer,Integer>,Integer>() {
    public Integer call(Grouping<Integer, Integer> grouping) {
        return grouping.getKey();
    }
});
Stephen Swensen
la source
Et puis vous voyez à quel point Java aspire encore à la programmation fonctionnelle. Un problème si simple, si difficile d'exprimer ce que vous voulez en Java.
froginvasion
0
public class DuplicatesWithOutCollection {

    public static void main(String[] args) {

        int[] arr = new int[] { 2, 3, 4, 6, 6, 8, 10, 10, 10, 11, 12, 12 };

        boolean flag = false;
        int k = 1;
        while (k == 1) {

            arr = removeDuplicate(arr);
            flag = checkDuplicate(arr, flag);
            if (flag) {
                k = 1;
            } else {
                k = 0;
            }

        }

    }

    private static boolean checkDuplicate(int[] arr, boolean flag) {
        int i = 0;

        while (i < arr.length - 1) {

            if (arr[i] == arr[i + 1]) {

                flag = true;

            } else {
                flag = false;
            }
            i++;

        }

        return flag;
    }

    private static int[] removeDuplicate(int[] arr) {

        int i = 0, j = 0;
        int[] temp = new int[arr.length];
        while (i < arr.length - 1) {

            if (arr[i] == arr[i + 1]) {

                temp[j] = arr[i + 1];
                i = i + 2;

            } else {

                temp[j] = arr[i];
                i = i + 1;

                if (i == arr.length - 1) {
                    temp[j + 1] = arr[i + 1];
                    break;
                }

            }
            j++;

        }
        System.out.println();
        return temp;
    }

}
Samrat Roy
la source
Mise en œuvre sans utiliser les classes de collection.Mais besoin de peu d'amélioration dans la boucle.L'aide au bénévolat est appréciable.La sortie pour ci-dessus ressemble à -> 2 3 4 6 8 10 11 12
Samrat Roy
Pour que cela s'exécute dans un laps de temps plus court, vous devez utiliser une structure de données basée sur le hachage pour garder une trace des doublons. C'est pourquoi vous voyez les autres solutions utilisant HashSet () - il est intégré à Java.
johnstosh
@johnstosh Oui, je sais à ce sujet, mais je pensais le faire sans utiliser les collections, c'est pourquoi j'ai mentionné dans mon commentaire.Comme vous le voyez, j'ai commenté bien avant février 2017, [il existe des techniques où vous n'avez pas du tout à utiliser les collections avec une complexité de temps moindre] geeksforgeeks.org / .... J'ai essayé ce programme sans connaître les pratiques de DS & Algo. Vous n'avez pas à me rejeter pour cela .. de toute façon Merci.
Samrat Roy
0
import java.util.Scanner;

public class OnlyDuplicates {
    public static void main(String[] args) {
        System.out.print(" Enter a set of 10 numbers: ");
        int[] numbers = new int[10];
        Scanner input = new Scanner(System.in);
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = input.nextInt();
        }
        numbers = onlyDuplicates(numbers);
        System.out.print(" The numbers are: ");
        for (int i = 0; i < numbers.length; i++) {
            System.out.print(numbers[i] + "");
        }
    }

    public static int[] onlyDuplicates(int[] list) {
        boolean flag = true;
        int[] array = new int[0];
        array = add2Array(array, list[0]);
        for (int i = 0; i < list.length; i++) {
            for (int j = 0; j < array.length; j++) {
                if (list[i] == array[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                array = add2Array(array, list[i]);
            }
            flag = true;
        }
        return array;
    }
    // Copy numbers1 to numbers2
    // If the length of numbers2 is less then numbers2, return false
    public static boolean copyArray(int[] source, int[] dest) {
        if (source.length > dest.length) {
            return false;
        }

        for (int i = 0; i < source.length; i++) {
            dest[i] = source[i];
        }
        return true;
    }
    // Increase array size by one and add integer to the end of the array
    public static int[] add2Array(int[] source, int data) {
        int[] dest = new int[source.length + 1];
        copyArray(source, dest);
        dest[source.length] = data;
        return dest;
    }
}
Brenden
la source
que dois-je changer pour que cela renvoie les doublons?
Brenden
Cela devrait être posé comme une nouvelle question.
willaien
0

Ce serait une bonne méthode pour trouver des valeurs en double, sans utiliser Set.

public static <T> List<T> findDuplicates(List<T> list){

List<T> nonDistinctElements = new ArrayList<>();

  for(T s : list)
    if(list.indexOf(s) != list.lastIndexOf(s))
      if(!nonDistinctElements.contains(s))
        nonDistinctElements.add(s);

  return nonDistinctElements;
}

Et disons que vous voulez une méthode qui vous renvoie une liste distincte, c'est-à-dire que si vous passez une liste où des éléments se produisent plus d'une fois, vous obtiendrez une liste avec des éléments distincts.

public static <T> void distinctList(List<T> list){

List<T> nonDistinctElements = new ArrayList<>();
for(T s : list)
  if(list.indexOf(s) != list.lastIndexOf(s))
    nonDistinctElements.add(s);

for(T nonDistinctElement : nonDistinctElements)
  if(list.indexOf(nonDistinctElement) != list.lastIndexOf(nonDistinctElement))
    list.remove(nonDistinctElement);
}
Aayush Shrivastava
la source
0

Et la version qui utilise la commons-collections CollectionUtils.getCardinalityMapméthode:

final List<Integer> values = Arrays.asList(1, 1, 2, 3, 3, 3);
final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(values);
System.out.println(cardinalityMap
            .entrySet()
            .stream().filter(e -> e.getValue() > 1)
            .map(e -> e.getKey())
            .collect(Collectors.toList()));

''

Panurg
la source
0

Et ce code -

public static void main(String[] args) {

    //Lets say we have a elements in array
    int[] a = {13,65,13,67,88,65,88,23,65,88,92};

    List<Integer> ls1 = new ArrayList<>();
    List<Integer> ls2 = new ArrayList<>();
    Set<Integer> ls3 = new TreeSet<>();

    //Adding each element of the array in the list      
    for(int i=0;i<a.length;i++) {
     {
    ls1.add(a[i]);
    }
    }

    //Iterating each element in the arrary
    for (Integer eachInt : ls1) {

    //If the list2 contains the iterating element, then add that into set<> (as this would be a duplicate element)
        if(ls2.contains(eachInt)) {
            ls3.add(eachInt);
        }
        else {ls2.add(eachInt);}

    }

    System.out.println("Elements in array or ls1"+ls1); 
    System.out.println("Duplicate Elements in Set ls3"+ls3);


}
Karthik Deepan
la source
0

juste au cas où pour ceux qui veulent également inclure à la fois les doublons et les non doublons. fondamentalement, la réponse est similaire à la bonne réponse mais au lieu de revenir de sinon partie, vous retournez l'autre partie

utilisez ce code (changez pour le type dont vous avez besoin)

public Set<String> findDup(List<String> Duplicates){
    Set<String> returning = new HashSet<>();
    Set<String> nonreturning = new HashSet<>();
    Set<String> setup = new HashSet<>();
    for(String i:Duplicates){
        if(!setup.add( i )){
            returning.add( i );
        }else{
            nonreturning.add( i );
        }
    }
    Toast.makeText( context,"hello set"+returning+nonreturning+" size"+nonreturning.size(),Toast.LENGTH_SHORT ).show();
    return nonreturning;
}

la source
0

Méthode plus générique comme variante de https://stackoverflow.com/a/52296246

    /**
     * Returns a duplicated values found in given collection based on fieldClassifier
     *
     * @param collection given collection of elements
     * @param fieldClassifier field classifier which specifies element to check for duplicates(useful in complex objects).
     * @param <T> Type of element in collection
     * @param <K> Element which will be returned from method in fieldClassifier.
     * @return returns list of values that are duplocated.
     */
    public static <T, K> List<K> lookForDuplicates(List<T> collection, Function<? super T, ? extends K> fieldClassifier) {

        return collection.stream().collect(Collectors.groupingBy(fieldClassifier))
                         .entrySet()
                         .stream()
                         .filter(e -> e.getValue().size() > 1)
                         .map(Map.Entry::getKey)
                         .collect(Collectors.toList());
    }
Igor Maculewicz
la source
-1

Si vous connaissez la valeur maximale (par exemple <10000), vous pouvez sacrifier de l'espace pour la vitesse. Je ne me souviens plus du nom exact de cette technique.

pseudo code:

//does not handle case when mem allocation fails 
//probably can be extended to unknown values /larger values .
maybe by sorting first
public List<int> GetDuplicates(int max)
{   
    //allocate and clear memory to 0/false
    bit[] buckets=new bit[max]
    memcpy(buckets,0,max);
    //find duplicates
    List<int> result=new List<int>();
    foreach(int val in List)
    {
        if (buckets[val])
        {
            result.add(value);
        }
        else
        {
            buckets[val]=1;
        }
    }
    return  result
}
Alex
la source
Je pense que vous voulez "booléen" au lieu de "bit"? Avez-vous exécuté votre code avant de le publier? C'est un bon début. Si vous jetez un œil à HashSet (), vous verrez que c'est l'implémentation des «buckets» que vous désirez.
johnstosh
-1

Essayez simplement ceci:

Exemple si les valeurs de liste sont: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] élément en double [3, 4].

Collections.sort(list);
        List<Integer> dup = new ArrayList<>();
        for (int i = 0; i < list.size() - 1; i++) {
            if (list.get(i) == list.get(i + 1)) {
                if (!dup.contains(list.get(i + 1))) {
                    dup.add(list.get(i + 1));
                }
            }
        }
        System.out.println("duplicate item " + dup);
Apprentissage des utilisateurs
la source
L'appel de contains () sur un ArrayList () est une opération coûteuse, vous devriez donc envisager d'utiliser un Set à la place. Vous verrez d'autres solutions utilisant HashSet () ou des versions liées de celui-ci.
johnstosh