Как удалить повторяющиеся элементы из ArrayList?

У меня есть ArrayList<String>, и я хочу удалить с него повторяющиеся строки. Как я могу это сделать?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
525
0
822 310
38
Перейти к ответу Данный вопрос помечен как решенный

Ответы 38

Ответ принят как подходящий

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

Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);

Конечно, это нарушает порядок элементов в ArrayList.

См. Также LinkedHashSet, если вы хотите сохранить порядок.

volley 09.12.2009 23:38

Но это просто создаст набор без дубликатов, я хочу знать, какой номер дублировался за время O (n)

Chetan 29.03.2012 23:43

Четан, поиск элементов в O (n) возможен, если набор возможных значений невелик (подумайте, Byte или Short); затем можно использовать BitSet или аналогичный для хранения и поиска уже встреченных значений за время O (1). Но опять же - с таким маленьким набором значений выполнение этого за O (n log n) в любом случае может не быть проблемой, поскольку n низкое. (Этот комментарий не применим к исходному плакату, которому нужно сделать это с помощью String.)

volley 03.05.2012 16:38

@Chetan находит все дубликаты из ArrayList в O (n), важно правильно определить метод equals для объектов, которые у вас есть в списке (нет проблем с числами): public Set<Object> findDuplicates(List<Object> list) { Set<Object> items = new HashSet<Object>(); Set<Object> duplicates = new HashSet<Object>(); for (Object item : list) { if (items.contains(item)) { duplicates.add(item); } else { items.add(item); } } return duplicates; }

Ondrej Bozek 20.06.2012 16:06

это здорово, и станет еще лучше, если вы измените HashSet на LinkedHashSet

Kevik 23.07.2013 15:07

Хорошей практикой будет определение переменных с использованием типов интерфейса List и Set (вместо типов реализации ArrayList и HashSet, как в вашем примере).

Jonik 29.08.2013 11:27

Вы можете очистить это, используя new HashSet(al) вместо инициализации его пустым и вызывая addAll.

ashes999 26.12.2013 16:44

Могу ли я добавить правила для настройки того, что для меня дублируется? Например: когда мой Object имеет несколько значений, если два из них повторяются, я считаю их дубликатами (другие значения могут отличаться) и использую Set?

jean d'arme 18.08.2015 12:32

@ jonathan-Stafford хороший и полезный код. голосование

maytham-ɯɐɥʇʎɐɯ 14.11.2015 15:25

Одна из причин, по которой я вынужден использовать коллекцию вместо набора, связана с вызовами HTTP API. API возвращает POJO определенных объектов, мне нужно воздействовать на него данными, поэтому мне действительно нужно, чтобы они не дублировались. По какой-то причине это не было частью API, чтобы вернуть мне список недублированных данных, я не могу дождаться, пока он будет разработан, поэтому я должен найти способ представить список без дубликатов.

Neon Warge 03.08.2016 10:45

И OneLiner будет: myArrayList = new ArrayList(new HashSet(myArrayList)); (но просто сделайте это, если вам действительно нужен ArrayList до И после этой строки!)

r00tandy 27.08.2016 14:25

@ jeand'arme Если вы используете TreeSet вместо HashSet, вы можете определить свой собственный Comparator для использования, и TreeSet будет рассматривать два элемента как дубликаты, если Comparators .compare (e1, e2) возвращает 0. Обратите внимание, что это будет разрушить существующий порядок Arraylist.

Jarred Allen 28.08.2016 00:48

какова временная сложность?

Giacomo 14.11.2018 18:52

не работает с ArrayList, имеющим модель вместо строки.

Ajay Mistry 26.02.2020 15:16

Альтернатива: Set<Object> set = new HashSet<>(); yourList.removeIf(x -> !set.add(x)); Преимущество состоит в том, что эта альтернатива позволяет вам решить, что использовать в выражении set.add(…) для вашего конкретного понятия «дубликат». Он также не зависит от фактического типа элементов списка. Он также сохраняет порядок, независимо от того, поддерживает ли набор этот порядок или нет. Также можно использовать с TreeSet (например, с настраиваемым компаратором) вместо HashSet.

Holger 04.06.2020 10:42

Если вам не нужны дубликаты, используйте Набор вместо List. Чтобы преобразовать List в Set, вы можете использовать следующий код:

// list is some List of Strings
Set<String> s = new HashSet<String>(list);

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

Точно так же в конце цепочки я дал ответ, в котором я использую Set for Custom Object. В случае, если у кого-то есть настраиваемый объект, такой как «Контакт» или «Студент», можно использовать этот ответ, который мне подходит.

Muhammad Adil 25.10.2016 17:16

Проблема возникает, когда вам нужно специально получить доступ к элементу. Например, при привязке объекта к представлению элемента списка в Android вам дается его индекс. Поэтому Set здесь использовать нельзя.

TheRealChx101 05.04.2019 09:13

Как я могу подойти к этому, если список представляет собой список объектов

jvargas 16.03.2020 23:20

Хотя преобразование ArrayList в HashSet эффективно удаляет дубликаты, если вам нужно сохранить порядок вставки, я бы рекомендовал вам использовать этот вариант.

// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);

Затем, если вам нужно вернуть ссылку на List, вы можете снова использовать конструктор преобразования.

Предоставляет ли LinkedHashSet какие-либо гарантии относительно того, какой из нескольких дубликатов хранится в списке? Например, если позиции 1, 3 и 5 дублируются в исходном списке, можем ли мы предположить, что этот процесс удалит 3 и 5? А может убрать 1 и 3? Спасибо.

Matt Briançon 01.05.2011 06:20

@Matt: да, это гарантирует. документы говорит: «Этот связанный список определяет порядок итераций, то есть порядок, в котором элементы были вставлены в набор (порядок вставки). Обратите внимание, что порядок вставки не изменяется, если элемент повторно вставляется в набор».

abahgat 02.05.2011 13:00

Очень интересно. У меня здесь другая ситуация. Я пытаюсь сортировать не String, а другой объект с именем AwardYearSource. Этот класс имеет атрибут типа int, называемый годом. Поэтому я хочу удалить дубликаты по году. то есть, если 2010 год упоминается более одного раза, я хочу удалить этот объект AwardYearSource. Как я могу это сделать?

WowBow 16.04.2012 19:27

@WowBow Например, вы можете определить объект Wrapper, который содержит AwardYearSource. И определите этот метод равенства объектов Wrapper на основе поля года AwardYearSources. Затем вы можете использовать Set с этими объектами Wrapper.

Ondrej Bozek 20.06.2012 16:19

@WowBow или реализовать Comparable / Comparator

shrini1000 11.01.2013 09:09

Как было сказано ранее, вы должны использовать класс, реализующий интерфейс Set, вместо List, чтобы быть уверенным в уникальности элементов. Если вам необходимо сохранить порядок элементов, можно использовать интерфейс SortedSet; класс TreeSet реализует этот интерфейс.

Возможно, это немного перебор, но мне нравится такая изолированная проблема. :)

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

public static <T> void removeDuplicates(ArrayList<T> list) {
    int size = list.size();
    int out = 0;
    {
        final Set<T> encountered = new HashSet<T>();
        for (int in = 0; in < size; in++) {
            final T t = list.get(in);
            final boolean first = encountered.add(t);
            if (first) {
                list.set(out++, t);
            }
        }
    }
    while (out < size) {
        list.remove(--size);
    }
}

Пока мы это делаем, вот версия для LinkedList (намного лучше!):

public static <T> void removeDuplicates(LinkedList<T> list) {
    final Set<T> encountered = new HashSet<T>();
    for (Iterator<T> iter = list.iterator(); iter.hasNext(); ) {
        final T t = iter.next();
        final boolean first = encountered.add(t);
        if (!first) {
            iter.remove();
        }
    }
}

Используйте интерфейс маркера, чтобы представить единое решение для List:

public static <T> void removeDuplicates(List<T> list) {
    if (list instanceof RandomAccess) {
        // use first version here
    } else {
        // use other version here
    }
}

Обновлено: Я думаю, что дженерики на самом деле не добавляют здесь никакой ценности ... Ну, хорошо. :)

Зачем использовать ArrayList в параметре? Почему не просто список? Это не сработает?

Shervin Asgari 12.11.2009 18:54

