Подтвердить что ты не робот

Удалить дубликаты из ArrayLists

У меня есть ArrayList пользовательских объектов. Я хочу удалить повторяющиеся записи.

Объекты имеют три поля: title, subtitle и id. Если субтитры возникают несколько раз, мне нужен только первый элемент с этим субтитрами (игнорируйте оставшийся объект с этим субтитрами).

4b9b3361

Ответ 1

Вы можете поместить содержимое ArrayList в TreeSet с помощью специального Компаратора, который должен вернуть 0, если оба субтитра совпадают. После этого вы можете конвертировать Set в список и иметь список без "дубликатов". Вот пример для Object, конечно, вы должны использовать правильный класс и логику.

public void removeDuplicates(List<Object> l) {
    // ... the list is already populated
    Set<Object> s = new TreeSet<Object>(new Comparator<Object>() {

        @Override
        public int compare(Object o1, Object o2) {
            // ... compare the two object according to your requirements
            return 0;
        }
    });
            s.addAll(l);
    List<Object> res = Arrays.asList(s.toArray());
}

Ответ 2

List list = (...);

//list may contain duplicates.

//remove duplicates if any
Set setItems = new LinkedHashSet(list);
list.clear();
list.addAll(setItems);

Вам может потребоваться переопределить "equals()", так что 2 элемента считаются равными, если они имеют один и тот же субтитр (например, тит и субтитры?)

Ответ 3

Я бы предложил использовать Set

http://download.oracle.com/javase/6/docs/api/java/util/Set.html

Что по своей природе не может содержать повторяющиеся элементы. Вы можете создать новый набор из оригинального ArrayList, используя

Set myset = new HashSet(myArrayList);

В качестве альтернативы просто используйте Set с самого начала и не используйте ArrayList, поскольку он не выполняет требуемую функцию.

Ответ 4

List<Item> result = new ArrayList<Item>();
Set<String> titles = new HashSet<String>();

for(Item item : originalList) {
    if(titles.add(item.getTitle()) {
        result.add(item);
    }
}

add() из Set возвращает false если элемент уже существует.

Ответ 5

Вы можете использовать решение O (n ^ 2): используйте list.iterator() для повторной сортировки списка один раз и на каждой итерации повторите его повтор, чтобы проверить, есть ли дубликаты. Если есть - вызов iterator.remove(). Вариант этого заключается в использовании guava Iterables.filter(list, predicate), где ваша логика фильтрации находится в предикате.

Другой способ (возможно, лучше) - определить методы equals(..) и hashCode(..) для обработки вашей пользовательской логики равенства, а затем просто построить new HashSet(list). Это очистит дубликаты.

Ответ 6

Если я правильно понял, у вас есть ArrayList<Custom>, позвоните ему list. В вашем классе Custom есть поле субтитров, скажем, с помощью метода getSubtitle(), который возвращает String. Вы хотите сохранить только первый уникальный субтитр и удалить оставшиеся дубликаты. Вот как вы можете это сделать:

Set<String> subtitles = new HashSet<String>();
for (Iterator<Custom> it = list.iterator(); it.hasNext(); ) {
    if (!subtitles.add(it.next().getSubtitle())) {
        it.remove();
    }
}

Ответ 7

Удаляет любые дубликаты в коллекции, сохраняя заказ, если это упорядоченная коллекция. Достаточно эффективно для большинства случаев.

public static <I, T extends Collection<I>> T removeDuplicates(T collection)
{
    Set<I> setItems = new LinkedHashSet<I>(collection);
    collection.clear();
    collection.addAll(setItems);

    return collection;
}

Ответ 8

Используйте Collections.sort() для сортировки и использования простого цикла для улавливания удвоений, например:

Collections.sort(myList);
A previous = null;
for (A elem: myList) {
    if (elem.compareTo(previous) == 0) continue;
    previous = elem;

    [... process unique element ...]
}

Это предполагает, что вы реализуете Comparable в своем типе A.

Ответ 9

Обновление для Java8:

Используя потоки Java8, вы также можете сделать довольно тривиально.

ArrayList<String> deduped;
deduped = yourArrayList.stream()
             .distinct()
             .collect(Collectors.toCollection(ArrayList::new));

Это также имеет преимущество перед тем, как ArrayList → Set → ArrayList поддерживает порядок.

Ответ 10

private static List<Integer> removeDuplicates(List<Integer> list) {
    ArrayList<Integer> uniqueList = new ArrayList<Integer>();
    for (Integer i : list) {
        if (!inArray(i, uniqueList)) {
            uniqueList.add(i);
        }
    }

    return uniqueList;
}

private static boolean inArray(Integer i, List<Integer> list) {
    for (Integer integer : list) {
        if (integer == i) {
            return true;
        }
    }

    return false;
}

Ответ 11

List<YourObject> all = ******** // this is the object that you have already  and filled it.
List<YourObject> noRepeat= new ArrayList<YourObject>();

for (YourObject al: all) {
    boolean isPresent = false;
    // check if the current objects subtitle already exists in noRepeat
    for (YourObject nr : noRepeat) {
        if (nr.getName().equals(al.getName()) {
            isFound = true;//yes we have already
            break;
        }
    }

    if (!isPresent)
        noRepeat.add(al); // we are adding if we don't have already
}

взять один новый объект ArrayList того же типа
один за другим добавьте все старые элементы arraylists в этот новый объект arraylist, но перед добавлением каждого объекта проверьте в новом arraylist, что если есть какой-либо объект с тем же субтитром. Если новый arraylist содержит такие субтитры, не добавляйте его. в противном случае добавьте это

Ответ 12

Решение зависит от обстоятельств.

Если у вас мало данных, перейдите в Set Set<T> unique = new HashSet<>(yourList); (используйте LinkedHashSet, если вы заботитесь о заказе. Он создает новую коллекцию, но обычно это не проблема.

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

List<Integer> numbers =
    new ArrayList<>(asList(1, 1, 2, 1, 2, 3, 5));

System.out.println("Numbers: " + numbers);
ListIterator<Integer> it = numbers.listIterator();
while (it.hasNext()) {
    int i = it.nextIndex();
    Integer current = it.next();
    for (int j = 0; j < i; ++j) {
        if (current.equals(numbers.get(j))) {
            it.remove();
            break;
        }
    }
}
System.out.println("Unique: " + numbers);

Он работает в O (n ^ 2), но он работает. Подобная реализация, но проще, когда сортировка списка - работает в O (n) времени. Обе версии объясняются в Farenda: удалить дубликаты из списка - различные реализации.

Ответ 13

Другой метод, использующий потоки Java 8, вы также можете сделать довольно круто:

List<Customer> CustomerLists;
List<Customer> unique = CustomerLists.stream().collect(collectingAndThen(
        toCollection(() -> new TreeSet<>(comparingLong(Customer::getId))),
        ArrayList::new));

Ответ 14

В Java 8 вы также можете сделать что-то вроде этого:

yourList.stream().collect(
     Collectors.toMap(
         obj -> obj.getSubtitle(),
         Function.identity(), 
         (o1,o2) -> o1))
    .values();

Хитрость заключается в том, чтобы собрать поток для отображения и предоставить лямбда-преобразователь коллизий ключей ((o1,o2) → o1), который всегда возвращает свой первый параметр. В результате получается коллекция, а не список, но вы можете легко преобразовать ее в список:

new ArrayList(resultCollection);