Alex Rivera | Logout

Filtering lists of generic types

Asked 2011-08-26T12:29:19.560
19

Lists or Iterables can be filtered easily using guavas filter(Iterable<?> unfiltered, Class<T> type). This operation performs two tasks: the list is filtered and transformed into a sequence of the given type T.

Quite often however I end up with Iterables<Something<?>> and I want to get a subsequence of Iterables<Something<T>> for some specialized T.

It is clear, that Guava can't solve this problem out of the box due to type erasure: Something<T> does not provide any direct information about its T.

Lets say I have something like S<? extends Number>. If I am able to define some predicate which tells me if S<?> may be casted to S<Double> I may use it as a filer:

<T extends Number> Predicate<S<?>> isOfType(Class<N> type) {...}

with:

Iterable<S<?>> numbers;
Iterable<S<?>> filtered = Iterable.filter(numbers, isOfType(Double.class));

This performs the task of filtering but it misses the transformation step. If I think my Predicate works well I may even think of casting:

Iterable<S<Double>> doubles = (Iterable<S<Double>>) filtered;

But this exposes some ugly cast operation.

As an alternative I may provide a Function<S<?>, S<Double>> to perform the cast. In constrast to Class.cast() however it should not throw a ClassCastException b

Edit
Report

1 Answer

2

Scala language in its collections framework offers similar functionality to Guava. We have Option[T] class which can be considered as at-most-single-element-collection. Among simple filtering or transformation methods there is a method which performs both operations at once. It expects provided transformation function to return a value of Option class. Then it merges content of returned Option objects into a collection. I think you can implement similar functionality in Java.

I was thinking of this problem some time ago because firstly applying transformation and then filtering requires passing the collection twice. Then someone enlightened me that I can transform and filter iterator of this collection. In this case the collection is traversed once and you may apply as many filters and transformations as you want.

answered 2011-09-15T06:56:56.487

Your Answer