Визначте дублікати у списку


119

У мене є список типу Integer, наприклад:

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

Я хотів би метод повернути всі дублікати, наприклад:

[1, 3]

Який найкращий спосіб зробити це?


2
Чи гарантовано сортування списку входів (як у вашому прикладі)?
NPE

7
сортуйте список, а потім пройдіть його, зберігаючи поточні та попередні значення. якщо current == до того, у вас є дублікат.
mcfinnigan

Ні, список не обов'язково сортується.
найсвіжіший

Відповіді:


183

Спосіб addпо Setповертає логічне значення , чи існує вже значення (правда , якщо вона не існує, брехня , якщо вона вже існує, см комплект документації ).

Тому просто повторіть усі значення:

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
Чому ви встановилиToReturn? Чи можете ви не просто використовувати set1.add (yourInt) та повернути set1?
Філ

3
так саме. Але коли елемент присутній лише один раз у вказаному списку, також додається елемент. Подивіться на приклад у запитанні: Моє рішення повернеться [1,3], оскільки число 2 вставлено у set1, а не в setToReturn. Ваше рішення повернеться [1,2,3] (що не є вимогою)
leifg

1
Я пропоную вам скористатися for (Integer yourInt, щоб уникнути зайвого боксу та розпакування, тим більше, що ваш внесок вже містить Integers.
Хосам Алі

1
@JonasThelemann вся ідея набору полягає в тому, що він НЕ може містити дублікатів. отже: незалежно від того, як часто ви додасте 3, це завжди закінчиться лише один раз.
leifg

1
До речі, у випадку, якщо HashSetвам також доведеться враховувати коефіцієнт навантаження, наприклад, коли ви вказуєте початкову ємність 100, оскільки ви хочете додати цю кількість елементів, вона округляється до наступної потужності 2 ( 128), що означає, що з коефіцієнтом навантаження за замовчуванням 0.75f, поріг зміни розміру буде 96, тому перед додаванням 100елементів буде розмір . На щастя, змінити розміри вже не так дорого. З сучасними JRE, зміни розміру більше не переробляються, елементи просто розподіляються між двома можливими місцями результатів на основі відповідного біту.
Холгер

50

Я також потребував вирішення цього питання. Я використав розчин Лейфга і зробив його загальним.

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
Я знаю, що це через 3 роки, але чому LinkedHashedSet, тобто чому ви дбаєте про замовлення?
Ахмад Рагаб

4
@AhmadRagab ви маєте рацію, LinkedHashSet не потрібен, якщо ви не піклуєтесь про те, щоб копії були знайдені (що, на мою думку, я робив у той час)
Джон Стріклер,

Дякуємо за продовження!
Ахмад Рагаб

Якщо у вас є стільки вхідних даних, що ви хочете використовувати це оптимальне рішення (замість сортування вхідних даних), ви також хочете попередньо виділити розмір об'єктів HashSet (). Без попереднього розміщення ви не отримаєте O (1) вставляти час, вставляючи в HashSet (). Це відбувається тому, що внутрішній хеш-масив неодноразово змінюється. Потім вставки в середньому до приблизно на зразок часу O (log N). Це означає, що обробка всіх N елементів стає O (N log N), коли вона могла бути O (N).
johnstosh

39

Я взяв рішення Джона Стріклера і переробив його для використання API потоків, введеного в 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());
}

3
це щось важко читати, ні? Ви робите побічний ефект в потоковій роботі, тому важко міркувати. Але це лише я думаю про функціональний стиль. Це стислий і, мабуть, найкоротший шлях;).
заморозка

Для великих списків ви можете зробити це виконання паралельно на кількох потоках?
johnstosh

@froginvasion вбудований distinct()метод також є надзвичайним. Не можу придумати ефективну (O (n)) чітку операцію, яка не є небезпечною.
wilmol

18

Ось рішення з використанням потоків із 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<>();

Ви просто подивіться, чи частота цього об'єкта у вашому списку більше, ніж один раз. Потім зателефонуйте .distinct (), щоб у вашому результаті були лише унікальні елементи

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
Це добре з точки зору читабельності, але РЕАЛЬНО погано для продуктивності. Collections::frequencyє O (n). Потрібно пройти всю колекцію, щоб знайти частоту предмета. І ми називаємо це один раз для кожного елемента колекції, який робить ці фрагменти O(n^2). Ви помітите різницю в будь-якій колекції з кількох елементів. Я б ніколи не використовував це в фактичному коді.
Паван

13

базовий розчин 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());

список вхідних даних перетворюється на карту (згрупування за однаковими значеннями). потім значення карти з унікальним значенням "видаляються", потім карта за допомогою клавіші, потім список списку перетворюється на Список
بلال المصمودي

красиве і швидке рішення, безпосередньо модифіковане у фільтрацію за конкретними
геттерами

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

}

Очевидно, ви можете робити з ними все, що завгодно (наприклад, помістити в набір, щоб отримати унікальний список повторюваних значень), а не друкувати ... Це також має перевагу записувати розташування повторюваних елементів.


7

Використання Guava на 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

Це також працює:

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

Це працює, але це досить повільно, оскільки виклик delete () у списку масиву - це лінійний пошук.
johnstosh

правда. Зауважте, що якщо ваш вхід містить багато дублікатів, показник ефективності менше, ніж якщо їх є лише кілька.
Адріан Костер

6

Ви можете використовувати щось подібне:

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

2
Використовувати Список тут дуже неефективно
Олександр Фарбер

2
І не запускайте мене intтут використовувати як тип змінної. Це означає, що для кожної ітерації Integer одноразово відмічається, а int - чотири рази!
Шон Патрік Флойд

1
Я думаю, що ви можете легко отримати ConcurrentModificationException, намагаючись видалити елемент зі списку під час ітерації над ним
Jad B.

