Java – n alternative to instanceof when filtering a Java stream by class

collectionsinheritancejava

I have an unexpected situation in a project in which all types extending one class are packed into a Java collection; but only a specific extension of that class contains an additional method. Let's call it "also()"; and let me be clear that no other extension has it. Right before performing one task on every item in that collection, I need to call also() on every item that implements it.

The easiest way forward is this:

stuff.stream().filter(item -> item instanceof SpecificItem)
            .forEach(item -> ((SpecificItem)item).also()));
stuff.stream().forEach(item -> item.method());

It works fine, but I'm not comfortable with the "instanceof" in there. That's generally a marker of bad code smell. It is very possible that I will refactor this class just to get rid of it. Before I do something that dramatic, though, I thought I would check with the community and see if someone with more experience with either Streams or Collections had a simpler solution.

As an example (certainly nonexclusive), is it possible to get a view of a collection that filters entries by class?

Best Answer

I'd suggest tossing in a .map call to do the cast for you. Then your later code can use the 'real thing'.

Before:

stuff.stream().filter(item -> item instanceof SpecificItem)
            .forEach(item -> ((SpecificItem)item).also()));

After:

stuff.stream().filter(item -> item instanceof SpecificItem)
            .map(item -> (SpecificItem)item)
            .forEach(specificItem -> specificItem.also()));

This isn't perfect, but seems to clean things up a little.

Related Topic