3

I got a problem with my function. That code works pretty fine for me, it removes an item when the boolean attribute is true:

private void doRemoveAusgefallenePlaene(Collection<CarPlan> pAllCarPlan) {
for (Iterator<CarPlan> lCarPlanIterator = pAllCarPlan.iterator(); lCarPlanIterator.hasNext();) {
  CarPlan lCarPlan = lCarPlanIterator.next();
  if (!lCarPlan.isAusfall()) {
    lCarPlanIterator.remove();
  }
}
}

My hope was to use the function for objects of type CarPlan as well as ShipPlan(both implements the interface Plan).

private void doRemoveAusgefallenePlaene(Collection<? extends Plan> pAllPlan) {
  for (Iterator<? extends Plan> lIterator = pAllPlan.iterator(); lPlanIterator.hasNext();) {
    Plan lPlan = lPlanIterator.next();
    if (!lPlan.isAusfall()) {
      lPlanIterator.remove();
    }
  }
}

Now I can call the function with Collections of Type CarPlan and ShipPlan

doRemoveAusgefallenePlaene(pAllCarPlan);
doRemoveAusgefallenePlaene(pAllShipPlan);

and the code compiles without problems. Unfortunately at execution time a UnsupportedOperationException is thrown in line

lPlanIterator.remove();

I think I understand something wrong by declaring Collection<? extends Plan>. Knows anyone the problem?

-- UPDATE -- for those who are interested in one possible solution:

final List<CarPlan> lAllCarPlan = new ArrayList<CarPlan>(pAllCarPlan);
doRemoveAusgefallenePlaene(lAllCarPlan);

works great with ShipPlan and CarPlan.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
nano_nano
  • 12,351
  • 8
  • 55
  • 83
  • Have you tried just using a `Collection'? – Evan Knowles Mar 15 '13 at 13:50
  • yes but then I am not able to pass Collections of type ShipPlan or CarPlan. The function I descripted is part of the businesscase doSomethingWithShip and doSomethingWithCar. I dont have the interface variable and it is not allowed to make a type cast. – nano_nano Mar 15 '13 at 13:55

2 Answers2

6

You are probably iterating over an unmodifiable collection, whose iterator will thus not support the remove operation.

Examples of unmodifiable collections include those produced by Collections.unmodifiableXX(). The list returned by Arrays.asList() is not completely unmodifiable (you can set an element at a specific index), but does not support add or remove operations since it is backed directly by the array you pass in.

From the Javadoc for remove():

Throws: UnsupportedOperationException - if the remove operation is not supported by this iterator

You need to look at what you're passing in, and make sure that the structure of the collection can actually be modified. You haven't shown us that code.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • so converting the collection to a list should solve the problem? – nano_nano Mar 15 '13 at 13:51
  • 1
    @StefanBe: It depends on the list. The major ones, `ArrayList` and `LinkedList`, are structurally modifiable, so their iterators support removal. As I've said, the list created by `Arrays.asList()` does not support it. – Mark Peters Mar 15 '13 at 13:51
2

From this other response from @dmeister: Why aren't Java Collections remove methods generic?

Josh Bloch and Bill Pugh refer to this issue in "Java Puzzlers IV: The Phantom Reference Menace, Attack of the Clone, and Revenge of The Shift" (Google TechTalk).

Josh Bloch says (6:41) that they attempted to generify the get method of Map, remove method and some other, but "it simply didn't work". There are too many reasonable programs that could not be generified if you only allow the generic type of the collection as parameter type. The example given by him is an intersection of a List of Numbers and a List of Longs.

Community
  • 1
  • 1
DocKuro
  • 445
  • 4
  • 13
  • I'm not sure the relevance this has to the question. Nowhere is Stefan trying to use the remove method of a collection. – Mark Peters Mar 15 '13 at 13:54