Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safely traversing a raw Iterator in Java?

I'm using a third party library that returns a raw Iterator, e.g.

Iterator<?> children = element.getChildElements();

I know the actual type, but I don't necessarily trust the third party lib to stick with it in the future. There are two (that I can think of) somewhat risky ways to traverse this:

@SuppressWarnings("unchecked")
Iterator<ActualObject> currentChildren = (Iterator<ActualObject>)currentElement.getChildElements();

or

Iterator<?> children = element.getChildElements();
while (null != children && children.hasNext()) {
  ActualObject child = (ActualObject)children.next(); //Possible ClassCastException @ runtime
  ...
}

The only "safe" way I could come up with to traverse this sort of iterator is the following:

Iterator<?> children = element.getChildElements();
while (null != children && children.hasNext()) {
  Object obj = children.next();
  ActualObject child = null;
    if (obj instanceof ActualObject)
      child = (ActualObject)obj;
    ...
}

This seems overly verbose. Is there a better, yet equally "safe" way to traverse a raw iterator?

EDIT: I realize I can catch/log the exception in an else block, I was looking (hoping) for a Java language equivalent of what ColinD has mentioned below.

like image 829
Justin Garrick Avatar asked Sep 14 '10 20:09

Justin Garrick


1 Answers

Guava makes this easy with its Iterators.filter(Iterator<?>, Class<T>) method. It returns an unmodifiable Iterator<T> that basically just skips every element of the given iterator that isn't an instance of type T:

Iterator<ActualObject> children = Iterators.filter(element.getChildElements(),
    ActualObject.class);

You can obviously then traverse the resulting iterator without needing to cast each element to ActualObject AND without having to worry about ClassCastException.

like image 132
ColinD Avatar answered Sep 21 '22 05:09

ColinD