Bir Listedeki kopyaları tanımlama


120

Tamsayı türünde bir Listem var, örneğin:

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

Tüm kopyaları döndürmek için bir yöntem istiyorum, örneğin:

[1, 3]

Bunu yapmanın en iyi yolu nedir?


2
Giriş listesinin sıralanması garanti ediliyor mu (örneğinizdeki gibi)?
NPE

7
listeyi sıralayın, ardından yürütün, mevcut ve önceki değerleri koruyun. Geçerli == öncesindeyse, bir kopyanız var.
mcfinnigan

Hayır, listenin sıralanması gerekmez.
en taze

Yanıtlar:


183

Bir değer zaten var olup olmadığına bakılmaksızın bir mantıksal değer döndürme yöntemi add( Setyoksa doğru, zaten varsa yanlış, bkz . Belgeleri ayarlama ).

Bu nedenle, tüm değerleri yineleyin:

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
Neden setToReturn'e sahipsiniz? Sadece set1.add (yourInt) kullanıp set1'i döndüremez misiniz?
Phil

3
Evet kesinlikle. Ancak bir elemnt belirtilen listede yalnızca bir kez bulunduğunda, öğe de eklenir. Sorudaki örneğe bakın: Çözümüm, 2 sayısı set1'e eklendiğinde ancak setToReturn'e eklenmediğinden [1,3] döndürür. Çözümünüz [1,2,3] döndürür (bu şart değildir)
leifg

1
for (Integer yourIntGereksiz kutulamayı ve kutudan çıkarmayı önlemek için kullanmanızı öneririm , özellikle de girdiniz zaten Integers içerdiğinden .
Hosam Aly

1
@JonasThelemann bir setin tüm fikri, kopyaları İÇERMEMESİDİR. bu nedenle: ne sıklıkla 3 eklerseniz ekleyin, her zaman yalnızca bir kez sonuçlanacaktır.
leifg

1
Bu arada, HashSetyük faktörünü de göz önünde bulundurmanız gerekirse, örneğin bir başlangıç ​​kapasitesi 100belirlediğinizde, bu sayıda eleman eklemek istediğiniz için, bir sonraki 2 ( 128) kuvvetine yuvarlanır, bu da şu anlama gelir: varsayılan yük faktörü olarak 0.75f, yeniden boyutlandırma eşiği olacaktır 96, bu nedenle, 100öğe eklemeden önce yeniden boyutlandırma yapılacaktır . Neyse ki, yeniden boyutlandırma artık o kadar pahalı değil. Güncel JRE'lerle, yeniden boyutlandırma artık yeniden işlenmez, öğeler yalnızca ilgili bit temelinde iki olası sonuç konumu arasında dağıtılır.
Holger

50

Buna da bir çözüme ihtiyacım vardı. Leifg'in çözümünü kullandım ve genel yaptım.

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
Bunun 3 yıl sonra olduğunu biliyorum, ancak neden LinkedHashedSet, yani siparişi neden önemsiyorsunuz?
Ahmad Ragab

4
@AhmadRagab haklısınız, Yinelenenlerin bulunma sırasını önemsemediğiniz sürece LinkedHashSet gerekli değildir (sanırım o sırada yaptığımı düşünüyorum)
John Strickler

Takip ettiğiniz için teşekkürler!
Ahmad Ragab

Bu optimal çözümü kullanmak istediğiniz kadar çok girdi veriniz varsa (girdiyi sıralamak yerine), o zaman HashSet () nesnelerinin boyutunu da önceden tahsis etmek isteyeceksiniz. Ön ayırma olmadan, HashSet () 'e eklerken O (1) ekleme zamanı alamazsınız. Bunun nedeni, dahili hash dizisinin tekrar tekrar yeniden boyutlandırılmasıdır. Ekler daha sonra O (log N) zamanı gibi bir şeye ortalanır. Bu, tüm N öğenin işlenmesi, O (N) olduğu zaman O (N log N) olacağı anlamına gelir.
johnstosh

39

John Strickler'in çözümünü aldım ve JDK8'de sunulan akışlar API'sini kullanmak için yeniden tasarladım:

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
Bunu okumak biraz zor, değil mi? Akış operasyonunda bir yan etki yapıyorsunuz, bu da mantık yürütmeyi zorlaştırıyor. Ama bu sadece işlevsel tarzı düşünüyorum. Kısa ve muhtemelen en kısa yol olsa da;).
froginvasion

Büyük listeler için, bunu birden çok iş parçacığı üzerinde paralel olarak yürütebilirsiniz.
johnstosh

@froginvasion yerleşik distinct()yöntem de durum bilgilidir . Durum bilgisi olmayan verimli (O (n)) ayrı bir işlem düşünemiyorum.
wilmol

18

İşte Java 8 ile Akışları kullanan bir çözüm

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