Список обязательно будет Работа как входной параметр для первого перечисленного метода. Однако это метод оптимизированный для использования со списком произвольного доступа, таким как ArrayList, поэтому, если вместо этого будет передан LinkedList, вы получите низкую производительность. Например, установка элемента n: th в LinkedList занимает O (n) времени, тогда как установка элемента n: th в списке произвольного доступа (таком как ArrayList) занимает время O (1). Опять же, это, вероятно, излишество ... Если вам нужен такой специализированный код, он, надеюсь, окажется в изолированной ситуации.

volley 09.12.2009 23:37

Вот способ, который не повлияет на порядок вашего списка:

ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();

Iterator iterator = l1.iterator();

while (iterator.hasNext()) {
    YourClass o = (YourClass) iterator.next();
    if (!l2.contains(o)) l2.add(o);
}

l1 - это исходный список, а l2 - это список без повторяющихся элементов (Убедитесь, что в YourClass есть метод equals в соответствии с тем, что вы хотите обозначить равенством)

В этом ответе не хватает двух вещей: 1) Он не использует дженерики, а необработанные типы (ArrayList<T> следует использовать вместо ArrayList) 2) Явного создания итератора можно избежать, используя for (T current : l1) { ... }. Даже если вы хотите использовать Iterator явно, в iterador есть орфографические ошибки.

RAnders00 07.12.2015 19:22

И эта реализация выполняется за квадратичное время по сравнению с реализацией связанного хеш-набора, работающей за линейное время. (т.е. это занимает в 10 раз больше времени для списка из 10 элементов, в 10 000 раз больше для списка из 10 000 элементов. Реализация JDK 6 для ArrayList.contains, JDK8 impl такая же.)

Patrick M 11.07.2016 19:09

Когда вы заполняете ArrayList, используйте условие для каждого элемента. Например:

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

    // fill 1 
    for ( int i = 0; i <= 5; i++ ) 
        if ( !al.contains( i ) ) 
            al.add( i ); 

    // fill 2 
    for (int i = 0; i <= 10; i++ ) 
        if ( !al.contains( i ) ) 
            al.add( i ); 

    for( Integer i: al )
    {
        System.out.print( i + " ");     
    }

Мы получим массив {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Также есть вариант ImmutableSet от Гуава (здесь - это документация):

ImmutableSet.copyOf(list);

Обратите внимание, что существует метод ImmutableSet.asList(), возвращающий ImmutableList, если он вам нужен как List.

Andy Turner 27.10.2017 22:25

for(int a=0;a<myArray.size();a++){
        for(int b=a+1;b<myArray.size();b++){
            if (myArray.get(a).equalsIgnoreCase(myArray.get(b))){
                myArray.remove(b); 
                dups++;
                b--;
            }
        }
}

import java.util.*;
class RemoveDupFrmString
{
    public static void main(String[] args)
    {

        String s = "appsc";

        Set<Character> unique = new LinkedHashSet<Character> ();

        for(char c : s.toCharArray()) {

            System.out.println(unique.add(c));
        }
        for(char dis:unique){
            System.out.println(dis);
        }


    }
}

LinkedHashSet сделает свое дело.

String[] arr2 = {"5","1","2","3","3","4","1","2"};
Set<String> set = new LinkedHashSet<String>(Arrays.asList(arr2));
for(String s1 : set)
    System.out.println(s1);

System.out.println( "------------------------" );
String[] arr3 = set.toArray(new String[0]);
for(int i = 0; i < arr3.length; i++)
     System.out.println(arr3[i].toString());

// вывод: 5,1,2,3,4

public Set<Object> findDuplicates(List<Object> list) {
        Set<Object> items = new HashSet<Object>();
        Set<Object> duplicates = new HashSet<Object>();
        for (Object item : list) {
            if (items.contains(item)) {
                duplicates.add(item);
                } else { 
                    items.add(item);
                    } 
            } 
        return duplicates;
        }

это может решить проблему:

private List<SomeClass> clearListFromDuplicateFirstName(List<SomeClass> list1) {

     Map<String, SomeClass> cleanMap = new LinkedHashMap<String, SomeClass>();
     for (int i = 0; i < list1.size(); i++) {
         cleanMap.put(list1.get(i).getFirstName(), list1.get(i));
     }
     List<SomeClass> list = new ArrayList<SomeClass>(cleanMap.values());
     return list;
}

Мне больше понравилось это решение.

Tushar Gogna 05.12.2017 10:19

Если вы хотите сохранить свой Заказ, лучше всего использовать LinkedHashSet. Потому что, если вы хотите передать этот список в запрос вставки путем его итерации, порядок будет сохранен.

Попробуй это

LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);

