2

I want to delete duplicate elements and therefore iterate through a ArrayList and compare two consecutive elements. (Persons are comparable)

ArrayList<Person> persons = getHelper().findAllPersons();
Collections.sort(persons);
ListIterator<Person> it = persons.listIterator();
if(it.hasNext()) {
    Person tmp = it.next();
    while(it.hasNext()) {
        if(tmp.getLastDiscovered() == it.next().getLastDiscovered()) {
            getHelper().delete(tmp);
        }
    tmp = it.next();
    }
}

I get a NoSuchElementException at tmp = it.next();

Shouldn't the while(it.hasNext()) prevent that?

3
  • final Set<Person> unqiuePeople = new TreeSet<Person>(persons) will do what you want in one line. Commented May 10, 2013 at 14:53
  • With the appropriately defined comparator/equals() method Commented May 10, 2013 at 14:57
  • @BrianAgnew given that the OP is already using Collections.sort to order the items I assume this is already defined. Commented May 10, 2013 at 15:01

4 Answers 4

5

The problem is you are calling it.next() twice, which will advance the iterator two times.

You should store the value to avoid repeating the side-effect.

    Person person = it.next();
    if (tmp.getLastDiscovered() == person.getLastDiscovered()) {
        getHelper().delete(tmp);
    }
    tmp = person;

Alternatively, you could use the for-each loop to avoid needing to interact with the iterators (I assume all Person are not null):

Person tmp = null;
for (Person person : persons) {
    if (tmp != null && tmp.getLastDiscovered() == person.getLastDiscovered()) {
        getHelper().delete(tmp);
    }
    tmp = person;
}
Sign up to request clarification or add additional context in comments.

Comments

1

You're calling it.next() twice (potentially) for each it.hasNext() call, hence your error.

If you want to remove duplicates, why not just populate a TreeSet (providing the appropriate Comparator) with your list ? The semantics of a Set are such that you'll have a distinct set of elements.

Comments

0

If you're using JDK 1.5.0 or later (which you most likely are, since it was released in 2004), you can use a foreach loop to obviate the iterator altogether, greatly simplifying the code.

ArrayList<Person> persons = getHelper().findAllPersons();
Collections.sort(persons);
for (Person person : persons) {
    if(tmp.getLastDiscovered() == person.getLastDiscovered()) {
        getHelper().delete(tmp);
    }
}

Comments

0
while(it.hasNext()) {
        if(tmp.getLastDiscovered() == it.next().getLastDiscovered()) {
            getHelper().delete(tmp);
        }

After that 'while' you are coming to end of the list. Then when it hasn't got next value, you are calling the line below.

tmp = it.next();

That gives you an exception.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.