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。我将向该方法添加一个警告。