Удалить каждый повторяющийся элемент из ArrayList

Пожалуйста, прежде чем минусовать - прочитайте вопрос и проверьте пример - это не дубликат!

Я хочу удалить каждый повторяющийся элемент из ArrayList в Java, например:

Original list: [4, 2, 2, 3, 4, 1]
Set result: [1, 2, 3, 4]
Desired result: [1, 3]

Очевидное решение для дубликатов — set здесь не работает.

Мое решение:

        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(5);
        arrayList.add(1);
        arrayList.add(5);
        arrayList.add(1);
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(3);

        ArrayList<Integer> temp = new ArrayList<>(arrayList);

        for(Integer number : new HashSet<Integer>(arrayList)){
            temp.remove(number);
        }

        arrayList.removeAll(temp);

Любые более умные/более умные решения?


person bartektartanus    schedule 28.07.2014    source источник
comment
Предоставленный дубликат был неправильным, но вы все равно не приложили никаких усилий.   -  person Sotirios Delimanolis    schedule 28.07.2014
comment
Дубликат чего? В любом случае, каков ваш вопрос и проблема, с которой вы столкнулись? Я вижу, чего вы хотите достичь, но я не вижу части, в которой вы объясняете, что мешает вам это сделать.   -  person Pshemo    schedule 28.07.2014
comment
Я задал этот вопрос 2 минуты назад и получил 6 отрицательных голосов за повторяющийся вопрос, но это явно не так.   -  person bartektartanus    schedule 28.07.2014
comment
Понижение не обязательно было за дубликаты. Вы должны показать нам, что вы уже пробовали.   -  person Swapnil    schedule 28.07.2014
comment
Вы не опубликовали код, показывающий, что вы пробовали. Кроме того, если за вопрос проголосовали против, не публикуйте его повторно.   -  person TFischer    schedule 28.07.2014
comment
Домашнее задание! Обратитесь за помощью к своему преподавателю или ТА.   -  person markspace    schedule 28.07.2014
comment
@mickey Ваши ссылки неверны. Проверьте желаемый результат, а не заданный результат.   -  person Pshemo    schedule 28.07.2014
comment
@Pshemo: я понимаю, о чем вы говорите: ни одна из этих ссылок не содержит кода для получения желаемого результата. Как следует из нескольких других ответов, похоже, что ОП ничего не пробовал. Код в этих ссылках может указать путь.   -  person Al Lelopath    schedule 28.07.2014
comment
@bartektartanus Ваш исходный список всегда отсортирован?   -  person Pshemo    schedule 28.07.2014
comment
Нет, это просто пример :)   -  person bartektartanus    schedule 28.07.2014
comment
Поскольку у вас уже есть работающее решение и вы заинтересованы в его улучшении (полагаю, в нем нет ошибок), вы должны опубликовать свой вопрос на codereview.stackexchange. .com. Общее правило таково: (1) если ваш код работает, но вы хотели бы услышать, как он может работать лучше, опубликуйте в обзоре кода (2), если вы пытаетесь заставить свой код работать, опубликуйте в Stack Overflow. В любом случае, поскольку вы уже разместили свой вопрос на Stack Overflow, этот совет предназначен для ваших будущих вопросов (вы должны публиковать вопрос только на одном из сайтов StackExchange, поэтому выберите либо SO, либо CR, никогда не публикуйте один и тот же вопрос на обоих сайтах).   -  person Pshemo    schedule 28.07.2014


Ответы (3)


В качестве альтернативы вы также можете проверить частоту удаления. Collections.frequency(arrayList, number)

public static void main(String[] args) {
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    arrayList.add(5);
    arrayList.add(1);
    arrayList.add(5);
    arrayList.add(1);
    arrayList.add(5);
    arrayList.add(2);
    arrayList.add(3);

    ArrayList<Integer> unique = new ArrayList<>();

    for (Integer number : arrayList) {
        if (Collections.frequency(arrayList, number) == 1) {
            unique.add(number);
        }
    }

    System.out.println(unique);
}
person Syam S    schedule 28.07.2014
comment
Вы также можете изменить условие частоты на == 1, а затем использовать полученный список как список тех чисел, которые не повторяются. - person JamesB; 28.07.2014
comment
Да. Отличная идея. Это аннулирует дополнительный цикл. Обновил мой ответ .. :) - person Syam S; 28.07.2014

Есть много способов сделать то, что вы хотите сделать. Вот один из них (где T — это тип, хранящийся в вашем существующем списке):

  1. Выделите Map<T, Integer>. Целое число будет использоваться для хранения того, сколько раз этот элемент появляется в вашем списке.
  2. Повторите свой список. Найдите каждый элемент на карте. Если он не существует, верните счет единице. Если он уже существует на карте, увеличьте счетчик и верните новый счетчик.
  3. Повторите записи на карте, чтобы извлечь дедублированный список. Вы не будете включать никакую запись со значением больше единицы.

Этот подход будет быстрым даже для больших списков.

person Rob    schedule 28.07.2014
comment
Ницца. Мне даже счетчик не нужен. Простого true/false достаточно :) - person bartektartanus; 28.07.2014

Вы можете использовать цикл для проверки дубликатов в ArrayList, а затем использовать remove() в ArrayList для удаления элементов.

См. следующее:

{
    ArrayList list;
    // ...
    while(true)
        for(final Integer o : list) {
            if(list.indexOf(o) != list.lastIndexOf(o)) {
                while(list.remove(o));
                continue;
            }
            break;
        }
}

Вместо нативного лучшего подхода было бы использовать временный Set для хранения объекты для удаления:

{
    ArrayList list;
    TreeSet<Integer> set = new TreeSet<>(); // Use your Set!
    // ...
    for(final Integer o : list)
        if(list.indexOf(o) != list.lastIndexOf(o))
            set.add(o);
    for(final Integer o : set)
        while(list.remove(o));
}
person Unihedron    schedule 28.07.2014
comment
Я думаю, что лучше просто скопировать список - перебрать один и удалить из другого :) - person bartektartanus; 28.07.2014
comment
Вы не должны изменять коллекцию, которую вы повторяете с помощью цикла for-each. - person Pshemo; 28.07.2014
comment
@Pshemo Я исправил это. Обратите внимание, что Iterable, используемый в for-каждом цикле, одновременно вызывает .next() до тех пор, пока .hasNext() не вернет false, поэтому вам необходимо перезапускать итерацию после каждой модификации (continue -> повтор блока while(true) -> for-каждый раз). - person Unihedron; 28.07.2014
comment
К вашему сведению, добавлено решение для использования временного файла Set. - person Unihedron; 28.07.2014