转换列表列表(或任何扩展 Number 的类)
我想创建一个非常通用的实用方法来获取任何 Collection 并将其转换为从 Number(长整型、双精度、浮点型、整数等)扩展的用户可选类的集合。
我想出了这段使用 Google Collections 的代码转换集合并返回不可变列表。
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);
我的代码是否太过分了,或者您将如何简化它并同时保持它足够通用?
I want to create a very generic utility method to take any Collection and convert it into a Collection of a user selectable class that extends from Number (Long, Double, Float, Integer, etc.)
I came up with this code that uses Google Collections to transform the Collection and to return an 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);
}
It can be used like this:
// Convert List<String> to List<Long>
List<Long> ids = MiscUtils.toNumberList(productIds, Long.class);
Is my code overkill or how would you simplify it and at the same time keep it generic enough?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为这段代码最重要的方面是函数,而不是方法本身。我也不认为切换
Function
主体中允许的子类是没有意义的,因为您已经知道当时想要返回什么类型的Number
函数
已创建。如果给定 BigInteger.class,您的方法会失败,这也有一点问题。鉴于此,我要做的是创建一个实用程序类(我们称之为
Numbers
)并提供其上的方法,每个方法返回一个Function
(可以是一个enum
单例)用于将String
解析为特定类型的Number
。也就是说:它们都可以像这样实现:
然后可以按照用户想要的方式使用:
这种方法比您的方法有很多优点:
Function
中进行任何切换...我们知道我们正在创建什么类型的数字,然后就这样做。快点。Function
可以在任何地方使用...用户不必像您的方法那样使用它(将转换后的值复制到ImmutableList
您只创建您真正想要允许的Function
,BigInteger
解析函数,用户就无法调用它,而不是让它完全合法。在编译时执行此操作,然后在运行时失败,就像您的示例一样,我建议将返回
ImmutableList
的任何方法的返回类型设置为ImmutableList 而不是
List
...它提供对方法的客户端有用的信息编辑:
如果您确实需要更动态的东西。 (即您希望具有某些
Class
实例的类能够将String
转换为该Number
类型)您还可以添加一个查找方法,例如:但是,如果您没有为其提供
Function
的Number
子类,则这与原始方法具有相同的问题。似乎在很多情况下这都不会有用。I think the most important aspect of this code is the
Function
as opposed to the method itself. I also don't think it makes sense to switch over the subclasses you allow in theFunction
body, as you already know what type ofNumber
you want to return at the time theFunction
is created. It's also slightly problematic that your method fails if given, say,BigInteger.class
.Given this, what I would do is create a utility class (let's call it
Numbers
) and provide methods on it that each return aFunction
(which can be anenum
singleton) for parsing aString
as a specific type ofNumber
. That is:They could each be implemented something like this:
This can then be used however users want:
This approach has quite a few advantages over yours:
Function
... we know what type of number we're creating and just do that. Faster.Function
can be used wherever... users aren't forced to use it the way your method does (copying the transformed values into anImmutableList
.Function
s you actually want to allow. If there's noBigInteger
parsing function, users just can't call that, as opposed to having it be completely legal to do that at compile time and then fail at runtime like in your example.As a side note, I'd recommend making the return type of any method that returns an
ImmutableList
beImmutableList
rather thanList
... it provides information that is useful to clients of the method.Edit:
If you really need something more dynamic (i.e. you want classes that have an instance of some
Class<T extends Number>
to be able to transformString
s to thatNumber
type) you could also add a lookup method like:This has the same problems as your original method, though, if there's a
Number
subclass that you don't provide aFunction
for. It also doesn't seem like there would be many situations where this would be useful.为什么不实现几个转换器函数并将它们传递给 Lists.transform() 调用?
所以,你可以这样写:
如果你想自动处理类型,你可以添加一个变压器工厂或一个映射:
Why don't you implement several transformer functions and pass them to Lists.transform() call?
So, you could write:
If you want to handle types automatically, you can add a transformer factory or a map:
我觉得不错。
既然您拥有 Class 令牌,为什么不避免未经检查的强制转换从而抑制警告呢?
Looks good to me.
Since you have the Class token, why not avoid the unchecked cast and thus suppress warnings?
您可以使用反射,并执行以下操作:
未经测试且可能很慢。
You could use reflection, and do something like this:
Untested and possible slow.