我想创建一个非常通用的实用程序方法来使用任何集合并将其转换为从Number(Long,Double,Float,Integer等)扩展的用户可选类的集合
我想出了使用Google Collections转换Collection并返回Immutable List的代码.
import java.util.List; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; /** * Takes a {@code List<String>} and transforms it into a list of the * specified {@code clazz}. * * @param <T> * @param stringValues * the list of Strings to be used to create the list of the * specified type * @param clazz * must be a subclass of Number. Defines the type of the new List * @return */ public static <T extends Number> List<T> toNumberList(List<String> stringValues,final Class<T> clazz) { List<T> ids = Lists.transform(stringValues,new Function<String,T>() { @SuppressWarnings("unchecked") @Override public T apply(String from) { T retVal = null; if (clazz.equals(Integer.class)) { retVal = (T) Integer.valueOf(from); } else if (clazz.equals(Long.class)) { retVal = (T) Long.valueOf(from); } else if (clazz.equals(Float.class)) { retVal = (T) Float.valueOf(from); } else if (clazz.equals(Double.class)) { retVal = (T) Double.valueOf(from); } else { throw new RuntimeException(String.format("Type %s is not supported (yet)",clazz.getName())); } return retVal; } }); return ImmutableList.copyOf(ids); }
它可以像这样使用:
// Convert List<String> to List<Long> List<Long> ids = MiscUtils.toNumberList(productIds,Long.class);
我的代码是否超标,或者您如何简化它,同时保持通用?
解决方法
我认为这个代码的最重要的方面是功能而不是方法本身.我也不认为在Function主体中切换允许的子类是有意义的,因为您已经知道在创建函数时要返回的Number类型.如果给定,例如BigInteger.class,您的方法失败也是有问题的.
给定这个,我会做的是创建一个实用程序类(让我们称之为Numbers),并提供方法,每个函数返回一个Function(可以是一个枚举单例),用于将String解析为特定类型的Number.那是:
public class Numbers { public static Function<String,Integer> parseIntegerFunction() { ... } public static Function<String,Long> parseLongFunction() { ... } ... }
他们每个都可以实现这样的:
public static Function<String,Integer> parseIntegerFunction() { return ParseIntegerFunction.INSTANCE; } private enum ParseIntegerFunction implements Function<String,Integer> { INSTANCE; public Integer apply(String input) { return Integer.valueOf(input); } @Override public String toString() { return "ParseIntegerFunction"; } }
然后用户可以使用它:
List<String> strings = ... List<Integer> integers = Lists.transform(strings,Numbers.parseIntegerFunction());
这种方法与你相比有很多优点:
>不需要功能中的任何切换…我们知道我们正在创建什么类型的数字,只是做到这一点.更快.
>更灵活,因为每个功能都可以在任何地方使用,用户不会以你的方法的方式使用它(将变换的值复制到ImmutableList中)
>您只需创建您实际想要允许的函数.如果没有BigInteger解析函数,用户只能不能调用它,而不是在编译时完全合法,然后在运行时失败,就像在你的例子中.
作为附注,我建议使返回类型的任何返回ImmutableList的方法是ImmutableList而不是List …它提供对方法的客户端有用的信息.
编辑:
如果你真的需要一些更动态的东西(也就是说,你希望具有一些Class< T extends Number>的实例的类可以将Strings转换成该Number类型),你也可以添加一个查找方法,如:
public static <T extends Number> Function<String,T> parseFunctionFor(Class<T> type) { // lookup the function for the type in an ImmutableMap and return it }
这与您的原始方法有相同的问题,但是,如果有一个Number子类不提供一个Function.它似乎也不会有很多情况,这将是有用的.