Identifizieren Sie Duplikate in einer Liste


117

Ich habe eine Liste vom Typ Integer, zB:

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

Ich möchte eine Methode, um alle Duplikate zurückzugeben, z.

[1, 3]

Was ist der beste Weg, dies zu tun?


2
Wird die Eingabeliste garantiert sortiert (wie in Ihrem Beispiel)?
NPE

7
Sortieren Sie die Liste, gehen Sie sie dann durch und behalten Sie die aktuellen und vorherigen Werte bei. Wenn aktuell == vor, haben Sie ein Duplikat.
McFinnigan

Nein, die Liste ist nicht unbedingt sortiert.
frischeste

Antworten:


183

Das Verfahren addvon Setliefert einen boolean , ob ein Wert bereits vorhanden ist (true , wenn es nicht vorhanden ist , falsch , wenn es bereits vorhanden ist , siehe Set - Dokumentation ).

Durchlaufen Sie einfach alle Werte:

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

1
Warum haben Sie setToReturn? Können Sie nicht einfach set1.add (yourInt) verwenden und set1 zurückgeben?
Phil

3
ja genau. Wenn ein Element jedoch nur einmal in der angegebenen Liste vorhanden ist, wird das Element ebenfalls hinzugefügt. Schauen Sie sich das Beispiel in der Frage an: Meine Lösung gibt [1,3] zurück, wenn die Nummer 2 in set1, aber nicht in setToReturn eingefügt wird. Ihre Lösung würde [1,2,3] zurückgeben (was nicht erforderlich ist)
leifg

1
Ich schlage vor, dass Sie verwenden for (Integer yourInt, um unnötiges Boxen und Unboxing zu vermeiden, zumal Ihre Eingabe bereits Integers enthält .
Hosam Aly

1
@ JonasThelemann Die ganze Idee eines Sets ist, dass es KEINE Duplikate enthalten kann. Deshalb: Egal wie oft Sie 3 hinzufügen, es wird immer nur einmal enden.
Leifg

1
Übrigens, falls HashSetSie auch den Lastfaktor berücksichtigen müssen, z. B. wenn Sie eine Anfangskapazität von angeben 100, weil Sie diese Anzahl von Elementen hinzufügen möchten, wird dieser auf die nächste Potenz von 2 ( 128) gerundet , was dies impliziert Mit dem Standardladefaktor von 0.75fwird der Größenänderungsschwellenwert festgelegt 96, sodass eine Größenänderung vorgenommen wird, bevor Sie 100Elemente hinzugefügt haben . Zum Glück ist die Größenänderung nicht mehr so ​​teuer. Mit aktuellen JREs wird die Größenänderung nicht mehr erneut aufbereitet, sondern die Elemente werden nur basierend auf dem relevanten Bit auf ihre beiden möglichen Ergebnispositionen verteilt.
Holger

50

Ich brauchte auch dafür eine Lösung. Ich habe die Lösung von Leifg verwendet und sie generisch gemacht.

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

1
Ich weiß, dass dies 3 Jahre später ist, aber warum ein LinkedHashedSet, dh warum interessiert Sie die Bestellung?
Ahmad Ragab

4
@AhmadRagab Sie haben Recht, LinkedHashSet ist nicht erforderlich, es sei denn, Sie kümmern sich um die Reihenfolge, in der die Duplikate gefunden wurden (was ich damals getan habe)
John Strickler

Vielen Dank für das Follow-up!
Ahmad Ragab

Wenn Sie so viele Eingabedaten haben, dass Sie diese optimale Lösung verwenden möchten (anstatt die Eingabe zu sortieren), möchten Sie auch die Größe der HashSet () -Objekte vorab zuweisen. Ohne die Vorbelegung erhalten Sie beim Einfügen in HashSet () keine Einfügezeit von O (1). Dies liegt daran, dass die Größe des internen Hash-Arrays wiederholt geändert wird. Die Einfügungen werden dann auf etwa O (log N) gemittelt. Dies bedeutet, dass die Verarbeitung aller N Elemente zu O (N log N) wird, wenn es O (N) gewesen sein könnte.
Johnstosh

38

Ich nahm John Stricklers Lösung und machte sie neu, um die in JDK8 eingeführte Streams-API zu verwenden:

private <T> Set<T> findDuplicates(Collection<T> collection) {
    Set<T> uniques = new HashSet<>();
    return collection.stream()
        .filter(e -> !uniques.add(e))
        .collect(Collectors.toSet());
}

3
das ist schwer zu lesen, nein? Sie haben einen Nebeneffekt im Stream-Betrieb, was es schwierig macht, darüber nachzudenken. Aber ich denke nur an funktionalen Stil. Es ist prägnant und wahrscheinlich der kürzeste Weg;).
Froginvasion

