سؤال

Imagine that I have a list of certain objects:

List<Student>

And I need to generate another list including the ids of Students in the above list:

List<Integer>

Avoiding using a loop, is it possible to achieve this by using apache collections or guava?

Which methods should be useful for my case?

هل كانت مفيدة؟

المحلول

Java 8 way of doing it:-

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

نصائح أخرى

With Guava you can use Function like -

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

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

and you can use this function to convert List of students to ids like -

Lists.transform(studentList, StudentToId.INSTANCE);

Surely it will loop in order to extract all ids, but remember guava methods returns view and Function will only be applied when you try to iterate over the List<Integer>
If you don't iterate, it will never apply the loop.

Note: Remember this is the view and if you want to iterate multiple times it will be better to copy the content in some other List<Integer> like

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

Thanks to Premraj for the alternative cool option, upvoted.

I have used apache CollectionUtils and BeanUtils. Accordingly, I am satisfied with performance of the following code:

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

It is worth mentioning that, I will compare the performance of guava (Premraj provided) and collectionUtils I used above, and decide the faster one.

Java 8 lambda expression solution:

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

If someone get here after a few years:

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

You can use Eclipse Collections for this purpose

Student first = new Student(1);
Student second = new Student(2);
Student third = new Student(3);

MutableList<Student> list = Lists.mutable.of(first, second, third);
List<Integer> result = list.collect(Student::getId);

System.out.println(result); // [1, 2, 3]

It is Mathematically impossible to do this without a loop. In order to create a mapping, F, of a discrete set of values to another discrete set of values, F must operate on each element in the originating set. (A loop is required to do this, basically.)

That being said:

Why do you need a new list? You could be approaching whatever problem you are solving in the wrong way.

If you have a list of Student, then you are only a step or two away, when iterating through this list, from iterating over the I.D. numbers of the students.

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

If you have a different sort of problem, then comment/update the question and we'll try to help you.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top