Удаление повторяющихся значений из ArrayList

У меня есть один Arraylist из String, и я добавил в него некоторое дублирующее значение. и я просто хочу удалить это дублирующее значение. Так как его удалить.

В этом примере у меня есть одна идея.

List<String> list = new ArrayList<String>();
        list.add("Krishna");
        list.add("Krishna");
        list.add("Kishan");
        list.add("Krishn");
        list.add("Aryan");
        list.add("Harm");

        System.out.println("List"+list);

        for (int i = 1; i < list.size(); i++) {
            String a1 = list.get(i);
            String a2 = list.get(i-1);
            if (a1.equals(a2)) {
                list.remove(a1);
            }
        }

        System.out.println("List after short"+list);

Но есть ли Достаточный способ удалить этот список дубликатов. без использования цикла For? И я могу это сделать, используя HashSet или каким-либо другим способом, но используя список массивов. хотел бы предложить ваше предложение. спасибо за ваш ответ заранее.

Ответы

Ответ 1

Вы можете создать LinkedHashSet из списка. LinkedHashSet будет содержать каждый элемент только один раз и в том же порядке, что и List. Затем создайте новый List из этого LinkedHashSet. Так эффективно, это однострочный:

list = new ArrayList<String>(new LinkedHashSet<String>(list))

Любой подход, который включает в себя List#contains или List#remove, вероятно, уменьшит асимптотическое время работы от O (n) (как в приведенном выше примере) до O (n ^ 2).


EDIT. Для требования, упомянутого в комментарии: Если вы хотите удалить повторяющиеся элементы, но считайте строки равными, игнорируя случай, тогда вы можете сделать что-то вроде этого:

Set<String> toRetain = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
toRetain.addAll(list);
Set<String> set = new LinkedHashSet<String>(list);
set.retainAll(new LinkedHashSet<String>(toRetain));
list = new ArrayList<String>(set);

У него будет время работы O (n * logn), которое по-прежнему лучше многих других опций. Обратите внимание, что это выглядит немного сложнее, чем могло бы быть: я предположил, что порядок элементов в списке не может быть изменен. Если порядок элементов в списке не имеет значения, вы можете просто сделать

Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
set.addAll(list);
list = new ArrayList<String>(set);

Ответ 2

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

void addToList(String s){
  if(!yourList.contains(s))
       yourList.add(s);
}

В этом случае подходящим является использование Set.

Ответ 3

Вы можете использовать утилиты Google Guava, как показано ниже.

 list = ImmutableSet.copyOf(list).asList(); 

Это, пожалуй, самый эффективный способ удаления дубликатов из списка и интересно, он сохраняет итерационный порядок.

UPDATE

Но в случае, если вы не хотите включать Guava, дубликаты могут быть удалены, как показано ниже.

ArrayList<String> list = new ArrayList<String>();
    list.add("Krishna");
    list.add("Krishna");
    list.add("Kishan");
    list.add("Krishn");
    list.add("Aryan");
    list.add("Harm");

System.out.println("List"+list);
HashSet hs = new HashSet();
hs.addAll(list);
list.clear();
list.addAll(hs);

Но, конечно, это разрушит порядок итераций элементов в ArrayList.

Шишир

Ответ 4

Java 8 функция потока

Вы можете использовать функцию distinct, как показано выше, чтобы получить отдельные элементы списка,

stringList.stream().distinct();

Из документации

Возвращает поток, состоящий из отдельных элементов (в соответствии с Object.equals(Object)) этого потока.


Другим способом, если вы не хотите использовать метод equals, является функция collect, как это,

stringList.stream()  
    .collect(Collectors.toCollection(() -> 
        new TreeSet<String>((p1, p2) -> p1.compareTo(p2)) 
));  

Из документации

Выполняет изменяемую операцию сокращения элементов этого потока с использованием Collector.

Надеюсь, что это поможет.

Ответ 5

List<String> list = new ArrayList<String>();
        list.add("Krishna");
        list.add("Krishna");
        list.add("Kishan");
        list.add("Krishn");
        list.add("Aryan");
        list.add("Harm");

HashSet<String> hs=new HashSet<>(list);

System.out.println("=========With Duplicate Element========");
System.out.println(list);
System.out.println("=========Removed Duplicate Element========");
System.out.println(hs);

Ответ 6

Я не думаю, что list = new ArrayList<String>(new LinkedHashSet<String>(list)) не самый лучший способ, так как мы используем LinkedHashset (мы можем использовать непосредственно LinkedHashset вместо ArrayList),

Решение:

import java.util.ArrayList;
public class Arrays extends ArrayList{

@Override
public boolean add(Object e) {
    if(!contains(e)){
        return super.add(e);
    }else{
        return false;
    }
}

public static void main(String[] args) {
    Arrays element=new Arrays();
    element.add(1);
    element.add(2);
    element.add(2);
    element.add(3);

    System.out.println(element);
}
}