Это преобразование будет очень полезно, если вы хотите вернуть список, но не набор.

Можно удалить дубликаты из arrayylist без использования HashSet или еще один Arraylist.

Попробуйте этот код ..

    ArrayList<String> lst = new ArrayList<String>();
    lst.add("ABC");
    lst.add("ABC");
    lst.add("ABCD");
    lst.add("ABCD");
    lst.add("ABCE");

    System.out.println("Duplicates List "+lst);

    Object[] st = lst.toArray();
      for (Object s : st) {
        if (lst.indexOf(s) != lst.lastIndexOf(s)) {
            lst.remove(lst.lastIndexOf(s));
         }
      }

    System.out.println("Distinct List "+lst);

Выход

Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]

Это медленно, и вы можете получить исключение ConcurrentModificationException.

maaartinus 18.10.2013 13:39

@maaartinus Вы пробовали этот код? Никаких исключений не будет, да и довольно быстро. Я попробовал код перед публикацией.

CarlJohn 18.10.2013 14:35

Вы правы, это не так, поскольку вы перебираете массив вместо списка. Однако это чертовски медленно. Попробуйте использовать несколько миллионов элементов. Сравните это с ImmutableSet.copyOf(lst).toList().

maaartinus 18.10.2013 14:49

отвечает на вопрос, который мне задали в интервью .. Как удалить повторяющиеся значения из ArrayList без использования Set. Спасибо

Aniket Paul 05.05.2016 12:10

Внутри indexOf выполняет итерацию lst, используя цикл for.

Patrick M 11.07.2016 20:32

В Java 8:

List<String> deduped = list.stream().distinct().collect(Collectors.toList());

Обратите внимание, что для правильной работы фильтрации необходимо соблюдать контракт hashCode-равно для членов списка.

Как мне сделать это для нечувствительности к регистру?

StackFlowed 13.09.2016 23:04

@StackFlowed Если вам не нужно сохранять порядок в списке, вы можете от addAll до new TreeSet<String>(String.CASE_INSENSITIVE_ORDER). Первый добавленный элемент останется в наборе, поэтому, если ваш список содержит «Dog» и «dog» (в этом порядке), TreeSet будет содержать «Dog». Если порядок необходимо сохранить, то перед строкой в ​​ответе поставьте list.replaceAll(String::toUpperCase);.

Paul 04.11.2017 02:28

Я получаю эту ошибку: несовместимые типы: List <Object> не может быть преобразован в List <String>

Samir 04.04.2018 17:34

В общем, это простое решение, но как удалить дубликаты из Arraylist int []?

Laser Infinite 23.01.2020 23:13

    ArrayList<String> list = new ArrayList<String>();
    HashSet<String> unique = new LinkedHashSet<String>();
    HashSet<String> dup = new LinkedHashSet<String>();
    boolean b = false;
    list.add("Hello");
    list.add("Hello");
    list.add("how");
    list.add("are");
    list.add("u");
    list.add("u");

    for(Iterator iterator= list.iterator();iterator.hasNext();)
    {
        String value = (String)iterator.next();
        System.out.println(value);

        if (b==unique.add(value))
            dup.add(value);
        else
            unique.add(value);


    }
    System.out.println(unique);
    System.out.println(dup);

Если вы хотите удалить дубликаты из ArrayList, найдите приведенную ниже логику,

public static Object[] removeDuplicate(Object[] inputArray)
{
    long startTime = System.nanoTime();
    int totalSize = inputArray.length;
    Object[] resultArray = new Object[totalSize];
    int newSize = 0;
    for(int i=0; i<totalSize; i++)
    {
        Object value = inputArray[i];
        if (value == null)
        {
            continue;
        }

        for(int j=i+1; j<totalSize; j++)
        {
            if (value.equals(inputArray[j]))
            {
                inputArray[j] = null;
            }
        }
        resultArray[newSize++] = value;
    }

    long endTime = System.nanoTime()-startTime;
    System.out.println("Total Time-B:"+endTime);
    return resultArray;
}

Зачем публиковать квадратичное решение вопроса, для которого уже есть линейные и лог-линейные решения двухлетней давности, которые также проще?