Listenizde bu nesnenin sıklığının birden fazla olup olmadığına bakmanız yeterlidir. Ardından sonucunuzda yalnızca benzersiz öğelere sahip olmak için .distinct () çağırın

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
Bu okunabilirlik açısından iyidir, ancak performans için GERÇEKTEN kötüdür. Collections::frequencyO (n). Bir öğenin sıklığını bulmak için tüm koleksiyonun üzerinden geçmesi gerekir. Ve bunu koleksiyondaki her öğe için bir kez çağırıyoruz, bu da bu parçacıkları oluşturur O(n^2). Bir avuç öğeden daha fazlasını içeren herhangi bir koleksiyondaki farkı fark edeceksiniz. Bunu asla gerçek kodda kullanmam.
Pawan

14

java 8 temel çözümü:

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

girdi listesi bir haritaya dönüştürülür (aynı değerlerle gruplama). daha sonra benzersiz değere sahip haritanın değerleri "silinir", ardından anahtar kullanılarak
eşlenir

güzel ve hızlı çözüm, belirli ürün alıcılarında doğrudan filtrelemeye dönüştürülebilir
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) );
    }

}

Açıkçası, yazdırmak yerine onlarla istediğinizi yapabilirsiniz (yani, yinelenen değerlerin benzersiz bir listesini elde etmek için bir Set koyun) ... Bu aynı zamanda yinelenen öğelerin konumunu kaydetme avantajına da sahiptir.


7

Java 8'de Guava'yı kullanma

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

Bu aynı zamanda çalışır:

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

Çalışır, ancak bir dizi listesinde remove () 'i çağırmak doğrusal bir arama olduğu için oldukça yavaştır.
johnstosh

doğru. Girdiniz çok sayıda kopya içeriyorsa, performans vuruşunun, bunlardan yalnızca birkaç tanesine göre daha az olacağını unutmayın.
Adriaan Koster

6

Bunun gibi bir şey kullanabilirsiniz:

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

2
Listeyi burada kullanmak çok etkisiz
Alexander Farber

2
Ve beni intburada değişken türü olarak kullanmaya başlama . Bu, her bir yineleme için, bir Tamsayının bir kez kutudan çıkarıldığı ve bir tamsayının dört kez kutulanacağı anlamına gelir!
Sean Patrick Floyd

1
Listeden bir öğeyi yinelerken kaldırmaya çalışırken kolayca ConcurrentModificationException alabileceğinizi düşünüyorum
Jad

1
Bu% 100 ConcurrentModificationException'dur çünkü bir liste üzerinde yineleme yaparsınız ve öğeleri anında kaldırırsınız.
theo231022

5

Lambas bir çözüm olabilir

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
Çalışır, ancak her giriş için Collections.frequency çalıştırır ve bu nedenle yavaştır.
arberg

4

Her değeri bir anahtar / değer seti olarak saklamak için bir MultiMap kullanın. Ardından, anahtarları yineleyin ve birden çok değere sahip olanları bulun.


3

Eclipse Koleksiyonlarını kullanırsanız , bu çalışacaktır:

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

Güncelleme: Eclipse Collections 9.2'den itibaren artık kullanabilirsinizselectDuplicates

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

Bunu başarmak için ilkel koleksiyonları da kullanabilirsiniz:

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

Not: Eclipse Koleksiyonlarının sorumlusuyum.


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

    }

}

Bu cevabı beğendim, sadece kopyayı başka bir listeye kaydetmek için başka bir tane eklemem gerekiyordu. teşekkürler
Tiago Machado

2

Buradaki bazı yanıtlara benzer, ancak bazı özelliklere göre yinelenenleri bulmak istiyorsanız:

  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

Map<Integer,Integer>bir öğe oluşturun , listeyi yineleyin, eğer haritada bir öğe varsa değerini artırın, aksi takdirde anahtar = 1
ile haritaya ekleyin haritayı yineleyin ve> = 2 anahtarıyla tüm öğeleri listelere ekleyin

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

    }

Bu oldukça iyi. Kaç kopya olduğunu bilmeniz gerekiyorsa en iyi çözüm budur. Bazı notlar: (1) put () yapmadan önce remove () 'i çağırmanıza gerek yoktur. (2) LinkedList'i, tekrarlanan add () çağrıları kullanmak yerine bir diziden kurabilirsiniz. (3) val! = Null olduğunda, sonuca hemen x ekleyebilirsiniz. Sonuç, yinelenenlerin sayısını tutmak isteyip istemediğinize bağlı olarak bir küme veya liste olabilir.
johnstosh

1

En iyi cevabın kompakt, genelleştirilmiş versiyonu, ayrıca boş kontrol ve önceden tahsis edilmiş Set boyutu eklendi:

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

