1

I have an iterator inside a thread and I am trying to remove the duplicate records.

 Runnable readingThread = new Runnable() {
        @Override
        public void run() {

            Iterator<Demand> iterator = null;
            for (iterator = demandListFromFile.iterator(); iterator.hasNext();) {
                Demand demand = iterator.next();

                /**
                 * Find and assign the Item ID
                 */
                if (itemListHashMap.containsValue(demand.getItem().getItemName())) {
                    demand.getItem().setIditem(itemListHashMapReversed.get(demand.getItem().getItemName()));

                } else {
                    unavailableItemsList.add(demand.getItem().getItemName());
                }


                /**
                 * Find and remove duplicate records
                 */
                for (Map.Entry<Date, String> entry : demandListHashMap.entries()) {

                    if (demand.getDueDate().equals(entry.getKey()) && demand.getItem().getItemName().equals(entry.getValue())) {

                        iterator.remove();
                    }

                }

            }

        }

After removing few items, the iterator.remove throws the below exception

Exception in thread "Thread-0" java.lang.IllegalStateException
    at java.base/java.util.ArrayList$Itr.remove(ArrayList.java:1009)
    at com.xxx.xxx.ui.Home$7.run(Home.java:455)
    at java.base/java.lang.Thread.run(Thread.java:834)

Why is this happening? Please note I have removed the code after and before the iterator, to keep this post short.

3
  • 1
    Just 'cos your app. has a GUI, doesn't mean it's appropriate to add the swing tag. Keep the tags relevant to the problem. Commented Feb 1, 2020 at 14:48
  • 1
    Are yo trying to remove from the iterator (iterator.remove();) ? or from the collection ? For more help please post minimal reproducible example and mark the line that throws the exception. Commented Feb 1, 2020 at 14:59
  • Since the .remove() is being called within a nested loop, could you be calling it more than once? If so, this will result in the exception's being thrown. You should break out of the loop immediately after calling remove. And yeah, @c0der is right -- you need to create and post a minimal reproducible example to adequately allow the queastion to be answered without guessing. Commented Feb 1, 2020 at 15:14

2 Answers 2

9

Iterator.java remove method:

    @throws IllegalStateException if the next method has not
              yet been called, or the remove method has already
              been called after the last call to the next method
    void remove() {
        ..
    }

The problem is in your for loop "Find and remove duplicate records" you may be calling iterator.remove more than once. The remove method removes the current element you are viewing so you can only call it once per using next(). To ensure it's called only once, add a break statement below iterator.remove();

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, this was my thought as well. 1+
0

The reason stated by @CausingUnderflowsEverywhere was absolutely right.

Adding to that, after seeing the implementation, iterator.remove element calls the ArrayList.remove method internally.

ArrayList is maintaining the index of the last element returned in a variable called lastRet Once the element is removed, the ArrayList.remove method set the lastRet to -1.

And the very first check of ArrayList.remove is

if (lastRet < 0)
{
     throw new IllegalStateException();
}

This is what happens in the background.

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.