abarnert 11.09.2014 11:40

Эти три строки кода могут удалить дублированный элемент из ArrayList или любой коллекции.

List<Entity> entities = repository.findByUserId(userId);

Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);

Код:

List<String> duplicatList = new ArrayList<String>();
duplicatList = Arrays.asList("AA","BB","CC","DD","DD","EE","AA","FF");
//above AA and DD are duplicate
Set<String> uniqueList = new HashSet<String>(duplicatList);
duplicatList = new ArrayList<String>(uniqueList); //let GC will doing free memory
System.out.println("Removed Duplicate : "+duplicatList);

Примечание: Однозначно будут накладные расходы на память.

Решение @ jonathan-Stafford в порядке. Но это не сохраняет порядок списка.

Если вы хотите сохранить порядок в списке, вы должны использовать это:

public static <T> void removeDuplicate(List <T> list) {
Set <T> set = new HashSet <T>();
List <T> newList = new ArrayList <T>();
for (Iterator <T>iter = list.iterator();    iter.hasNext(); ) {
   Object element = iter.next();
   if (set.add((T) element))
      newList.add((T) element);
   }
   list.clear();
   list.addAll(newList);
}

Это только для завершения ответа. Очень хороший!

Когда вы используете T element = iter.next();, вам не нужны непроверенные приведения типов. Или вы используете for(T element: list) … вместо того, чтобы иметь дело с Iterator вручную.

Holger 04.07.2019 12:58

        List<String> result = new ArrayList<String>();
        Set<String> set = new LinkedHashSet<String>();
        String s = "ravi is a good!boy. But ravi is very nasty fellow.";
        StringTokenizer st = new StringTokenizer(s, " ,. ,!");
        while (st.hasMoreTokens()) {
            result.add(st.nextToken());
        }
         System.out.println(result);
         set.addAll(result);
        result.clear();
        result.addAll(set);
        System.out.println(result);

output:
[ravi, is, a, good, boy, But, ravi, is, very, nasty, fellow]
[ravi, is, a, good, boy, But, very, nasty, fellow]

Потоки Java 8 предоставляют очень простой способ удаления повторяющихся элементов из списка. Используя отдельный метод. Если у нас есть список городов, и мы хотим удалить дубликаты из этого списка, это можно сделать в одной строке -

 List<String> cityList = new ArrayList<>();
 cityList.add("Delhi");
 cityList.add("Mumbai");
 cityList.add("Bangalore");
 cityList.add("Chennai");
 cityList.add("Kolkata");
 cityList.add("Mumbai");

 cityList = cityList.stream().distinct().collect(Collectors.toList());

Как удалить повторяющиеся элементы из Arraylist

public static void main(String[] args){
    ArrayList<Object> al = new ArrayList<Object>();
    al.add("abc");
    al.add('a');
    al.add('b');
    al.add('a');
    al.add("abc");
    al.add(10.3);
    al.add('c');
    al.add(10);
    al.add("abc");
    al.add(10);
    System.out.println("Before Duplicate Remove:"+al);
    for(int i=0;i<al.size();i++){
        for(int j=i+1;j<al.size();j++){
            if (al.get(i).equals(al.get(j))){
                al.remove(j);
                j--;
            }
        }
    }
    System.out.println("After Removing duplicate:"+al);
}

Эта реализация не возвращает ни одного элемента в списке из-за последнего j--

neo7 23.09.2015 12:29

Эта реализация работает очень хорошо. За этим нет никаких проблем, и для этой задачи я использую только один массив. Так что этот ответ полностью хорош. Перед тем, как давать отрицательный отзыв, вы также должны добавить тестовый пример, чтобы каждый мог понять результат.Спасибо. Манаш

Manash Ranjan Dakua 24.09.2015 16:14

Вот мой ответ без использования какой-либо другой структуры данных, такой как set, hashmap и т. д.

public static <T> ArrayList<T> uniquefy(ArrayList<T> myList) {

    ArrayList <T> uniqueArrayList = new ArrayList<T>();
    for (int i = 0; i < myList.size(); i++){
        if (!uniqueArrayList.contains(myList.get(i))){
            uniqueArrayList.add(myList.get(i));
        }
    }

    return uniqueArrayList;
}