Sıfır kontrole ihtiyacınız var mı? Yeni HashSet <> (0) mantıklı boş küme döndürür mü?
johnstosh

@johnstosh bu kod basitleştirilebilir, ancak sıfırın kontrol edilmesi sadece gerektiğinde tempSetile başlatmaya izin verir listSize. Bu küçük bir optimizasyon ama hoşuma gitti.
Christophe Roussy

1

Sebastian'ın cevabını aldım ve buna bir anahtar çıkarıcı ekledim -

    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

İş parçacığı açısından güvenli bir alternatif şudur:

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

Listede yinelenen öğeleri bulmak için şunu deneyin:

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

Evet, bu seti bulur, ancak yinelenen öğelerin listesini veya kümesini bulamaz.
johnstosh

0

Bu, sıralı ve sıralanmamış için çalışmalıdır.

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

ArrayList'in altListesinde contains () çağrısı yapmak pahalıdır çünkü doğrusal bir aramadır. Yani bu 10 ürün için sorun değil, 10 milyon için değil.
johnstosh

0

Bu, işlevsel tekniklerin parladığı bir sorundur. Örneğin, aşağıdaki F # çözümü, en iyi zorunlu Java çözümünden hem daha net hem de daha az hataya açıktır (ve hem Java hem de F # ile her gün çalışıyorum).

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

Elbette bu soru Java ile ilgili. Bu yüzden benim önerim Java'ya işlevsel özellikler getiren bir kitaplık benimsemek. Örneğin, kendi kütüphanem kullanılarak şu şekilde çözülebilir (ve orada bakmaya değer başka birkaç tane daha var):

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

Ve sonra Java'nın işlevsel programlamada ne kadar kötü olduğunu görüyorsunuz. Java'da ne istediğinizi ifade etmek çok basit bir problem.
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;
    }

}

Koleksiyon sınıflarını kullanmadan uygulama Ancak döngüde çok az iyileştirmeye ihtiyaç var Gönüllülük yardımı kayda değerdir Yukarıdaki çıktı -> 2 3 4 6 8 10 11 12
Samrat Roy

Bunun daha kısa sürede yürütülmesini sağlamak için, kopyaları takip etmek için karma tabanlı bir veri yapısı kullanmanız gerekir. HashSet () kullanan diğer çözümleri görmenizin nedeni budur - Java'da yerleşiktir.
johnstosh

@johnstosh Evet bunu biliyorum ama Koleksiyonları kullanmadan yapmayı düşünüyordum, bu yüzden yorumumda bahsetmiştim. 2017 Şubat ayından önce de yorumda bulunmuştum, [koleksiyonları kullanmak zorunda olmadığınız teknikler var daha az zaman karmaşıklığı ile] geeksforgeeks.org/… . DS & Algo uygulamalarını bilmeden bu programı denedim. Bunun için bana olumsuz oy vermenize gerek yok .. her neyse teşekkürler.
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;
    }
}

Yinelenenleri döndürmek için bunun için neyi değiştirmem gerekiyor?
Brenden

Bu yeni bir soru olarak sorulmalıdır.
willaien

0

Bu, Set kullanmadan Yinelenen değerleri bulmak için iyi bir yöntem olacaktır.

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

Ve diyelim ki, size ayrı bir liste döndüren bir yöntem istiyorsunuz, yani elemanların birden çok kez meydana geldiği bir listeyi geçerseniz, farklı elemanların olduğu bir liste alacaksınız.

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

Ve commons-collections CollectionUtils.getCardinalityMapyöntemi kullanan versiyon :

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

Peki ya bu kod -

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

hem yinelenen hem de yinelenmeyenleri de dahil etmek isteyenler için. temelde cevap doğru cevaba benzer, ancak bölüm değilse geri dönmek yerine else bölümünü geri verirsiniz

bu kodu kullanın (ihtiyacınız olan türü değiştirin)

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

Https://stackoverflow.com/a/52296246 varyantı olarak daha genel yöntem

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

Maksimum değeri biliyorsanız (örneğin <10000), hız için yer feda edebilirsiniz. Bu tekniğin tam adını hatırlayamıyorum.

sözde kod:

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

Sanırım "bit" yerine "boole" mi istiyorsunuz? Kodunuzu göndermeden önce çalıştırdınız mı? Bu iyi bir başlangıç. HashSet () 'e bakarsanız, bunun arzu ettiğiniz' kova 'uygulaması olduğunu göreceksiniz.
johnstosh

-1

Sadece şunu dene:

Örnek Liste değerleri: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] yinelenen öğe [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);

Bir ArrayList () üzerinde contains () işlevini çağırmak pahalı bir işlemdir, bu nedenle bunun yerine bir Set kullanmayı düşünmelisiniz. HashSet () veya bağlantılı sürümlerini kullanan diğer çözümleri göreceksiniz.
johnstosh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.