Java 转换列表的更好方法<;MyDataType>;列出<;字符串>;

Java 转换列表的更好方法<;MyDataType>;列出<;字符串>;,java,Java,我想知道是否有更好的方法来转换整个列表或集合,如我在以下代码示例中所示: public static List<String> getAllNames(List<Account> allAccounts) { List<String> names = new ArrayList<String>(allAccounts.size()); for (Account account : allAccounts) {

我想知道是否有更好的方法来转换整个
列表
集合
,如我在以下代码示例中所示:

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;
    }
公共静态列表getAllName(列表allAccounts){
列表名称=新的ArrayList(allAccounts.size());
对于(账户:所有账户){
name.add(account.getName());
}
返回姓名;
}

每次我产生一个像这样的
方法
,我开始思考,难道没有更好的方法吗?我的第一个想法可能是创建一个包含一些
泛型和
反射的解决方案,但这似乎有点过大,在性能方面可能有点慢?

没有更好的方法。铸造是一件困难而危险的事情。在您的示例中,您不能将字符串强制转换为MyDataType,反之亦然,不是吗? 如果您更经常需要,可以使用某种toStringList()方法创建自己的列表实现。

有一种更实用的方法:

return FluentIterable.from(allAccounts).transform(new Function<Account,String>(){
    public String apply(Account account){return account.getName();}
}).toImmutableList()
返回FluentIterable.from(allAccounts).transform(新函数(){
公共字符串应用(帐户){return Account.getName();}
}).toImmutableList()的
当然,这在本质上也是一样的

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

看看谷歌的库

像这样的东西应该可以

final List<String> names = Lists.transform(myObjs, new Function<MyObject, String>() {
    public String apply(final MyObject input) {
        return input.getName();
    }
});
final List name=Lists.transform(myObjs,新函数(){
公共字符串应用(最终MyObject输入){
返回input.getName();
}
});

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

List<A> a = new ArrayList<A>();
List<B> b = (List)a;
List a=new ArrayList();
列表b=(列表)a;
但是,您必须重写类的toString()方法的实现,以返回getName()值。 但是没有类型检查


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

您可以尝试使用Guava库中的
Iterables
函数
类。您可以使用

Iterable<String> newTypeIterable = Iterables.transform(oldTypeIterable, new Function<MyDataType, String> () {
   @Override
   public String apply(MyDataType from)
   {
     return from.getName();
   }
});
Iterable newTypeIterable=Iterables.transform(旧类型Iterable,新函数(){
@凌驾
应用公共字符串(MyDataType from)
{
从.getName()返回;
}
});

事实证明,您也可以使用
列表
类来实现这一点

事实上,我的个人图书馆中就有这种方法

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;
}
公共静态列表castList(列表源列表)
{
List targetList=newarraylist(sourceList.size());
for(TSource t:sourceList){
//如果类型不兼容,这将抛出ClassCastException
//小心
targetList.add((TTarget)t);
}
返回目标列表;
}
使用非常简单,因为编译器会推断TTarget的类型

List<Object> objects = new ArrayList<Object>();
objects.add("One");
objects.add("Two");

List<String> strings = castList(objects);
List objects=new ArrayList();
对象。添加(“一”);
对象。添加(“两个”);
列表字符串=列表(对象);
关于绩效:
我认为使用泛型在这里没有问题。但复制整个阵列的需要是另一回事

好的,这是你能得到的最好的IMO。这可能是“最好的方法”,但我会稍微调整一下,
List name=new ArrayList(allAccounts.size())
。在Java实现功能之前,你的方法是好的。请注意,这不是“强制转换”,而是“转换”。“铸造”一词有一个特定的含义,在这里不适用。@mre:是的,这是个好主意。如果你不介意的话,我也在上面的代码中添加了这个,他无法将
列表
转换为
列表
。@assylias,但他仍然可以转换为
List@assylias:这只是一个例子,说明了强制转换的困难。你是否意识到如果你这样做,
List
不会是
B
的列表?用
List
List
试试这个。是的,我意识到了但它回答了OP的问题,不是吗?正如我提到的,它不是类型安全的方法。我不知道有一个Lists类,我想你必须使用
Iterables
。谢谢。不,你不能在番石榴中更改列表的类型,但是你可以轻松地创建一个不同于现有列表的列表+1@SeanPatrickFloyd,用于返回不可变列表-我认为这是一个更好的方法,现在我看它谢谢你关于番石榴的提示,我从来没有看过它,但我会更深入地看它。@RNJ不,不总是这样。在某些场景中,实时视图更合适,与我所想的非常接近。我可能还会在新列表中添加一个带有我想要获取的属性名的字符串。然而,我认为如果您添加到非可铸造类型,您将得到一个铸造异常。也许您应该在
方法头中添加类似的内容
?您是对的,如果类型不兼容,您将得到ClassCastException。我将向该方法添加一个警告。