«Без использования какой-либо другой структуры данных», кроме другого ArrayList. Что будет очень неэффективно для больших списков.

Holger 04.07.2019 12:59

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

public static void main(String[] args) {
       List<String> l = new ArrayList<String>();
       l.add("A");
       l.add("B");
       l.add("C");
       l.add("A");
       System.out.println("Before removing duplicates: ");
       for (String s : l) {
            System.out.println(s);
       }
       Set<String> set = new HashSet<String>(l);
       List<String> newlist = new ArrayList<String>(set);
       System.out.println("after removing duplicates: ");
       for (String s : newlist) {
            System.out.println(s);
       }
  }

для справки обратитесь по этой ссылке Как удалить дубликаты из ArrayList

Что-то вроде этого работает лучше?

public static void removeDuplicates(ArrayList<String> list) {
    Arraylist<Object> ar     = new Arraylist<Object>();
    Arraylist<Object> tempAR = new Arraylist<Object>();
    while (list.size()>0){
        ar.add(list(0));
        list.removeall(Collections.singleton(list(0)));
    }
    list.addAll(ar);
}

Это должно поддерживать порядок, а также не быть квадратичным по времени выполнения.

«… А также не быть квадратичным по времени выполнения» Конечно, это является, квадратичным по времени выполнения. Это даже хуже, чем другие квадратичные решения.

Holger 04.07.2019 13:02

Если вы хотите использовать стороннюю библиотеку, вы можете использовать метод distinct() в Коллекции Eclipse (ранее GS Collections).

ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
    FastList.newListWith(1, 3, 2),
    integers.distinct());

Преимущество использования distinct() вместо преобразования в набор, а затем обратно в список состоит в том, что distinct() сохраняет порядок исходного списка, сохраняя первое вхождение каждого элемента. Это реализовано с использованием как набора, так и списка.

MutableSet<T> seenSoFar = UnifiedSet.newSet();
int size = list.size();
for (int i = 0; i < size; i++)
{
    T item = list.get(i);
    if (seenSoFar.add(item))
    {
        targetCollection.add(item);
    }
}
return targetCollection;

Если вы не можете преобразовать исходный список в тип Eclipse Collections, вы можете использовать ListAdapter для получения того же API.

MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();

Примечание: Я участник коллекций Eclipse.

ArrayList<String> city=new ArrayList<String>();
city.add("rajkot");
city.add("gondal");
city.add("rajkot");
city.add("gova");
city.add("baroda");
city.add("morbi");
city.add("gova");

HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(city);
city.clear();
city.addAll(hashSet);
Toast.makeText(getActivity(),"" + city.toString(),Toast.LENGTH_SHORT).show();

Предположим, у нас есть список String, например:

List<String> strList = new ArrayList<>(5);
// insert up to five items to list.        

Затем мы можем удалить повторяющиеся элементы несколькими способами.

До Java 8

List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));

Примечание: Если мы хотим сохранить порядок вставки, нам нужно использовать LinkedHashSet вместо HashSet.

Использование гуавы

List<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));

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

List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());

Примечание: В случае, если мы хотим собрать результат в реализация конкретного списка, например LinkedList, тогда мы можем изменить приведенный выше пример как:

List<String> deDupStringList3 = strList.stream().distinct()
                 .collect(Collectors.toCollection(LinkedList::new));

Мы также можем использовать parallelStream в приведенном выше коде, но это может не дать ожидаемых преимуществ в производительности. Проверьте этот вопрос для получения дополнительной информации.

Да, когда я набирал свои предыдущие комментарии, у меня сложилось впечатление, что parallel streams всегда будет обеспечивать лучшую производительность. Но это миф. Позже я узнал, что есть определенные сценарии, в которых следует использовать параллельные потоки. В этом сценарии параллельные потоки не дадут лучшей производительности. и да, в некоторых случаях параллельные потоки могут не дать желаемых результатов. List<String> deDupStringList3 = stringList.stream().map(String::toLowerCase).distinct().coll‌​ect(Collectors.toLis‌​t()); должен быть подходящим решением в этом случае

Diablo 10.08.2018 13:32

Вы также можете сделать это так, сохранив порядок:

// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));

Я думаю, что это лучший способ удалить дубликаты в ArrayList. Определенно рекомендуется. Спасибо @Nenad за ответ.