Bei großen Listen können Sie dies parallel auf mehreren Threads ausführen lassen?
Johnstosh

@froginvasion Die eingebaute distinct()Methode ist ebenfalls statusbehaftet. Ich kann mir keine effiziente (O (n)) eindeutige Operation vorstellen, die nicht zustandsbehaftet ist.
Wilmol

18

Hier ist eine Lösung mit Streams mit 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<>();

Sie sehen nur, ob die Häufigkeit dieses Objekts mehr als einmal in Ihrer Liste enthalten ist. Rufen Sie dann .distinct () auf, um nur eindeutige Elemente in Ihrem Ergebnis zu haben

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

1
Dies ist gut in Bezug auf die Lesbarkeit, aber es ist wirklich schlecht für die Leistung. Collections::frequencyist O (n). Es muss die gesamte Sammlung durchlaufen, um die Häufigkeit eines Artikels zu ermitteln. Und wir nennen dies einmal für jeden Artikel in der Sammlung, wodurch diese Schnipsel entstehen O(n^2). Sie werden den Unterschied in jeder Sammlung von mehr als einer Handvoll Elementen bemerken. Ich würde dies niemals im eigentlichen Code verwenden.
Pawan

12

Java 8 Basislösung:

List duplicates =    
list.stream().collect(Collectors.groupingBy(Function.identity()))
    .entrySet()
    .stream()
    .filter(e -> e.getValue().size() > 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

Die Eingabeliste wird in eine Karte umgewandelt (Gruppierung nach denselben Werten). dann werden die Werte der Karte mit dem eindeutigen Wert "gelöscht", dann die Karte mit dem Schlüssel, dann wird die Liste der Liste in eine Liste umgewandelt
مصموديلال المصمودي

schöne und schnelle Lösung, direkt modifizierbar in Filterung auf bestimmte Getter des Artikels
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) );
    }

}

Natürlich können Sie mit ihnen machen, was Sie wollen (dh in ein Set einfügen, um eine eindeutige Liste doppelter Werte zu erhalten), anstatt zu drucken ... Dies hat auch den Vorteil, dass auch die Position doppelter Elemente aufgezeichnet wird.


7

Verwenden von Guava unter 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();
}

7

Das funktioniert auch:

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

Es funktioniert, ist aber ziemlich langsam, da das Aufrufen von remove () in einer Array-Liste eine lineare Suche ist.
Johnstosh

wahr. Beachten Sie, dass der Leistungstreffer geringer ist, wenn Ihre Eingabe viele Duplikate enthält, als wenn nur wenige vorhanden sind.
Adriaan Koster

6

Sie können so etwas verwenden:

List<Integer> newList = new ArrayList<Integer>();
for(int i : yourOldList)
{
    yourOldList.remove(i);
    if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
}

2
Die Verwendung der Liste hier ist sehr ineffektiv
Alexander Farber

2
Und lassen Sie mich inthier nicht anfangen, als Variablentyp zu verwenden. Dies bedeutet, dass für jede einzelne Iteration eine Ganzzahl einmal und ein Int viermal entpackt wird!
Sean Patrick Floyd

