Как проверить, совпадают ли два объекта в ArrayList? [Дубликат]

Вы должны использовать обозначение квадратной скобки, когда -

  1. Имя свойства - это номер. var ob = { 1: 'One', 7 : 'Seven' }
    ob.7 // SyntaxError ob[7] // "Seven"
  2. Имя свойства имеет специальный символ. var ob = { 'This is one': 1, 'This is seven': 7, }
    ob.'This is one' // SyntaxError ob['This is one'] // 1
  3. Имя свойства присваивается переменной, и вы хотите получить доступ к значению свойства этой переменной. var ob = { 'One': 1, 'Seven': 7, } var _Seven = 'Seven'; ob._Seven // undefined ob[_Seven] // 7
78
задан 19 February 2009 в 02:14
поделиться

13 ответов

Простейший: сбрасывает всю коллекцию в Set (используя конструктор Set (Collection) или Set.addAll), а затем посмотрите, имеет ли Set тот же размер, что и ArrayList.

List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);

if(set.size() < list.size()){
    /* There are duplicates */
}

Обновить : Если я правильно понимаю ваш вопрос, у вас есть 2d-массив Block, как в

Block table [] [];

, и вы хотите определить,

В этом случае я мог бы сделать следующее, считая, что Block реализует «equals» и «hashCode» правильно:

for (Block[] row : table) {
   Set set = new HashSet<Block>(); 
   for (Block cell : row) {
      set.add(cell);
   }
   if (set.size() < 6) { //has duplicate
   }
}

Я не на 100% уверен в синтаксисе, поэтому было бы безопаснее записать его как

for (int i = 0; i < 6; i++) {
   Set set = new HashSet<Block>(); 
   for (int j = 0; j < 6; j++)
    set.add(table[i][j]);

...

148
ответ дан OscarRyz 26 August 2018 в 07:58
поделиться
  • 1
    Обязательно реализуйте hashCode / equals. – jon077 18 February 2009 в 22:27
  • 2
    Или даже немного проще: оберните его при создании набора, например. новый HashSet (список), вместо использования addAll. – Fabian Steeg 18 February 2009 в 22:28
  • 3
    @ jon077: Это зависит от вашего определения «дубликат». – Michael Myers♦ 18 February 2009 в 22:29
  • 4
    Будет ли процесс обнаружения элементов в 2D-массиве одинаковым? Например, проверка с массива [0] [0] на массив [0] [6] («строка») ..? Большое спасибо, Терри – user 18 February 2009 в 22:29
  • 5
    Каждый объект массива имеет целое значение. Под «дублированием» объект будет иметь одинаковое целочисленное значение. – user 18 February 2009 в 22:30

Улучшен код с использованием возвращаемого значения Set#add вместо сравнения размера списка и набора.

public static <T> boolean hasDuplicate(Iterable<T> all) {
    Set<T> set = new HashSet<T>();
    // Set#add returns false if the set does not change, which
    // indicates that a duplicate element has been added.
    for (T each: all) if (!set.add(each)) return true;
    return false;
}
55
ответ дан akuhn 26 August 2018 в 07:58
поделиться
  • 1
    Было бы лучше сказать HashSet, сколько места выделить: Set<T> set = new HashSet<T>(list.size());? Учитывая параметр «Список», я считаю, что он более эффективен, если в списке нет общих дубликатов. – Paul Jackson 28 April 2014 в 23:50
  • 2
    @PaulJackson Размер, основанный на полном списке, вероятно, будет полезен. Однако, если общий случай заключается в том, чтобы найти дубликат раньше, пространство было потрачено впустую. Также даже размер HashSet до размера списка приведет к изменению размера при прохождении по всему списку из-за базового коэффициента загрузки хэш-структуры. – Jay Anderson 22 March 2018 в 22:19
  • 3
    Если вы не столкнетесь с реальными проблемами со временем выполнения или пространством, я бы не стал точно таким же, как ваш код. Преждевременной оптимизации лучше избегать. – akuhn 22 March 2018 в 23:51
    String tempVal = null;
    for (int i = 0; i < l.size(); i++) {
        tempVal = l.get(i); //take the ith object out of list
        while (l.contains(tempVal)) {
            l.remove(tempVal); //remove all matching entries
        }
        l.add(tempVal); //at last add one entry
    }

Примечание: это будет иметь большую производительность, хотя, поскольку элементы удаляются из начала списка. Чтобы решить эту проблему, у нас есть два варианта. 1) итерация в обратном порядке и удаление элементов. 2) Используйте LinkedList вместо ArrayList. Из-за необъективных вопросов, заданных в интервью, чтобы удалить дубликаты из списка без использования какой-либо другой коллекции, приведенным выше примером является ответ. В реальном мире, хотя, если я должен достигнуть этого, я положу элементы из списка в Set, просто!