ByWaleed 13.03.2019 12:59

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

   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) o2).getId()) /*&&
                    ((Contact)o1).getName().equalsIgnoreCase(((Contact)o2).getName())*/) {
                return 0;
            }
            return 1;
        }
    });
    set.addAll(list);

    final List newList = new ArrayList(set);
    return newList;
}

вы можете использовать вложенный цикл в следующем:

ArrayList<Class1> l1 = new ArrayList<Class1>();
ArrayList<Class1> l2 = new ArrayList<Class1>();

        Iterator iterator1 = l1.iterator();
        boolean repeated = false;

        while (iterator1.hasNext())
        {
            Class1 c1 = (Class1) iterator1.next();
            for (Class1 _c: l2) {
                if (_c.getId() == c1.getId())
                    repeated = true;
            }
            if (!repeated)
                l2.add(c1);
        }

Если вы используете тип модели List <T> / ArrayList <T>. Надеюсь, это тебе поможет.

Вот мой код без использования какой-либо другой структуры данных, такой как set или hashmap

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

Сложность времени: O (n): без набора

private static void removeDup(ArrayList<String> listWithDuplicateElements) {
    System.out.println(" Original Duplicate List :" + listWithDuplicateElements);
    List<String> listWithoutDuplicateElements = new ArrayList<>(listWithDuplicateElements.size());

    listWithDuplicateElements.stream().forEach(str -> {
        if (listWithoutDuplicateElements.indexOf(str) == -1) {
            listWithoutDuplicateElements.add(str);
        }
    });     

    System.out.println(" Without Duplicate List :" + listWithoutDuplicateElements);
}

Вызов indexOf на ArrayList внутри forEach - это O (n²).

Holger 04.07.2019 13:03

Это правильный вариант (если вас беспокоят накладные расходы на HashSet.

 public static ArrayList<String> removeDuplicates (ArrayList<String> arrayList){
    if (arrayList.isEmpty()) return null;  //return what makes sense for your app
    Collections.sort(arrayList, String.CASE_INSENSITIVE_ORDER);
    //remove duplicates
    ArrayList <String> arrayList_mod = new ArrayList<>();
    arrayList_mod.add(arrayList.get(0));
    for (int i=1; i<arrayList.size(); i++){
        if (!arrayList.get(i).equals(arrayList.get(i-1))) arrayList_mod.add(arrayList.get(i));
    }
    return arrayList_mod;
}

«Если вас беспокоят накладные расходы HashSet» и не учитываются накладные расходы Collectiors.sort

Holger 04.07.2019 15:34

Set<String> strSet = strList.stream().collect(Collectors.toSet());

Самый простой способ удалить дубликаты.

Не проще Set<String> strSet = new HashSet<>(strList);

Holger 04.07.2019 15:35

Если вы хотите, чтобы ваш список автоматически игнорировал дубликаты и сохранял свой порядок, вы можете создать HashList (встроенный список HashMap).

public static class HashList<T> extends ArrayList<T>{
        private HashMap <T,T> hashMap;
        public HashList(){
            hashMap=new HashMap<>();
        }

        @Override
        public boolean add(T t){
            if (hashMap.get(t)==null){
                hashMap.put(t,t);
                return super.add(t);
            }else return false;
        }

        @Override
        public boolean addAll(Collection<? extends T> c){
            HashList<T> addup=(HashList<T>)c;
            for(int i=0;i<addup.size();i++){
                add(addup.get(i));
            }return true;
        }

    }

Usage Example:

HashList<String> hashlist=new HashList<>();
hashList.add("hello");
hashList.add("hello");
System.out.println(" HashList: "+hashlist);

Попробуйте ListIterator<String> i = hashList.listIterator(); i.add("hello"); i.add("hello");. В качестве альтернативы вы можете использовать hashList.add("a"); hashList.add("b"); hashList.replaceAll(x -> "hello");. И в будущем может быть больше способов противодействовать этому подходу. Вывод состоит в том, что вам не следует пытаться принудительно применять новые контракты путем создания подклассов с классами, не предназначенными для этого. Вы найдете больше по этой теме, когда будете искать правило ООП «Предпочитайте композицию наследованию».

Holger 04.07.2019 15:41

это имеет большой смысл

LiNKeR 27.09.2020 17:45

Другие вопросы по теме