2013-05-22 2 views
5

У меня есть ArrayList с пользовательскими объектами. Я хочу удалить дубликаты из массива в зависимости от свойства имени настраиваемого объекта. Я попытался выполнить это с помощью Set person = new TreeSet(); но он не работает. Я думаю, потому что набор сравнивает адреса или что-то еще, чем свойство name. Поэтому я теперь пытаюсь использовать итератор, который также не удаляет дубликаты. Это то, что я получил;удаление элемента из arraylist в зависимости от свойства настраиваемого объекта

ArrayList<Person> people = new ArrayList<Person>(); 
Iterator<Person> iterator = people.iterator(); 
while (iterator.hasNext()) { 
    Person person = iterator.next(); 

    if (person.getName().equals(iterator.next().getName())) { 
     iterator.remove(); 
    } 
} 
for (Person person : people) { 
    System.out.println(person.getName()); 
} 

ArrayList не изменяется, хотя я вижу дубликаты в нем. Мне нужна помощь. Благодаря!

+0

ли человек реализует равные и хэш-коды? Набор должен работать, если вы реализуете equals и hashcode – user1121883

+0

Как правило, плохая идея для удаления во время итерации ... возможно, лучше создать отдельный список и фильтровать (добавлять) намеченные результаты в новый список. – vikingsteve

+0

Почему это плохая идея удалить во время итерации? Это отличная идея, если получить доступ к ней только из одного потока.Если у вас нет других проблем – tgkprog

ответ

10

У меня была такая же ситуация, и я придумал это решение для использования SortedSet. В этом случае те объекты, которые заставляют компаратор сравнения возвращать 0, будут вставлены один раз в Set.

Вот пример:

SortedSet<Person> persons = new TreeSet<Person>(new Comparator<Person>() { 
    @Override 
    public int compare(Person arg0, Person arg1) { 
     return arg0.getName().compareTo(arg1.getName()); 
    } 
}); 

А теперь, если вы вставляете Person в свой persons, не будут вставлены дубликаты (на основе их name собственности).

Таким образом, вы можете использовать итератор над своим list<Person> и вставить каждый его элемент в свой набор persons и быть уверенным, что у вас не будет дубликатов. Таким образом, остальное будет выглядеть так:

Iterator<Person> iterator = people.iterator(); 
while(iterator.hasNext()) { 
    persons.add(iterator.next()); 
} 
people.clear(); 
people.addAll(persons); //Now, your people does not contain duplicate names 
+0

Я реализовал 'Comparable' и' Comparator' в классе Person, и он отлично работает. Большое спасибо – madcoderz

+0

Быстро, не так ли? Добро пожаловать :) –

+0

Эй, я сделал это и успешно работал. Но мой исходный список с повторяющимися значениями также изменяется на отсортированное значение. Не знаю, почему. Пожалуйста, помогите мне. – Arun

2

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

Один из вариантов заключается в том, чтобы определить новый список и заполнить его элементами, как только вы подтвердите, что они не дубликаты. Это позволяет избежать итераций вложенности.

И, наконец, другим вариантом было бы определить метод equals, который сравнивается на основе этого свойства и бросает объекты в Set. Не забудьте также hashCode.

+0

* сравнивайте объекты со следующим объектом * Кроме того, следующий объект не будет сравниваться с третьим объектом. Четвертый объект не будет сравниваться с пятым объектом .... – johnchen902

0

Каждый раз, когда вы пишете .next(), итерация выполняется на 1 шаг вперед. Итак, скажем, у вас 10 человек в вашем списке. Вы выбираете 1-го человека и проверяете следующего человека, используя iterator.next(). Хотя вы получаете второго человека, итератор теперь находится у человека 2. Поэтому в следующем прогоне 3-го человека выбирают и сравнивают с 4-м человеком.

Что вы должны сделать, выберите 1 человека и сравните его имя с именами всех 10 человек в списке, а затем удалите все экземпляры дубликатов объектов из списка.

2

Не удаляется, потому что вы только сравниваете каждый элемент со следующим элементом. Вы можете сохранить имена в HashSet, который может содержать только 1 из каждой строки, а затем удалить элемент, если его имя уже установлено.

HashSet<String> seen = new HashSet<String>(); 
while (iterator.hasNext()) { 
    Person p = iterator.next(); 
    if (seen.contains(p.getName())) { 
      iterator.remove(); 
    } else { 
      seen.add(p.getName()); 
    } 
}