Вывод: [1, 2, 3]

Здесь я расширяю ArrayList, поскольку я использую его с некоторыми изменениями, переопределяя метод add.

Ответ 7

Простая функция для удаления дубликатов из списка

private void removeDuplicates(List<?> list)
{
    int count = list.size();

    for (int i = 0; i < count; i++) 
    {
        for (int j = i + 1; j < count; j++) 
        {
            if (list.get(i).equals(list.get(j)))
            {
                list.remove(j--);
                count--;
            }
        }
    }
}

Пример:
Вход: [1, 2, 2, 3, 1, 3, 3, 2, 3, 1, 2, 3, 3, 4, 4, 4, 1]
Выход: [1, 2, 3, 4]

Ответ 8

Это будет лучший способ

    List<String> list = new ArrayList<String>();
    list.add("Krishna");
    list.add("Krishna");
    list.add("Kishan");
    list.add("Krishn");
    list.add("Aryan");
    list.add("Harm");

    Set<String> set=new HashSet<>(list);

Ответ 9

Лучше использовать HastSet

1-a) HashSet содержит набор объектов, но таким образом, что позволяет вам легко и быстро определить, находится ли объект уже в наборе или нет. Он делает это, внутренне управляя массивом и сохраняя объект, используя индекс, который вычисляется из хэш-кода объекта. Взгляните сюда

1-b) HashSet - это неупорядоченная коллекция, содержащая уникальные элементы. Он имеет стандартные операции коллекции Add, Remove, Contains, но поскольку он использует хэш-реализацию, эти операции O (1). (В отличие от List, например O (n) для Contains и Remove.) HashSet также предоставляет стандартные операции набора, такие как объединение, пересечение и симметричная разность. Посмотрите здесь

2) Существуют различные реализации наборов. Некоторые делают операции ввода и поиска сверхбыстрыми элементами хэширования. Однако это означает, что порядок, в котором были добавлены элементы, теряется. Другие реализации сохраняют добавленный заказ за счет более медленного времени работы.

Класс HashSet в С# идет для первого подхода, тем самым не сохраняя порядок элементов. Это намного быстрее обычного списка. Некоторые базовые тесты показали, что HashSet прилично быстрее работает с первичными типами (int, double, bool и т.д.). Это намного быстрее при работе с объектами класса. Таким образом, точка HashSet быстрая.

Единственный улов HashSet - отсутствие доступа по индексам. Для доступа к элементам вы можете либо использовать перечислитель, либо использовать встроенную функцию для преобразования HashSet в список и итерации через это. Посмотрите здесь

Ответ 10

Без цикла Нет! Поскольку ArrayList индексируется по порядку, а не по ключу, вы не можете найти целевой элемент без повторения всего списка.

Хорошей практикой программирования является выбор правильной структуры данных в соответствии с вашим сценарием. Поэтому, если Set больше подходит для вашего сценария, обсуждение его реализации с помощью List и попытка найти самый быстрый способ использования ненадлежащей структуры данных не имеет смысла.

Ответ 11

public static void main(String[] args) {
    @SuppressWarnings("serial")
    List<Object> lst = new ArrayList<Object>() {
        @Override
        public boolean add(Object e) {
            if(!contains(e))
            return super.add(e);
            else
            return false;
        }
    };
    lst.add("ABC");
    lst.add("ABC");
    lst.add("ABCD");
    lst.add("ABCD");
    lst.add("ABCE");
    System.out.println(lst);

}

Это лучший способ

Ответ 12

list = list.stream().distinct().collect(Collectors.toList());
Это может быть одно из решений, использующих Java8 Stream API. Надеюсь это поможет.

Ответ 13

Использование java 8:

public static <T> List<T> removeDuplicates(List<T> list) {
    return list.stream().collect(Collectors.toSet()).stream().collect(Collectors.toList());
}

Ответ 14

Если вам просто нужно удалить дубликаты, используя только ArrayList, других классов Collection, то: -

//list is the original arraylist containing the duplicates as well
List<String> uniqueList = new ArrayList<String>();
    for(int i=0;i<list.size();i++) {
        if(!uniqueList.contains(list.get(i)))
            uniqueList.add(list.get(i));
    }

Надеюсь, это поможет!

Ответ 15

private static void removeDuplicates(List<Integer> list)
{
    Collections.sort(list);
    int count = list.size();
    for (int i = 0; i < count; i++) 
    {
        if(i+1<count && list.get(i)==list.get(i+1)){
            list.remove(i);
            i--;
            count--;
        }
    }
}

Ответ 16

     public List<Contact> removeDuplicates(List<Contact> list) {
    // Set set1 = new LinkedHashSet(list);
    Set set = new TreeSet(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
                 if(((Contact)o1).getId().equalsIgnoreCase(((Contact)2).getId()) ) {
                return 0;
            }
            return 1;
        }
    });
    set.addAll(list);
    final List newList = new ArrayList(set);
    return newList;
}