Reputation: 61
Hi I'm doing homework for my school and am trying to remove instance from two-dimensional TreeMap<String, TreeMap<Date, Integer>
and keep it the same structure
my function that is supposed to do that :
public void vyhodExpirovane(){
Date now = new Date(System.currentTimeMillis());
TreeMap<Date, Integer> produkt;
System.out.println(now);
for (String name: obsah.keySet()){
produkt = obsah.get(name);
System.out.print(name + " pocet roznych" + produkt.size() + " datum");
for (Date d: produkt.keySet()){
System.out.println( d + " pocet:" + produkt.get(d));
if (d.before(now)) {
obsah.get(name).remove(d);
}
}
}
}
and my map looks like this
<cheese , <Mar 10 10:58:02 CET 2015, 1>>
<apple , <Mar 10 10:58:02 CET 2015, 1> <Mar 10 11:58:02 CET 2015, 2>>
when the remove from my function removes first occurance of apple and is supposed to go to second it crashes with:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.TreeMap$PrivateEntryIterator.nextEntry(Unknown Source)
at java.util.TreeMap$KeyIterator.next(Unknown Source)
at Chladnicka.vyhodExpirovane(Chladnicka.java:126)
at MainClass.main(MainClass.java:46)
which is on the inner for loop (for (Date d: produkt.keySet()))
any idea why is it crashing?
Upvotes: 0
Views: 593
Reputation: 13713
It is crashing because you try to remove an element while you implicitly iterating your tree map (as it affects the internal iteration index). You should keep the keys you want to remove in a temporary data structure and remove the keys after iterating the tree map.
Upvotes: 0
Reputation: 178461
for (Date d: produkt.keySet()){
System.out.println( d + " pocet:" + produkt.get(d));
if (d.before(now)) {
obsah.get(name).remove(d);
}
}
You cannot remove an element from a collection while iterating it, this is causing the error.
You should use the fact that you have TreeMap
, that maintains order of the elements, so your items are already sorted according to Date
!
You can use this fact to simply your code and use the tailMap()
functionality and get a submap that include only keys with higher dates already.
This can be done instead of modifying your existing map - create a new one using the mentioned method, and put it in the original tree.
obsah.put(name, obsah.get(name).tailMap(now))
Note that modifying a value (of the outer map) while iterating does not cause this exception.
Upvotes: 2
Reputation: 14338
Use Iterator
instead of inner loop:
Iterator<Map.Entry<Date, Integer>> i = produkt.entrySet().iterator();
Map.Entry<Date, Integer> e;
while (i.hasNext() && (e = i.next()) != null) {
if (e.getKey().before(now)) {
i.remove();
}
}
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html#entrySet%28%29
Upvotes: 0