使用海藻石filter(Iterable<?> unfiltered, Class<T> type)
可以很容易地过滤清单或Iterables。此操作执行两个任务:列表过滤和转化为给定类型T的序列过滤一般类型列表
常常不过我最终Iterables<Something<?>>
和我想要得到的Iterables<Something<T>>
子序列为一些专门的T.
很清楚,那番石榴不能开箱即用的解决这个问题,因为类型擦除:Something<T>
不提供有关其T.任何直接信息
可以说我有类似S<? extends Number>
。 如果我能够定义一些断言它告诉我,如果S<?>
可强制转换为S<Double>
我可以用它作为一个过滤器:
<T extends Number> Predicate<S<?>> isOfType(Class<N> type) {...}
有:
Iterable<S<?>> numbers;
Iterable<S<?>> filtered = Iterable.filter(numbers, isOfType(Double.class));
此进行过滤的任务,但它错过了转换步骤。 如果我认为我的谓语行之有效我可能甚至想铸造:
Iterable<S<Double>> doubles = (Iterable<S<Double>>) filtered;
但是,这暴露了一些丑陋的转换操作。
作为替代,我可以提供Function<S<?>, S<Double>>
来执行演员。 与Class.cast()
相反,它不应该抛出ClassCastException
,而只是返回null
如果该元素不能被铸造(或转换)。 这样的顺序可以没有任何明确的转换转换:
<T extends Number> Function<S<?>, S<T>> castOrNull(Class<N> type) {...}
Iterable<S<Double>> doubles = Iterable.filter(numbers, castOrNull(Double.class));
但是是不是真的过滤列表:相反,它仍然包含了其不能转换或强制转换为S<Double>
每个元素空的对象。 但是这可以通过附加的过滤步骤一样容易解决:
Iterable<S<Double>> doubles = Iterables.filter(doubles, Predicates.notNull());
第二个解决办法似乎要聪明得多给我。要定义的Function
可以执行强制转换(隐藏未经检查的操作),也可以根据需要创建一些新的对象S<T>
。
剩下的问题是: 有没有更聪明的方法来执行必要的转换和过滤一步?我可以简单地定义像一些效用函数:
<I,O> Iterables<O> convert(
Iterables<O> input,
Function<? super I, ? extends O> convert,
Predicate<? super O> filter);
<I,O> Iterables<O> convert(
Iterables<O> input,
Function<? super I, ? extends O> convert);
当第二函数是第一个具有Predicates.notNull()
短切;
但值得拥有第一个函数,因为谓词不是必需的Predicates.notNull()
。想象一下Iterable<Iterable<? extends Number>>
。转换函数Function<Iterable<? extends Number>, Iterable<Double>>
可能会简单地返回一个可能为空的过滤序列,而不是返回null。额外的过滤器最终可以使用Iterables.isEmpty()
删除空序列。
如果'Iterable.filter(...)'返回一个具有扩展功能的迭代器,那么你可以链式过滤器会很有用。 '/ * S extends Collection */Iterable
> doubles = Iterable.filter(numbers,castOrNull(Double.class))。filter(Predicates.notNull())。filter(Predicates.notEmpty());' – aalku想要一步到位呢?转换和过滤是不同的操作。 – pawstrong