5

我想知道是否没有更好的方法来转换整体ListsCollections按照我在以下代码示例中显示的方式:

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这样的作品,我都会开始思考,难道没有更好的方法吗?我的第一个想法是用一些genericsand创建一个解决方案reflections,但这似乎有点过大,而且在性能方面可能有点慢?

4

6 回答 6

6

看看 Google 的Guava

像这样的事情应该这样做

final List<String> names = Lists.transform(myObjs, new Function<MyObject, String>() {
    public String apply(final MyObject input) {
        return input.getName();
    }
});
于 2012-12-04T14:31:38.940 回答
5

使用Guava,有一种更实用的方法:

return FluentIterable.from(allAccounts).transform(new Function<Account,String>(){
    public String apply(Account account){return account.getName();}
}).toImmutableList()

当然,这本质上是做同样的事情。

顺便说一句:这个答案和 RNJ 的区别在于,在我的情况下,列表将被创建一次,而在另一个答案中,它是一个实时视图。两个版本都有效,但适用于不同的场景。

于 2012-12-04T14:30:49.700 回答
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);

关于性能:我认为在这里使用泛型没有问题。但是需要复制整个数组是另一回事。

于 2012-12-04T14:43:13.553 回答
0

没有更好的办法。铸造是一件困难而危险的事情。在您的示例中,您无法将 String 转换为 MyDataType ,反之亦然,不是吗?如果您更频繁地需要这些,您可以使用某种 toStringList() 方法创建自己的列表实现。

于 2012-12-04T14:29:27.757 回答
0

有一个简单的方法,但它不是类型安全的

List<A> a = new ArrayList<A>();
List<B> b = (List)a;

但是您必须重写类的 toString() 方法的实现以返回 getName() 值。但是没有类型检查,

如前所述,您当然可以做一个循环并在每个对象上调用 getName

于 2012-12-04T14:32:55.303 回答
0

您可以尝试使用 Guava 库中的IterablesFunction类。您可以创建一种新的Iterable使用类型,

Iterable<String> newTypeIterable = Iterables.transform(oldTypeIterable, new Function<MyDataType, String> () {
   @Override
   public String apply(MyDataType from)
   {
     return from.getName();
   }
});

原来你也可以在Lists课堂上做到这一点!

于 2012-12-04T14:34:01.397 回答