How to make a new list with a property of an object which is in another list

JavaListCollectionsJava StreamGuava

Java Problem Overview


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 Solutions


Solution 1 - Java

Java 8 way of doing it:-

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

Solution 2 - Java

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));

Solution 3 - Java

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.

Solution 4 - Java

Java 8 lambda expression solution:

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

Solution 5 - Java

If someone get here after a few years:

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

Solution 6 - Java

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]

Solution 7 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjavatarView Question on Stackoverflow
Solution 1 - JavaKaushikView Answer on Stackoverflow
Solution 2 - JavaPremrajView Answer on Stackoverflow
Solution 3 - JavajavatarView Answer on Stackoverflow
Solution 4 - JavaVijayView Answer on Stackoverflow
Solution 5 - JavaJonathan PerrottaView Answer on Stackoverflow
Solution 6 - JavaYassin HajajView Answer on Stackoverflow
Solution 7 - JavaZéychinView Answer on Stackoverflow