列表或Iterables可以使用guavas
filter(Iterable> unfiltered, Class type)轻松过滤。此操作执行两个任务:将列表过滤并转换为给定类型T的序列。
然而,我最终得到了Iterables< Something>
并且我想获得一个Iterables< Something< T>>的子序列。对于一些专门的T.
很明显,由于类型擦除,番石榴不能解决这个问题:某事< T>不提供关于它的T的任何直接信息。
让我说我有一些像S?扩展号码> ;.
如果我能够定义一些谓词,告诉我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()来删除空序列。