我想知道是否没有更好的方法来转换整个Lists
或Collections
,就像我在以下代码示例中显示的那样:
public static List<String> getAllNames(List<Account> allAccounts) {
List<String> names = new ArrayList<String>(allAccounts.size());
for (Account account : allAccounts) {
names.add(account.getName());
}
return names;
}
每当我产生这样的method
时,我开始思考,是不是有更好的方法?我的第一个想法是创建一个可能有一些generics
和reflections
的解决方案,但这似乎有点过大,在性能方面可能有点慢?
答案 0 :(得分:6)
查看Google的Guava图书馆
这样的事情应该这样做
final List<String> names = Lists.transform(myObjs, new Function<MyObject, String>() {
public String apply(final MyObject input) {
return input.getName();
}
});
答案 1 :(得分:5)
使用Guava,有一种更实用的方法:
return FluentIterable.from(allAccounts).transform(new Function<Account,String>(){
public String apply(Account account){return account.getName();}
}).toImmutableList()
但当然,这基本上也是一样的。
BTW:这个答案和RNJ之间的区别在于,在我的情况下,列表将被创建一次,而在另一个答案中,它是一个实时视图。两个版本都有效,但适用于不同的场景。答案 2 :(得分:2)
我的个人图书馆实际上有这种方法。
public static <TSource,TTarget> List<TTarget> castList(List<TSource> sourceList)
{
List<TTarget> targetList = new ArrayList<TTarget>(sourceList.size());
for (TSource t : sourceList) {
//This will throw a ClassCastException if the types are not compatible
//Be carefull
targetList.add((TTarget)t);
}
return targetList;
}
用法非常简单,因为编译器会推断出TTarget的类型。
List<Object> objects = new ArrayList<Object>();
objects.add("One");
objects.add("Two");
List<String> strings = castList(objects);
关于表现: 我认为使用泛型在这里没问题。但复制整个阵列的需要是另一回事。
答案 3 :(得分:0)
没有更好的方法。铸造是一件困难而且危险的事情。在您的示例中,您无法将String转换为MyDataType,反之亦然,不是吗? 你可以使用某种toStringList()创建一个自己的List-Implementation - 如果你需要更频繁的话,可以使用方法。
答案 4 :(得分:0)
有一种简单的方法,但它不是类型安全的
List<A> a = new ArrayList<A>();
List<B> b = (List)a;
但是你必须覆盖类的toString()方法的实现以返回getName()值。 但是没有类型检查,
如上所述,您当然可以改为循环并在每个对象上调用getName
答案 5 :(得分:0)
您可以尝试使用Guava库中的Iterables
和Function
类。您可以使用
Iterable
的新类型
Iterable<String> newTypeIterable = Iterables.transform(oldTypeIterable, new Function<MyDataType, String> () {
@Override
public String apply(MyDataType from)
{
return from.getName();
}
});
事实证明,您也可以使用Lists
课程执行此操作!