如何使用另一个列表中对象的属性制作新列表


79

想象一下,我有一些对象的列表:

List<Student>

我需要生成包含另一个列表idsStudents在上面的列表:

List<Integer>

避免使用循环,是否可以通过使用apache collectionsguava来实现?

哪种方法对我的情况有用?


嘿,我发现它刚才:stackoverflow.com/questions/737244/...
Javatar

乔恩的答案很酷,但是如果您看一下,它还会使用循环。任何解决方案都将使用循环-尽管您可能看不到它,但在内部它会
导致

有人必须应用循环才能完成。您或您可能使用的某些lib。
sudmong 2012年

实际上,乔恩的答案与我的情况不符,因为我不想使用for循环。我认为在某个地方可以找到一种更方便的方法,但是请等待我找到它:)
Javatar 2012年

Answers:


173

Java 8的实现方式:-

List<Integer> idList = students.stream().map(Student::getId).collect(Collectors.toList());

1
如果我想要一个元组列表怎么办?类似于[((Id,name),(Id,name)]]。
Khazana

并非所有Android API都支持所有1.8功能。特别是,java.util.stream之前,不支持API 24
黑马

41

使用番石榴,您可以使用功能,例如-

private enum StudentToId implements Function<Student, Integer> {
        INSTANCE;

        @Override
        public Integer apply(Student input) {
            return input.getId();
        }
    }

您可以使用此功能将学生名单转换为-

Lists.transform(studentList, StudentToId.INSTANCE);

当然它将循环以提取所有id,但是请记住guava方法返回view,并且仅当您尝试遍历时才应用Function。List<Integer>
如果不进行迭代,它将永远不会应用循环。

注意:请记住,这是观点,如果你想要遍历多次,这将是更好的内容在其他一些复制List<Integer>

ImmutableList.copyOf(Iterables.transform(students, StudentToId.INSTANCE));

我认为必须单独定义一个函数是不明智的。我认为这也可以匿名完成,并且一步一步完成
Marc

如何提取列表的字符串(float等)成员?
sepehr '16

22

感谢Premraj推荐的替代酷选项。

我已经使用了Apache CollectionUtils和BeanUtils。因此,我对以下代码的性能感到满意:

List<Long> idList = (List<Long>) CollectionUtils.collect(objectList, 
                                    new BeanToPropertyValueTransformer("id"));

值得一提的是,我将比较上面使用的番石榴(提供的Premraj)和collectionUtils的性能,并确定速度更快的一种。


3
无论出于
何种

1
是的,但是对于强制转换我想要转换的每种类型的对象,强制要求额外的枚举声明来限制它的使用对我来说实际上并不是一个好主意。
Javatar 2012年

好吧,这取决于您的设计-您可以说出Identifiable定义getId()方法的接口,然后可以使用此单个枚举单例模式来通常提取ID。
2012年

2
番石榴肯定比豆utils的作为后来使用反射更有效..
拉维

2
我绝对想避免在构造函数new BeanToPropertyValueTransformer(“ id”)中使用属性名称作为String。重构将很难!但我正在寻找解决方案。同时,我将使用冗长但安全的Guava解决方案。
redochka

7

Java 8 Lambda表达式解决方案:

List<Integer> iDList = students.stream().map((student) -> student.getId()).collect(Collectors.toList());

如果Java <1.8,则使用Apache CollectionUtils。示例:Collection <String> firstnames = CollectionUtils.collect(userlist,TransformerUtils.invokerTransformer(“ getFirstname”));;
a_subscriber

5

如果几年后有人到达这里:

List<String> stringProperty = (List<String>) CollectionUtils.collect(listOfBeans, TransformerUtils.invokerTransformer("getProperty"));

而且您只是救了我:)
Behrad3d

-5

从数学上讲,没有循环就不可能做到这一点。为了创建一组离散值到另一组离散值的映射F,F必须对原始组中的每个元素进行操作。(执行此操作基本上需要一个循环。)

话虽如此:

为什么需要新清单?您可能会以错误的方式来解决任何问题。

如果您有的列表Student,则在遍历此列表时,只需遍历一两步即可遍历学生的ID号。

for(Student s : list)
{
    int current_id = s.getID();
    // Do something with current_id
}

如果您有其他问题,请评论/更新问题,我们将尽力为您提供帮助。


首先感谢您的回复。但是,令人震惊的是,您说需要新列表是错误的方式。因为这取决于容量和需要的范围。因此,您的方法是错误的方法:)我再次提到“达到无循环能力”是一种更方便的方法,以免使代码不可读且性能低下。无论如何,我已经找到一种实现它的方法,可以分享一点。
Javatar 2012年

我并不是说这错误的方法,但是这可能是错误的方法,具体取决于您要解决的问题。
Zéychin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.