У меня есть ArrayList пользовательских объектов. Я хочу удалить повторяющиеся записи.
Объекты имеют три поля: title, subtitle и id. Если субтитры возникают несколько раз, мне нужен только первый элемент с этим субтитрами (игнорируйте оставшийся объект с этим субтитрами).
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, если элемент уже существует.
Использовать 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.
Вы можете использовать решение O (n ^ 2): Используйте list.iterator() для повторной сортировки списка один раз и на каждой итерации повторите его повтор, чтобы проверить, есть ли дубликаты. Если есть - вызов iterator.remove(). Вариант этого заключается в использовании guava's Iterables.filter(list, predicate), где ваша логика фильтрации находится в предикате.
Другой способ (возможно, лучше) - определить методы equals(..) и hashCode(..) для обработки ваших пользовательских логику равенства, а затем просто построить a new HashSet(list). Это очистит дубликаты.
Я бы предложил использовать Set
http://download.oracle.com/javase/6/docs/api/java/util/Set.html
, который его характер не может содержать повторяющиеся элементы. Вы можете создать новый набор из оригинального ArrayList с помощью
Set myset = new HashSet(myArrayList);
. Или просто используйте Set с самого начала и не используйте ArrayList, поскольку он не выполняет требуемую функцию. [ ! d4]
Обновление для Java8:
Используя потоки Java8, вы также можете сделать довольно тривиально.
ArrayList<String> deduped;
deduped = yourArrayList.stream()
.distinct()
.collect(Collectors.toCollection(ArrayList::new));
Это также имеет преимущество перед тем, как ArrayList → Set → ArrayList поддерживает упорядочение.
Удаляет любые дубликаты в коллекции, сохраняя заказ, если он является упорядоченной коллекцией. Достаточно эффективно для большинства случаев.
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;
}
В Java 8 вы также можете сделать что-то вроде этого:
yourList.stream().collect(
Collectors.toMap(
obj -> obj.getSubtitle(),
Function.identity(),
(o1,o2) -> o1)
.values();
Трюк состоит в том, чтобы собирать поток для сопоставления и предоставлять ключевой коллизионный преобразователь лямбда ((o1,o2) -> o1), который всегда возвращает свой первый параметр , Результатом является коллекция, а не список, но вы можете легко преобразовать ее в список:
new ArrayList(resultCollection);
Решение зависит от обстоятельств.
Если у вас мало данных, переходите к 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: удаление дубликатов из списка - различные реализации .
List list = (...);
//list may contain duplicates.
//remove duplicates if any
Set setItems = new LinkedHashSet(list);
list.clear();
list.addAll(setItems);
Возможно, вам придется переопределить «equals ()», так что 2 элемента считаются равными, если они имеют один и тот же субтитр (например, тит и субтитры?)
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, если есть какой-либо объект с тем же subtitle.if новый arraylist содержит такие субтитры, не добавляйте его. иначе добавьте его Если я правильно понял, у вас есть 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();
}
}
Другой метод Использование потоков Java8 также можно сделать довольно круто
Список списков клиентов
Список unique = CustomerLists.stream (). collect (collectAndThen (toCollection (() - > new TreeSet & lt;> (compareLong (Customer :: getId))), ArrayList :: new));