Dit*_*itz 19 java generics iterable guava
可以使用番石榴轻松过滤列表或Iterables filter(Iterable<?> unfiltered, Class<T> type).此操作执行两个任务:列表被过滤并转换为给定类型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) {...}
Run Code Online (Sandbox Code Playgroud)
有:
Iterable<S<?>> numbers;
Iterable<S<?>> filtered = Iterable.filter(numbers, isOfType(Double.class));
Run Code Online (Sandbox Code Playgroud)
这执行过滤任务,但它错过了转换步骤.如果我认为我的Predicate运作良好,我甚至可以考虑转换:
Iterable<S<Double>> doubles = (Iterable<S<Double>>) filtered;
Run Code Online (Sandbox Code Playgroud)
但这暴露了一些丑陋的演员操作.
作为替代方案,我可以提供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));
Run Code Online (Sandbox Code Playgroud)
但是列表并没有真正过滤:相反,它仍然包含无法转换或转换为每个元素的空对象S<Double>.但这可以通过额外的过滤步骤轻松解决,如:
Iterable<S<Double>> doubles = Iterables.filter(doubles, Predicates.notNull());
Run Code Online (Sandbox Code Playgroud)
第二种解决方案对我来说似乎更聪明.在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);
Run Code Online (Sandbox Code Playgroud)
其中第二个功能是第一个功能的捷径Predicates.notNull();
但是,第一个函数也是值得的,因为谓词不是必需的Predicates.notNull().
想象一下Iterable<Iterable<? extends Number>>.转换器函数Function<Iterable<? extends Number>, Iterable<Double>>可以简单地返回过滤的序列,该序列可以是空的而不是返回null.附加过滤器最终可以使用删除空序列Iterables.isEmpty().
Scala 语言在其集合框架中提供了与 Guava 类似的功能。我们有 Option[T] 类,它可以被视为至多单元素集合。在简单的过滤或转换方法中,有一种方法可以同时执行这两种操作。它期望提供的转换函数返回 Option 类的值。然后它将返回的 Option 对象的内容合并到一个集合中。我认为你可以用Java实现类似的功能。
我前段时间在考虑这个问题,因为首先应用转换然后过滤需要传递集合两次。然后有人启发我,我可以转换和过滤这个集合的迭代器。在这种情况下,集合将被遍历一次,您可以根据需要应用任意数量的过滤器和转换。