列表或Iterables可以使用guavas

filter(Iterable> unfiltered, Class type)轻松过滤。此操作执行两个任务:将列表过滤并转换为给定类型T的序列。

然而,我最终得到了Iterables< Something>

并且我想获得一个Iterables< Something< T>>的子序列。对于一些专门的T.

很明显,由于类型擦除,番石榴不能解决这个问题:某事< T>不提供关于它的T的任何直接信息。

让我说我有一些像S?扩展号码&gt ;.

如果我能够定义一些谓词,告诉我S可以铸造成S< Double>我可以将其用作文件管理器:

> isOfType(Class type) {...}

有:

Iterable> numbers;

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

这执行过滤的任务,但是错过了转换步骤。

如果我认为我的谓词工作正常,甚至可以考虑投射:

Iterable> doubles = (Iterable>) filtered;

但这暴露了一些丑陋的演员操作。

作为替代,我可以提供一个功能< S< S>,S&Double>>执行演员。

在与Class.cast()的对比中,它不应该抛出ClassCastException,只是当元素不能被转换(或转换)时返回null)。

这样可以转换序列,而不需要任何明确的转换:

, S> castOrNull(Class type) {...}

Iterable> doubles = Iterable.filter(numbers, castOrNull(Double.class));

但是列表没有被真正过滤:相反,它仍然包含无法转换或转换为S&Double的每个元素的空对象。

但这可以通过附加的过滤步骤轻松解决,如:

Iterable> doubles = Iterables.filter(doubles, Predicates.notNull());

第二个解决方案对我来说似乎更加聪明。待定义的功能可以执行转换(隐藏未经检查的操作),或者可能真正创建一些新的对象S< T>如有必要。

剩下的问题是:

是否有更智能的方式执行必要的转换和过滤单步?我可以简单地定义一些效用函数,如:

Iterables convert(

Iterables input,

Function super I, ? extends O> convert,

Predicate super O> filter);

Iterables convert(

Iterables input,

Function super I, ? extends O> convert);

其中第二个函数是第一个具有Predicates.notNull()的第一个函数的快捷方式;

但是值得拥有第一个函数,因为谓词不是必需的Predicates.notNull()。

想象一下一个可迭代的< Iterable>。转换器函数Function< Iterable,可迭代< Double>>可以简单地返回一个可能为空的过滤序列,而不是返回null。附加的过滤器最终可以使用Iterables.isEmpty()来删除空序列。