1

In Java 8 I can map over streams with the map method, e.g.

Stream.of("Hello", "world").map(s -> s.length())

gives me a stream containing the integers [5, 5]. I am trying to do the same with lists. I have come up with

List<String> list = ...

list.stream().map(s -> s.length()).collect(Collectors.toList())

This works but is rather verbose. Is there a more concise solution? Ideally, there would be a similar map method for lists, but I haven't found any. So, are there any alternatives?

3
  • Another option is list.stream().collect(Collectors.mapping(String::length, Collectors.toList())), but how compact do you want it to be? Commented Nov 23, 2018 at 7:03
  • Using a stream to map a list is already much less verbose than using a for loop. Commented Nov 23, 2018 at 7:07
  • @ernest_k: As compact as possible since I am using this pattern pretty often. I have also considered: (1) implementing a custom List class with its own map method, or (2) using streams instead of lists. But I am using Hibernate and when a class has a one-to-many association, it returns a collection of associated objects as a list, not as a stream. If I want to map on that collection (which happens extremely often), I have to convert between list and stream all the time. Commented Nov 23, 2018 at 7:09

2 Answers 2

5

As compact as possible

Just wrap it into your own utility function:

public <T, S> List<S> mapBy(List<T> items, Function<T, S> mapFn) {
    return items.stream().map(mapFn).collect(Collectors.toList());
}

Now you can just use mapBy(students, Student::getName). It doesn't get less verbose than that.

Note that this is only useful if that's the only data mutation you want to make. Once you have more stream operators you want to apply it'd be better to do just that as otherwise you keep creating intermediate lists, which is quite wasteful.

Sign up to request clarification or add additional context in comments.

4 Comments

This seems a good idea, thanks. I can probably put this in a utility class as a static method.
Yes, personally I like having a StreamUtil with this and some similar methods such as finding an item in a list by equality of a specific property or such.
@Giorgio Thanks, appreciate the edit. Coding on mobile is difficult. :-)
yw. When I tried the code in Eclipse I noticed that the return type should be List<S>. Fixed that as well.
1

Think practically to do operation on each element in list you need to either stream it or loop it, so stream is more concise than loop. for more info you can replace lambda expression with method reference operator

list.stream().map(String::length).collect(Collectors.toList());

2 Comments

So there is no way to avoid converting to stream and then use collect to go back to list again. Using a method reference is an improvement though.
either stream or loop need to choose one in both, because you need to get size from all the elements in list, this operation is not specific to one or two elements in list

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.