筛选泛型类型的列表
列表或可迭代可以使用番石榴过滤器(可迭代<>未过滤,类<T>类型)
轻松过滤。此操作执行两个任务:筛选列表并将其转换为给定类型 T 的序列。
然而,很多时候我最终会得到,我想得到一些专门的T的子序列。Iterables<Something<?>>
Iterables<Something<T>>
很明显,由于类型擦除,番石榴无法开箱即用地解决此问题:没有提供有关其T的任何直接信息。Something<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;
但这暴露了一些丑陋的演员操作。
作为替代方案,我可能会提供一个来执行演员表。然而,在constrast到Class.cast()
中,它不应该抛出一个,但如果元素不能被强制转换(或转换),它只应该返回。这样,序列可以在没有任何显式转换的情况下进行转换:Function<S<?>, S<Double>>
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()
想象一个.转换器函数可以简单地返回一个过滤的序列,该序列可能是空的,而不是返回null。附加筛选器可能最终使用 删除空序列。Iterable<Iterable<? extends Number>>
Function<Iterable<? extends Number>, Iterable<Double>>
Iterables.isEmpty()