Удалить дубликаты из ArrayLists
У меня есть ArrayList пользовательских объектов. Я хочу удалить повторяющиеся записи.
Объекты имеют три поля: title, subtitle
и id
. Если субтитры возникают несколько раз, мне нужен только первый элемент с этим субтитрами (игнорируйте оставшийся объект с этим субтитрами).
Ответы
Ответ 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);