1
це 100% ConcurrentModificationException, оскільки ви повторюєте список і ви видаляєте елементи на льоту.
theo231022

5

Ламба може бути рішенням

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
Працює, але він працює Collections.frequency для кожного запису і, таким чином, повільно.
arberg

4

Використовуйте MultiMap, щоб зберігати кожне значення як набір ключа / значення. Потім перейдіть по клавішах і знайдіть ті з кількома значеннями.


3

Якщо ви використовуєте Eclipse Collections , це спрацює:

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

Оновлення: Станом на Колекції Eclipse 9.2 тепер ви можете використовуватиselectDuplicates

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

Ви також можете використовувати примітивні колекції для цього:

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

Примітка. Я є членом колекції Eclipse.


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

    }

}

Мені подобається ця відповідь, просто потрібно додати ще, щоб зберегти дублікат в іншому списку. спасибі
Тіаго Мачадо

2

Подібно до деяких відповідей тут, але якщо ви хочете знайти дублікати на основі якоїсь властивості:

  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>, повторіть список, якщо елемент знаходиться на карті, збільште його значення, інакше додайте його до карти за допомогою ключа = 1
повторіть карту та додайте до списків усі елементи за допомогою ключа> = 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);
        }

    }

Це досить добре. Це найкраще рішення, якщо вам потрібно знати, скільки було дублікатів. Деякі зауваження: (1) вам не потрібно дзвонити видалити () перед тим, як робити put (). (2) Ви можете встановити LinkedList з масиву, а не використовувати повторні дзвінки add (). (3) Коли val! = Null, ви можете негайно додати x до результату. Результатом може бути набір або список, залежно від того, чи хотіли ви залишити кількість дублікатів.
johnstosh

1

Компактна узагальнена версія головної відповіді, також додано порожній чек та попередньо виділений розмір набору:

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

Вам потрібна нульова перевірка? Чи поверне новий HashSet <> (0) розумний порожній набір?
Джонстош

@johnstosh цей код можна спростити, але перевірка нуля дозволяє ініціювати лише tempSetз, listSizeколи це необхідно. Це незначна оптимізація, але мені це подобається.
Крістоф Руссі

1

Я взяв відповідь Себастьяна і додав до нього ключExtractor -

    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

Альтернативна безпека альтернативи:

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

Спробуйте це, щоб знайти дублікати елементів у списку:

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

Так, це знаходить набір, але він не знаходить список або набір тих елементів, які є дублікатами.
johnstosh

0

Це повинно працювати для сортованих та несортованих.

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 дорого, оскільки це лінійний пошук. Тож це нормально для 10 предметів, але не для 10 мільйонів.
johnstosh

0

Це проблема, коли блищать функціональні прийоми. Наприклад, наступне рішення F # є більш чітким і менш схильним до помилок, ніж найкраще необхідне рішення Java (і я працюю щодня як з Java, так і з F #).

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

Звичайно, це питання стосується Java. Тому я пропоную прийняти бібліотеку, яка приносить функціональні можливості Java. Наприклад, це можна вирішити, використовуючи мою власну бібліотеку наступним чином (а також є кілька інших, на які варто також подивитися):

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

І тоді ви бачите, скільки Java насправді все ще висмоктує у функціональному програмуванні. Така проста проблема, настільки важко висловити те, що ви хочете на 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;
    }

}

Реалізація без використання колекційних класів.Но потрібно трохи покращити цикл. Довідкова допомога у волонтері. Вихід для вище виглядає так:>> 2 3 4 6 8 10 11 12
Самрат Рой

Щоб зробити це виконаним за менший проміжок часу, вам потрібно використовувати структуру даних на основі хешу для відстеження дублікатів. Ось чому ви бачите інші рішення за допомогою HashSet () - він вбудований у Java.
johnstosh

@johnstosh Так, я знаю про це, але я думав зробити це без використання колекцій, чому я згадав у своєму коментарі. Як ви бачите, я коментував спосіб до лютого 2017 року, [є методи, де вам взагалі не доведеться використовувати колекції з меншою складністю часу] geeksforgeeks.org/…. Я спробував цю програму, не знаючи практик DS & Algo. Вам за це не потрібно звертати увагу ... завжди дякую.
Самрат Рой

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

що мені потрібно змінити, щоб повернути дублікати?
Бренден

Це слід задати як нове запитання.
willaien

0

Це був би хороший метод пошуку дублюючих значень, не використовуючи 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;
}

І скажіть, що ви хочете метод, який повертає вам окремий список, тобто якщо ви передаєте список, де елементи трапляються не один раз, ви отримаєте список з різними елементами.

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

І версія, яка використовує commons-collections CollectionUtils.getCardinalityMapметод:

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

Як щодо цього коду -

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

про всяк випадок для тих, хто також хоче включити як дублікат, так і не дублікати. в основному відповідь аналогічна правильній відповіді, але замість того, щоб повертатися з, якщо не частини, ви повертаєте іншу частину

використовувати цей код (змінити потрібний тип)

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

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

Якщо ви знаєте максимальне значення (наприклад, <10000), ви можете пожертвувати місцем для швидкості. Я не можу пригадати точну назву цієї методики.

псевдокод:

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

Я думаю, ви хочете "булевий" замість "біт"? Ви виконували код перед тим, як опублікувати його? Це вдалий старт. Якщо ви подивитесь на HashSet (), то побачите, що саме вам потрібна реалізація "відра".
Джонстош

-1

Просто спробуйте:

Приклад, якщо значеннями списку є: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] дублікат елемента [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);

Викликання містить () на ArrayList () - дорога операція, тому вам слід подумати про використання набору. Ви побачите інші рішення, використовуючи HashSet () або пов'язані його версії.
Джонстош
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.