在一个列表中获取对象的属性列表

70

当有一个 List<Person> 时,是否有可能从中获取所有person.getName()的List?是否有现成的方法可以调用,还是我必须像这样编写一个 foreach 循环:

List<Person> personList = new ArrayList<Person>();
List<String> namesList = new ArrayList<String>();
for(Person person : personList){
    namesList.add(personList.getName());
}
8个回答

138

Java 8及以上版本:

List<String> namesList = personList.stream()
                                   .map(Person::getName)
                                   .collect(Collectors.toList());

如果你需要确保得到一个 ArrayList 作为结果,你需要将最后一行更改为:

                                    ...
                                    .collect(Collectors.toCollection(ArrayList::new));

Java 7及以下版本:

在Java 8之前的标准集合API不支持此类转换。除非使用一些更高级的集合API或扩展,否则必须编写循环(或将其包装在自己的“map”函数中)。

(您Java代码片段中的这些行正是我会使用的行。)

在Apache Commons中,您可以使用CollectionUtils.collectTransformer

在Guava中,您可以使用Lists.transform方法。


我对可读性的提高并不感到印象深刻。虽然它更简洁了,但我们确实减少了50%的字符。"是啊",我猜?在性能方面怎么样? - Poutrathor
我也不是。说实话,我很少认为流API能提高可读性。 - aioobe

17

也许你已经做过这个,但是对于其他人来说

使用Java 1.8

List<String> namesList = personList.stream().map(p -> p.getName()).collect(Collectors.toList()); 

6

试试这个

Collection<String> names = CollectionUtils.collect(personList, TransformerUtils.invokerTransformer("getName"));  

使用Apache Commons Collection API。

3
我认为你总是需要这样做。但如果你总是需要这样的事情,我建议创建另一个类,例如称之为People,其中personList是一个变量。
可以像这样实现:
class People{
    List<Person> personList;
    //Getters and Setters

    //Special getters
    public List<string> getPeopleNames(){
         //implement your method here        
    }

    public List<Long> getPeopleAges(){
         //get all people ages here
    }
}

在这种情况下,每次只需要调用一个getter。

2

尚未测试,但这是个思路:

public static <T, Q> List<T> getAttributeList(List list, Class<? extends Q> clazz, String  attribute)    
{
    List<T> attrList= new ArrayList<T>();

    attribute = attribute.charAt(0).toUpperCase() + attribute.substring(1); 
    String methodName = "get"+attribute;

    for(Object obj: personList){
        T aux = (T)clazz.getDeclaredMethod(methodName, new Class[0]).invoke(obj, new Object[0]);
        attrList.add(aux);
    }
}

1

0

你将需要循环访问每个对象的getName()方法。

也许guava可以做出一些花哨的东西...


你能提供一个使用Guava的例子吗? - Sonnenhut

0

在标准的Java Collection API中,至少只有你提出的那种方法可以实现这个功能,没有其他更好的方式。

我很久以前就一直希望有类似的东西...特别是自从我尝到了Ruby的甜头,它有像collect和select这样的闭包操作非常棒。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接