1
Ich denke, Sie können leicht eine ConcurrentModificationException erhalten, wenn Sie versuchen, ein Element aus der Liste zu entfernen, während Sie darüber iterieren
Jad B.

1
Dies ist eine 100% ige ConcurrentModificationException, da Sie eine Liste durchlaufen und Elemente im laufenden Betrieb entfernen.
Theo231022

5

Lambas könnte eine Lösung sein

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());

1
Funktioniert, führt jedoch Collections.frequency für jeden Eintrag aus und ist daher langsam.
Arberg

4

Verwenden Sie eine MultiMap, um jeden Wert als Schlüssel / Wertesatz zu speichern. Durchlaufen Sie dann die Schlüssel und suchen Sie diejenigen mit mehreren Werten.


3

Wenn Sie Eclipse-Sammlungen verwenden , funktioniert dies:

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);

Update: Ab Eclipse Collections 9.2 können Sie jetzt verwendenselectDuplicates

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);

Sie können auch primitive Sammlungen verwenden, um dies zu erreichen:

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);

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.


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);

    }

}

Ich mag diese Antwort, musste nur ein anderes hinzufügen, um das Duplikat in einer anderen Liste zu speichern. danke
Tiago Machado

2

Ähnlich wie bei einigen Antworten hier, aber wenn Sie Duplikate basierend auf einer Eigenschaft suchen möchten:

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

1

Erstellen Sie eine Map<Integer,Integer>, iterieren Sie die Liste. Wenn sich ein Element in der Karte befindet, erhöhen Sie seinen Wert. Fügen Sie es andernfalls mit Schlüssel = 1
zur Karte hinzu. Iterieren Sie die Karte und fügen Sie alle Elemente mit Schlüssel> = 2 zu den Listen hinzu

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

    }

Das ist ziemlich gut. Dies ist die beste Lösung, wenn Sie wissen möchten, wie viele Duplikate vorhanden waren. Einige Hinweise: (1) Sie müssen remove () nicht aufrufen, bevor Sie put () ausführen. (2) Sie können die LinkedList über ein Array einrichten, anstatt wiederholte add () -Aufrufe zu verwenden. (3) Wenn val! = Null ist, können Sie sofort x zum Ergebnis hinzufügen. Das Ergebnis kann eine Menge oder eine Liste sein, je nachdem, ob Sie die Anzahl der Duplikate zählen möchten.
Johnstosh

1

Kompakte generierte Version der Top-Antwort, außerdem leerer Scheck hinzugefügt und vorbelegt Set-Größ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;
  }

Benötigen Sie die Nullprüfung? Gibt new HashSet <> (0) die sinnvolle leere Menge zurück?
Johnstosh

@johnstosh dieser Code könnte vereinfacht werden, aber für Null Überprüfung ermöglicht nur die init tempSetmit , listSizewenn notwendig. Dies ist eine kleine Optimierung, aber ich mag es.
Christophe Roussy

1

Ich nahm Sebastians Antwort und fügte einen keyExtractor hinzu -

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

1

Eine thread-sichere Alternative ist folgende:

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

0

Versuchen Sie dies, um doppelte Elemente in der Liste zu finden:

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

Ja, dies findet die Menge, aber es findet nicht die Liste oder Menge der Elemente, die Duplikate sind.
Johnstosh

0

Dies sollte für sortiert und unsortiert funktionieren.

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

Das Aufrufen von enthält () in der Unterliste der ArrayList ist teuer, da es sich um eine lineare Suche handelt. Das ist also okay für 10 Artikel, aber nicht für 10 Millionen.
Johnstosh

0

Dies ist ein Problem, bei dem funktionale Techniken glänzen. Zum Beispiel ist die folgende F # -Lösung sowohl klarer als auch weniger fehleranfällig als die beste zwingende Java-Lösung (und ich arbeite täglich sowohl mit Java als auch mit F #).

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

