I want to generate a list of strings, comprising id and external ids, from a list of Bean.
public class User {
private String id;
private List<String> externalIds;
}
I got it using the below code, but here I need to do the stream twice.
List<User> references = new ArrayList();
Stream.concat(references.stream().map(User::getId),
references.stream().map(User::getExternalIds).flatMap(Collection::stream))
.collect(Collectors.toList());
Is there any better way to rewrite this code?
CodePudding user response:
Use Stream.concat
inside the flatMap
operation:
references.stream()
.flatMap(user -> Stream.concat(
Stream.of(user.getId()),
user.getExternalIds().stream()
))
.collect(Collectors.toList())
CodePudding user response:
Try this:
references.stream()
.flatMap(u -> Stream.of(List.of(u.getId()), u.getExternalIds()))
.flatMap(List::stream)
.collect(Collectors.toList());
CodePudding user response:
references.stream()
then:
map()
which is to create a list including id & externalIds
then:
flatMap()
then:
collect()
Another way: in User
, make a new get method to return a list with both id & externalIds
then:
references.stream().flatMap(User::getThatNewMethodIds()).collect(...)
CodePudding user response:
If you're using Java 16 you can do it using mapMulti
. This essentially intercepts each item in the stream and replaces it with other items. It avoids re-streaming and flatmapping. Since the nature of the stream(i.e. type) is being changed from User
to String
, the witness before mapMulti
is required.
- add the
user id
in the stream. - then add each
external id
in the stream for that user
List<String> results = references.stream()
.<String>mapMulti((user, consumer) -> {
consumer.accept(user.getId());
for (String id : user.getExternalIds()) {
consumer.accept(id);
}
}).toList();