2014-01-30 4 views
1

Привет и спасибо за чтение! В настоящее время я изучаю Generics в Java, и это то, что я пытаюсь выполнить:Удаление повторяющихся элементов в ArrayList Java

Мне нужно удалить повторяющиеся элементы из ArrayList. В настоящее время ArrayList содержит целые числа. Я хочу сначала распечатать исходный список, а затем распечатать полученный список после удаления дубликатов. Это то, что у меня есть до сих пор. Любая помощь приветствуется!

public static void main(String[] args) { 
    ArrayList<Integer> list1 = new ArrayList<Integer>(); 

    list1.add(1); 
    list1.add(1); 
    list1.add(1); 

    list1.add(2); 
    list1.add(2); 
    list1.add(2); 

    list1.add(3); 
    list1.add(3); 
    list1.add(3); 

    removeDuplicates(list1); 

     System.out.println("Original List with Duplicates: \n" + list1); 
     System.out.println(); 
     //System.out.println("After removing duplicates: \n" + list2); 

} 

public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list2){ 


    for(int i = 0; i < list2.size(); i++){ 

    //logic to remove duplicates  


    } 

    return list2; 
} 
+1

Нужно ли поддерживать порядок в списке? Если это так, вы хотите сохранить первый, последний или какой-либо другой дубликат? –

+0

Я хочу, чтобы конечный результат был просто «1 2 3» вместо «1 1 1 2 2 2 3 3 3». Но заказ не обязательно имеет значение, пока дубликаты не исчезнут. – user3254957

ответ

1

Шаг первый

Преобразование списка в набор.

Set<Integer> aSet = new HashSet<Integer>(list);

Шаг второй

Преобразование набора обратно в список.

list = new ArrayList<Integer>(new HashSet<Integer>(list));

Почему это работает

Наборы могут содержать только уникальные элементы.

+0

Я не уверен, что такое HashSet. Есть ли способ сделать это без него? – user3254957

+0

@ user3254957 HashSet - действительно эффективный набор. Набор представляет собой набор уникальных элементов. – Rainbolt

+0

О, хорошо, хорошо знать! Благодаря! – user3254957

2

Вы можете добавить элементы в коллекцию Set. Если вы хотите сохранить заказ, вы должны использовать LinkedHashSet

0

Преобразование массива ArrayList для установки, возможно, HashSet, а затем обратно в ArrayList, который можно сортировать, если вы хотите, чтобы номера в порядке (порядок в наборах обычно не гарантируется) ,

HashSet hs<Integer> = new HashSet(list1); 

ArrayList<Integer> uniqueList = Collections.sort(new ArrayList<Integer>(hs)); 

Там также различные SortedSet, среди них TreeSet.

Кроме того, вы можете использовать менее подверженной ошибкам строительства for цикла:

for (int i : uniqueList) { 
    System.out.println(i); 
} 
+0

ArrayList не имеет метода сортировки – MadProgrammer

+0

Вы правы, обновили его с помощью Collections.sort(). – claj

0
public static void main(String[] args) { 
    ArrayList<Integer> list1 = new ArrayList<Integer>(); 
    ArrayList<Integer> list2 = new ArrayList<Integer>(); 

    list1.add(1); 
    list1.add(1); 
    list1.add(1); 

    list1.add(2); 
    list1.add(2); 
    list1.add(2); 

    list1.add(3); 
    list1.add(3); 
    list1.add(3); 



     System.out.println("Original List with Duplicates: \n" + list1); 
     System.out.println(); 

     list2 = removeDuplicates(list1); 

     System.out.println("After removing duplicates: \n" + list2); 

} 

public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list2){ 

    ArrayList<E> usedList = new ArrayList<E>(); 
    ArrayList<E> newList = new ArrayList<E>(); 

    for(int i = 0; i < list2.size(); i++){ 

     E object = list2.get(i); 

     if(! usedList.contains(object)) 
     { 
      usedList.add(object); 
      newList.add(object); 
     } 
    } 

    return newList; 
} 

выход (как и ожидалось):

Original List with Duplicates: 
[1, 1, 1, 2, 2, 2, 3, 3, 3] 

After removing duplicates: 
[1, 2, 3] 

Если вы работаете с другими типами (не стандарт java, например int), то вам необходимо переопределить метод equals, потому что он используется в методе ArrayListcontains.

+0

это теоретически правильно, но неприемлемо медленно (сложность n^2). Алгоритм слишком медленный для использования на практике, поскольку он должен пройти через новый элемент списка по элементу, чтобы узнать, является ли новый элемент уникальным или нет. – claj

+0

@claj Да, вы правы. Но я думаю, что для учебных целей (когда эффективность _usually_ не так важна), это, вероятно, лучший способ сделать это. –

+0

Зло, чтобы научить людей вещам, которые не работают в реальной жизни, по крайней мере, не говоря о том, что действительно действительно ясно. Ваш пример пропускает такое предупреждение. Кроме того, этот пример намного длиннее других приведенных решений. – claj

0
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list2){ 
    LinkedHashSet<E> dataSet = new LinkedHashSet<E>(list2.size()); 
    dataSet.addAll(list2); 
    ArrayList<E> uniqueLists = new ArrayList<E>(dataSet.size()); 
    uniqueLists.addAll(dataSet); 
    return uniqueLists; 
} 
0

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

public static <E> List<E> removeDuplicates(List<E> list){ 
    ListIterator<E> iter = list.listIterator(); 
    Set<E> seen = new HashSet<>(); 
    while (iter.hasNext()) { 
     if (!seen.add(iter.next())) { 
      // element not added--must have already been seen, so remove element 
      iter.remove(); 
     } 
    } 
    return list; 
} 

Альтернативы сбросить весь список в Set, очистить список, а затем добавить все элементы множества вернуться в список. В зависимости от реализации Set это может или не может сохранить порядок.

public static <E> List<E> removeDuplicates(List<E> list){ 
    Set<E> unique = new LinkedHashSet<>(list); 
    list.clear(); 
    list.addAll(unique); 
    return list; 
} 

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

public static <E> List<E> removeNonUnique(List<E> list){ 
    Set<E> seen = new HashSet<>(); // all values seen 
    Set<E> dups = new HashSet<>(); // all values seen more than once 
    for (E elt : list) { 
     if (!seen.add(elt)) { 
      // element not added--must have already been seen, so add to dups 
      dups.add(elt); 
     } 
    } 
    // clean out the list 
    list.removeAll(dups); 
    return list; 
} 

Обратите внимание, что, так как мы не изменяя список во время цикла, нам не нужно иметь явный итератор.

+0

Спасибо за это! Что, если я захочу удалить все, что имеет повторяющиеся элементы? Например: если я добавлю 4 и 5 в список как отдельные элементы, после удаления всех повторяющихся элементов вывод будет просто «4 5» с 1,2 и 3 имеют дублирующие элементы. – user3254957

+0

@ user3254957 - Я добавил код, чтобы показать, как я это сделаю. Я изменил имя метода, поскольку на самом деле это не совсем то же самое. –

+0

Спасибо Теду! Выглядит хорошо. – user3254957

Смежные вопросы