Natürlich geht es bei dieser Frage um Java. Mein Vorschlag ist daher, eine Bibliothek zu verwenden, die Java Funktionsfunktionen bietet. Zum Beispiel könnte es mit meiner eigenen Bibliothek wie folgt gelöst werden (und es gibt auch einige andere, die einen Blick wert sind):

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

Und dann sehen Sie, wie viel Java bei der funktionalen Programmierung tatsächlich noch nervt. So ein einfaches Problem, so schwer auszudrücken, was Sie in Java wollen.
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;
    }

}

Implementierung ohne Verwendung von Collection-Klassen. Die Schleife muss jedoch nur geringfügig verbessert werden. Die freiwillige Hilfe ist spürbar. Die Ausgabe für oben sieht aus wie -> 2 3 4 6 8 10 11 12
Samrat Roy

Damit dies in kürzerer Zeit ausgeführt werden kann, müssen Sie eine Hash-basierte Datenstruktur verwenden, um Duplikate zu verfolgen. Aus diesem Grund sehen Sie die anderen Lösungen mit HashSet () - es ist in Java integriert.
Johnstosh

@johnstosh Ja, das weiß ich, aber ich habe darüber nachgedacht, es ohne Verwendung von Sammlungen zu schaffen. Deshalb habe ich es in meinem Kommentar erwähnt. Wie Sie sehen, habe ich bereits vor Februar 2017 einen Kommentar abgegeben. [Es gibt Techniken, bei denen Sie überhaupt keine Sammlungen verwenden müssen mit geringerer zeitlicher Komplexität] geeksforgeeks.org/… .Ich habe dieses Programm ausprobiert, ohne die DS & Algo-Praktiken zu kennen. Dafür musst du mich nicht ablehnen. Trotzdem Danke.
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;
    }
}

Was muss ich ändern, damit die Duplikate zurückgegeben werden?
Brenden

Dies sollte als neue Frage gestellt werden.
Willaien

0

Dies wäre eine gute Methode, um doppelte Werte zu finden, ohne Set zu verwenden.

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

Angenommen, Sie möchten eine Methode, die Ihnen eine eindeutige Liste zurückgibt. Wenn Sie also eine Liste übergeben, in der Elemente mehr als einmal vorkommen, erhalten Sie eine Liste mit unterschiedlichen Elementen.

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

0

Und Version, die commons-collections CollectionUtils.getCardinalityMapMethode verwendet:

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()));

`` `


0

Wie wäre es mit diesem 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);


}

0

Nur für den Fall, dass Sie sowohl das Duplikat als auch das Nicht-Duplikat einschließen möchten. Grundsätzlich ist die Antwort der richtigen Antwort ähnlich, aber anstatt von einem Teil zurückzukehren, wenn nicht Teil, geben Sie den anderen Teil zurück

Verwenden Sie diesen Code (ändern Sie den gewünschten Typ)

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

0

Allgemeinere Methode als Variante von 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());
    }

-1

Wenn Sie den Maximalwert kennen (zum Beispiel <10000), können Sie Platz für Geschwindigkeit opfern. Ich kann mich nicht an den genauen Namen dieser Technik erinnern.

Pseudocode:

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

Ich denke du willst "boolean" statt "bit"? Haben Sie Ihren Code ausgeführt, bevor Sie ihn veröffentlicht haben? Dies ist ein guter Anfang. Wenn Sie sich HashSet () ansehen, werden Sie feststellen, dass es sich um die gewünschte Buckets-Implementierung handelt.
Johnstosh

-1

Versuchen Sie einfach Folgendes:

Beispiel, wenn Listenwerte sind: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] doppeltes Element [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);

Das Aufrufen von enthält () in einer ArrayList () ist eine teure Operation, daher sollten Sie stattdessen ein Set verwenden. Sie werden andere Lösungen sehen, die HashSet () oder verknüpfte Versionen davon verwenden.
Johnstosh
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.