0
ответ дан Amitesh Jha 26 August 2018 в 07:58
поделиться

Проще говоря: 1) убедитесь, что все элементы сопоставимы. 2) Сортируйте массив. 2) итерации по массиву и поиска дубликатов

2
ответ дан Antonio 26 August 2018 в 07:58
поделиться
/**
     * Method to detect presence of duplicates in a generic list. 
     * Depends on the equals method of the concrete type. make sure to override it as required.
     */
    public static <T> boolean hasDuplicates(List<T> list){
        int count = list.size();
        T t1,t2;

        for(int i=0;i<count;i++){
            t1 = list.get(i);
            for(int j=i+1;j<count;j++){
                t2 = list.get(j);
                if(t2.equals(t1)){
                    return true;
                }
            }
        }
        return false;
    }

Пример конкретного класса, который переопределил equals():

public class Reminder{
    private long id;
    private int hour;
    private int minute;

    public Reminder(long id, int hour, int minute){
        this.id = id;
        this.hour = hour;
        this.minute = minute;
    }

    @Override
    public boolean equals(Object other){
        if(other == null) return false;
        if(this.getClass() != other.getClass()) return false;
        Reminder otherReminder = (Reminder) other;
        if(this.hour != otherReminder.hour) return false;
        if(this.minute != otherReminder.minute) return false;

        return true;
    }
}
0
ответ дан faizal 26 August 2018 в 07:58
поделиться

Улучшенный код для возврата повторяющихся элементов

  • Может найти дубликаты в коллекции
  • вернуть набор дубликатов
  • Уникальные элементы могут быть получены из набора

public static <T> List getDuplicate(Collection<T> list) {

    final List<T> duplicatedObjects = new ArrayList<T>();
    Set<T> set = new HashSet<T>() {
    @Override
    public boolean add(T e) {
        if (contains(e)) {
            duplicatedObjects.add(e);
        }
        return super.add(e);
    }
    };
   for (T t : list) {
        set.add(t);
    }
    return duplicatedObjects;
}


public static <T> boolean hasDuplicate(Collection<T> list) {
    if (getDuplicate(list).isEmpty())
        return false;
    return true;
}
9
ответ дан Jason Plank 26 August 2018 в 07:58
поделиться
  • 1
    Это довольно здорово. у вас есть некорректный код, и, возможно, это не самый оптимальный способ, но ваш подход полностью потрясает! (и он отлично работает) – Jules Colle 3 October 2012 в 20:23

Мне нужно было выполнить аналогичную операцию для Stream, но не удалось найти хороший пример. Вот что я придумал.

public static <T> boolean areUnique(final Stream<T> stream) {
    final Set<T> seen = new HashSet<>();
    return stream.allMatch(seen::add);
}

Это имеет преимущество короткого замыкания, когда дубликаты найдены раньше, чем обрабатывать весь поток и не намного сложнее, чем просто положить все в a Set и проверить размер. Таким образом, этот случай будет примерно таким:

List<T> list = ...
boolean allDistinct = areUnique(list.stream());
6
ответ дан Jay Anderson 26 August 2018 в 07:58
поделиться

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

15
ответ дан matt b 26 August 2018 в 07:58
поделиться
  • 1
    Обязательно реализуйте hashCode / equals :) – jon077 18 February 2009 в 22:36
  • 2
    @ jon077: Не обязательно, как я только что сказал. – Michael Myers♦ 18 February 2009 в 22:38
  • 3
    Однако использование набора не выполняет обнаружение дубликатов. Он просто мешает им. Если, конечно, вы не проверяете результат метода добавления, как указано в @akuhn выше. – mcallahan 20 October 2017 в 17:51
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class FindDuplicateInArrayList {

    public static void main(String[] args) {

        Set<String> uniqueSet = new HashSet<String>();
        List<String> dupesList = new ArrayList<String>();
        for (String a : args) {
            if (uniqueSet.contains(a))
                dupesList.add(a);
            else
                uniqueSet.add(a);
        }
        System.out.println(uniqueSet.size() + " distinct words: " + uniqueSet);
        System.out.println(dupesList.size() + " dupesList words: " + dupesList);
    }
}
0
ответ дан Pang 26 August 2018 в 07:58
поделиться

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

 public Set<?> findDuplicatesInList(List<?> beanList) {
    System.out.println("findDuplicatesInList::"+beanList);
    Set<Object> duplicateRowSet=null;
    duplicateRowSet=new LinkedHashSet<Object>();
            for(int i=0;i<beanList.size();i++){
                Object superString=beanList.get(i);
                System.out.println("findDuplicatesInList::superString::"+superString);
                for(int j=0;j<beanList.size();j++){
                    if(i!=j){
                         Object subString=beanList.get(j);
                         System.out.println("findDuplicatesInList::subString::"+subString);
                         if(superString.equals(subString)){
                             duplicateRowSet.add(beanList.get(j));
                         }
                    }
                }
            }
            System.out.println("findDuplicatesInList::duplicationSet::"+duplicateRowSet);
        return duplicateRowSet;
  }
