Identifikasi duplikat dalam Daftar

120

Saya memiliki Daftar tipe Integer misalnya:

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

Saya ingin metode untuk mengembalikan semua duplikat misalnya:

[1, 3]

Apa cara terbaik untuk melakukannya?

paling segar
sumber
2
Apakah daftar masukan dijamin akan disortir (seperti dalam contoh Anda)?
NPE
7
urutkan daftar, lalu jalankan, pertahankan nilai saat ini dan sebelumnya. jika saat ini == sebelumnya Anda memiliki duplikat.
mcfinnigan
Tidak, daftar tersebut belum tentu diurutkan.
terbaru

Jawaban:

183

Metode adddari Sethasil sebuah boolean apakah suatu nilai sudah ada (benar jika itu tidak ada, false jika sudah ada, lihat Set dokumentasi ).

Jadi, lakukan iterasi melalui semua nilai:

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
sumber
1
Mengapa Anda memiliki setToReturn? Bisakah Anda tidak hanya menggunakan set1.add (yourInt) dan mengembalikan set1?
Phil
3
ya persis. Tetapi jika elemnt hanya ada sekali dalam daftar yang ditentukan, elemen tersebut juga ditambahkan. Lihatlah contoh di pertanyaan: Solusi saya akan mengembalikan [1,3] karena angka 2 dimasukkan dalam set1 tetapi tidak di setToReturn. Solusi Anda akan
menghasilkan
1
Saya menyarankan Anda menggunakan for (Integer yourInt, untuk menghindari tinju dan unboxing yang tidak perlu, terutama karena masukan Anda sudah berisi Integers.
Hosam Aly
1
@JonasThelemann ide keseluruhan dari sebuah set adalah bahwa ia TIDAK bisa berisi duplikat. oleh karena itu: tidak peduli seberapa sering Anda akan menambahkan 3, itu akan selalu berakhir hanya sekali.
leifg
1
Ngomong-ngomong, jika HashSetAnda juga harus mempertimbangkan faktor beban, misalnya ketika Anda menentukan kapasitas awal 100, karena Anda ingin menambahkan jumlah elemen itu, itu akan dibulatkan ke pangkat berikutnya 2 ( 128), yang berarti bahwa dengan faktor beban default 0.75f, ambang pengubahan ukuran akan menjadi 96, jadi akan ada pengubahan ukuran sebelum Anda menambahkan 100elemen. Untungnya, mengubah ukuran tidak semahal itu lagi. Dengan JRE terbaru, mengubah ukuran tidak mengulang lagi, elemen hanya didistribusikan di antara dua kemungkinan lokasi hasil berdasarkan bit yang relevan.
Holger
50

Saya membutuhkan solusi untuk ini juga. Saya menggunakan solusi leifg dan membuatnya menjadi generik.

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
sumber
1
Saya tahu ini 3 tahun kemudian, tetapi mengapa LinkedHashedSet, yaitu mengapa Anda peduli dengan pesanan?
Ahmad Ragab
4
@AhmadRagab Anda benar, LinkedHashSet tidak diperlukan kecuali Anda peduli dengan urutan duplikat ditemukan (yang menurut saya saya lakukan saat itu)
John Strickler
Terima kasih telah menindaklanjuti!
Ahmad Ragab
Jika Anda memiliki begitu banyak data input sehingga Anda ingin menggunakan solusi optimal ini (daripada mengurutkan input) maka Anda juga ingin mengalokasikan ukuran objek HashSet () sebelumnya. Tanpa pra-alokasi, Anda tidak mendapatkan O (1) waktu penyisipan saat memasukkan ke dalam HashSet (). Ini karena larik hash internal berulang kali diubah ukurannya. Sisipan kemudian rata-rata menjadi sesuatu seperti waktu O (log N). Ini berarti memproses semua N item menjadi O (N log N) padahal bisa jadi O (N).
johnstosh
39

Saya mengambil solusi John Strickler dan membuatnya kembali untuk menggunakan API aliran yang diperkenalkan di 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());
}
Sebastian
sumber
3
ini agak sulit untuk dibaca, bukan? Anda melakukan efek samping dalam operasi streaming, membuatnya agak sulit untuk dipikirkan. Tapi itu hanya saya yang memikirkan gaya fungsional. Ini singkat dan mungkin cara terpendek;).
froginvasion
Untuk daftar besar, Anda dapat membuat ini dieksekusi secara paralel di beberapa utas?
johnstosh
@froginvasion metode bawaan distinct()juga stateful. Tidak dapat memikirkan operasi berbeda yang efisien (O (n)) yang tidak stateful.
wilmol
18

Berikut adalah solusi menggunakan Streams dengan 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<>();

Anda hanya perlu melihat apakah frekuensi objek ini lebih dari sekali dalam daftar Anda. Kemudian panggil .distinct () untuk hanya memiliki elemen unik dalam hasil Anda

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
manusia salju
sumber
1
Ini bagus dalam hal keterbacaan, tapi BENAR - BENAR buruk untuk performa. Collections::frequencyadalah O (n). Itu perlu melalui seluruh koleksi untuk menemukan frekuensi suatu barang. Dan kami memanggil ini sekali untuk setiap item dalam koleksi, yang membuat cuplikan ini O(n^2). Anda akan melihat perbedaan dalam koleksi lebih dari segelintir elemen. Saya tidak pernah menggunakan ini dalam kode sebenarnya.
Pawan
14

solusi dasar 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());
بلال المصمودي
sumber
daftar masukan diubah menjadi peta, (pengelompokan berdasarkan nilai yang sama). kemudian nilai peta dengan nilai unik "dihapus" kemudian dipetakan menggunakan kunci, kemudian daftar daftar diubah menjadi Daftar
بلال المصمودي
solusi cantik dan cepat, langsung dapat dimodifikasi menjadi pemfilteran pada pengambil item tertentu
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) );
    }

}

Jelas Anda dapat melakukan apa pun yang Anda inginkan dengan mereka (misalnya, meletakkan Set untuk mendapatkan daftar unik dari nilai duplikat) daripada mencetak ... Ini juga memiliki keuntungan merekam lokasi item duplikat juga.

Ashkan Aryan
sumber
7

Menggunakan Guava di 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
sumber
7

Ini juga berfungsi:

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
sumber
Ini berfungsi, tetapi agak lambat karena memanggil remove () pada daftar array adalah pencarian linier.
johnstosh
benar. Perhatikan bahwa jika masukan Anda berisi banyak duplikat, kinerja yang dicapai lebih sedikit daripada jika hanya ada sedikit.
Adriaan Koster
6

Anda dapat menggunakan sesuatu seperti ini:

List<Integer> newList = new ArrayList<Integer>();
for(int i : yourOldList)
{
    yourOldList.remove(i);
    if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
}
Eng. Fouad
sumber
2
Menggunakan Daftar di sini sangat tidak efektif
Alexander Farber
2
Dan jangan biarkan saya mulai menggunakan intsebagai tipe variabel di sini. Ini berarti bahwa untuk setiap iterasi, sebuah Integer tidak dikotakkan sekali dan int dikotak empat kali!
Sean Patrick Floyd
1
Saya pikir Anda bisa dengan mudah mendapatkan ConcurrentModificationException saat mencoba menghapus elemen dari daftar sambil mengulanginya
Jad B.
1
ini adalah 100% ConcurrentModificationException karena Anda mengulang daftar dan menghapus elemen dengan cepat.
theo231022
5

Lambas mungkin bisa menjadi solusi

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
sumber
1
Bekerja, tetapi menjalankan Collections.frequency untuk setiap entri dan karenanya lambat.
arberg
4

Gunakan MultiMap untuk menyimpan setiap nilai sebagai kumpulan kunci / nilai. Kemudian lakukan iterasi melalui kunci dan temukan kunci dengan beberapa nilai.

John B
sumber
3

Jika Anda menggunakan Koleksi Eclipse , ini akan berfungsi:

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

Pembaruan: Pada Koleksi Eclipse 9.2 Anda sekarang dapat menggunakanselectDuplicates

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

Anda juga dapat menggunakan koleksi primitif untuk melakukannya:

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

Catatan: Saya seorang pelaku untuk Koleksi Eclipse.

Donald Raab
sumber
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
sumber
Saya suka jawaban ini, hanya perlu menambahkan yang lain untuk menyimpan duplikat di daftar lain. terima kasih
Tiago Machado
2

Mirip dengan beberapa jawaban di sini, tetapi jika Anda ingin menemukan duplikat berdasarkan beberapa properti:

  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.dll
sumber
1

buat Map<Integer,Integer>, ulangi daftar, jika elemen ada di peta, tingkatkan nilainya, jika tidak tambahkan ke peta dengan key = 1,
ulangi peta, dan tambahkan ke daftar semua elemen dengan key> = 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
sumber
Ini lumayan bagus. Ini adalah solusi terbaik jika Anda perlu mengetahui berapa banyak duplikat yang ada. Beberapa catatan: (1) Anda tidak perlu memanggil remove () sebelum melakukan put (). (2) Anda bisa mengatur LinkedList dari array daripada menggunakan panggilan add () berulang. (3) Ketika val! = Null, Anda dapat langsung menambahkan x ke hasil. Hasilnya bisa berupa satu set atau daftar tergantung pada apakah Anda ingin menghitung jumlah duplikat.
johnstosh
1

Versi ringkas yang dihasilkan dari jawaban teratas, juga menambahkan cek kosong dan ukuran Set yang dialokasikan sebelumnya:

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
sumber
Apakah Anda memerlukan cek nol? Akankah HashSet baru <> (0) mengembalikan set kosong yang masuk akal?
johnstosh
@johnstosh kode ini dapat disederhanakan, tetapi memeriksa nol memungkinkan untuk hanya melakukan init tempSetdengan listSizebila perlu. Ini adalah pengoptimalan kecil tapi saya menyukainya.
Christophe Roussy
1

Saya mengambil jawaban Sebastian dan menambahkan keyExtractor padanya -

    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
sumber
1

Alternatif aman utas adalah ini:

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

Coba ini untuk menemukan item duplikat dalam daftar:

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
sumber
Ya, ini menemukan set, tetapi tidak menemukan daftar atau set item yang duplikat.
johnstosh
0

Ini harus bekerja untuk disortir dan tidak disortir.

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
sumber
Memanggil berisi () pada subList ArrayList mahal karena merupakan pencarian linier. Jadi ini oke untuk 10 item, tapi tidak untuk 10 juta.
johnstosh
0

Ini adalah masalah di mana teknik fungsional bersinar. Sebagai contoh, solusi F # berikut lebih jelas dan tidak terlalu rentan terhadap bug dibandingkan solusi Java imperatif terbaik (dan saya bekerja setiap hari dengan Java dan F #).

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

Tentu saja pertanyaan ini tentang Java. Jadi saran saya adalah mengadopsi perpustakaan yang menghadirkan fitur fungsional ke Java. Misalnya, ini bisa diselesaikan menggunakan perpustakaan saya sendiri sebagai berikut (dan ada beberapa lainnya di luar sana yang layak untuk dilihat juga):

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
sumber
Dan kemudian Anda melihat betapa Java sebenarnya masih menyebalkan pada pemrograman fungsional. Masalah yang begitu sederhana, sulit untuk mengungkapkan apa yang Anda inginkan di 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
sumber
Menerapkan tanpa menggunakan class Collection. Tetapi memerlukan sedikit peningkatan dalam loop. Bantuan sukarela cukup berarti Output untuk tampilan di atas -> 2 3 4 6 8 10 11 12
Samrat Roy
Untuk membuat ini dieksekusi dalam waktu yang lebih singkat, Anda perlu menggunakan struktur data berbasis hash untuk melacak duplikat. Itulah mengapa Anda melihat solusi lain menggunakan HashSet () - itu dibangun ke dalam Java.
johnstosh
@johnstosh Ya saya tahu tentang itu tetapi saya berpikir untuk membuatnya tanpa menggunakan Koleksi, itulah sebabnya saya sebutkan dalam komentar saya. Seperti yang Anda lihat, saya telah berkomentar jauh sebelum Feb 2017, [ada teknik di mana Anda tidak harus menggunakan koleksi sama sekali dengan kerumitan waktu yang lebih sedikit] geeksforgeeks.org/…. Saya telah mencoba program itu tanpa mengetahui praktik DS & Algo. Anda tidak perlu meremehkan saya untuk itu..selalu terima kasih.
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
sumber
apa yang perlu saya ubah untuk mengembalikan duplikat?
Brenden
Ini harus ditanyakan sebagai pertanyaan baru.
willaien
0

Ini akan menjadi metode yang baik untuk menemukan nilai Duplikat, tanpa menggunakan 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;
}

Dan katakanlah, Anda menginginkan metode yang mengembalikan Anda daftar berbeda, yaitu jika Anda meneruskan daftar di mana elemen muncul lebih dari sekali, Anda akan mendapatkan daftar dengan elemen berbeda.

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
sumber
0

Dan versi yang menggunakan commons-collections CollectionUtils.getCardinalityMapmetode:

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
sumber
0

Bagaimana dengan kode ini -

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
sumber
0

untuk berjaga-jaga bagi mereka yang juga ingin menyertakan duplikat dan bukan duplikat. pada dasarnya jawaban tersebut mirip dengan jawaban yang benar tetapi bukannya kembali dari jika bukan bagian Anda mengembalikan bagian lain

gunakan kode ini (ubah ke jenis yang Anda butuhkan)

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

sumber
0

Metode yang lebih umum sebagai varian dari 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
sumber
-1

Jika Anda mengetahui nilai maksimum (misalnya <10000), Anda dapat mengorbankan ruang untuk kecepatan. Saya tidak dapat mengingat nama pasti dari teknik ini.

kode semu:

//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
sumber
Saya pikir Anda ingin "boolean" daripada "bit"? Apakah Anda menjalankan kode Anda sebelum mempostingnya? Ini awal yang bagus. Jika Anda melihat HashSet () maka Anda akan melihat bahwa itu adalah implementasi 'ember' yang Anda inginkan.
johnstosh
-1

Coba saja ini:

Contoh jika nilai List adalah: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] duplikat item [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);
Pembelajaran Pengguna
sumber
Memanggil berisi () pada ArrayList () adalah operasi yang mahal, jadi Anda harus mempertimbangkan untuk menggunakan Set sebagai gantinya. Anda akan melihat solusi lain menggunakan HashSet () atau versi yang ditautkan.
johnstosh