2
ответ дан Rakesh Sabbani 26 August 2018 в 07:58
поделиться

лучший способ справиться с этой проблемой - использовать HashSet:

ArrayList<String> listGroupCode = new ArrayList<>();
listGroupCode.add("A");
listGroupCode.add("A");
listGroupCode.add("B");
listGroupCode.add("C");
HashSet<String> set = new HashSet<>(listGroupCode);
ArrayList<String> result = new ArrayList<>(set);

Просто напечатать результирующий арифметик и увидеть результат без дубликатов:)

0
ответ дан Roy Wasse 26 August 2018 в 07:58
поделиться
    ArrayList<String> withDuplicates = new ArrayList<>();
    withDuplicates.add("1");
    withDuplicates.add("2");
    withDuplicates.add("1");
    withDuplicates.add("3");
    HashSet<String> set = new HashSet<>(withDuplicates);
    ArrayList<String> withoutDupicates = new ArrayList<>(set);

    ArrayList<String> duplicates = new ArrayList<String>();

    Iterator<String> dupIter = withDuplicates.iterator();
    while(dupIter.hasNext())
    {
    String dupWord = dupIter.next();
    if(withDuplicates.contains(dupWord))
    {
        duplicates.add(dupWord);
    }else{
        withoutDupicates.add(dupWord);
    }
    }
  System.out.println(duplicates);
  System.out.println(withoutDupicates);
0
ответ дан sivaram 26 August 2018 в 07:58
поделиться
  • 1
    Добавьте некоторое объяснение с ответом, как этот ответ помогает OP в устранении текущей проблемы – ρяσѕρєя K 4 July 2017 в 04:44

Если ваши элементы каким-то образом сопоставимы (тот факт, что порядок имеет какой-либо реальный смысл, равнодушен - он просто должен соответствовать вашему определению равенства), самое быстрое решение для удаления дубликатов собирается сортировать список (0 ( n log (n))), затем выполнить один проход и искать повторяющиеся элементы (то есть равные элементы, которые следуют друг за другом) (это O (n)).

Общая сложность будет O (n log (n)), что примерно совпадает с тем, что вы получите с помощью Set (n times long (n)), но с гораздо меньшей константой. Это связано с тем, что константа в sort / dedup возникает из-за стоимости сравнения элементов, тогда как стоимость из набора, скорее всего, будет результатом вычисления хеша, плюс одно (возможно, несколько) хеш-сравнений. Если вы используете реализацию Set на основе хэша, то есть потому, что Tree based даст вам O (n log² (n)), что еще хуже.

Как я понимаю, однако вам не нужно удалить дубликаты, а просто проверить их существование. Таким образом, вы должны вручную скомпилировать алгоритм сортировки слияния или кучи в своем массиве, который просто выдает возвращаемое значение true (т. Е. «Есть дубликат»), если ваш компаратор возвращает 0 и в противном случае завершает сортировку и проходит проверку отсортированного массива для повторов , В случае слияния или кучи, действительно, когда сортировка будет завершена, вы будете сравнивать каждую повторяющуюся пару, если оба элемента уже не находятся в их конечных положениях (что маловероятно). Таким образом, алгоритм выборочной сортировки должен дать огромное повышение производительности (я должен был бы это доказать, но, я думаю, алгоритм с измененным алгоритмом должен быть в O (log (n)) на равномерно случайных данных)

8
ответ дан Varkhan 26 August 2018 в 07:58
поделиться
  • 1
    В этом случае n равно 6, поэтому я не буду тратить много времени на детали реализации, но я сохраню ваше представление о специальной сортировке кучи, если мне когда-нибудь понадобится сделать что-то подобное. – Paul Tomblin 19 February 2009 в 02:25
  • 2
    Я не понимаю третий абзац. Mergesort и heapsort - это O (nlog (n)), а не O (log (n)) при написании; даже если вы выходите, как только вы идентифицируете дубликат, который все еще не меняет вашу временную сложность ... – ChaimKut 6 May 2012 в 15:33
Другие вопросы по тегам:

Похожие вопросы: