bilak
bilak

Reputation: 4922

Java 8 stream combine two different collections

I'm still new to java 8 streams so I'm figuring out how to do it at simplest as possible.

I would like to know if there is simpler solution for combining two streams of different objects.

Let's say I have following java objects.

public class Message {

    private String id;
    private String key;
    private List<MessageLocalization> localizations = new ArrayList<>();

    // ...getters setters
}

public class MessageLocalization {

    private String id;
    private String language;
    private String baseText;
    private String shortText;
    private String longText;
    private Integer orderBy = 1;

    // ...getters setters
}

and with following method I'm retrieving all messages with their localizations.

public List<Message> getAllMessages() {
        List<Message> messages =
                StreamSupport
                        .stream(messageRepository.findAll().spliterator(), false)
                        .map(message -> new Message(message.getId(), message.getMessageKey()))
                        .collect(Collectors.toList());

        messages
                .stream()
                .forEach(message -> {
                    localizationRepository.findAllByObjectIdAndLocalizedType(message.getId(), LocalizedType.MESSAGE)
                            .stream()
                            .forEach(localization -> {
                                message.getLocalizations().add(
                                        new MessageLocalization(localization.getId(),
                                                localization.getLanguage(),
                                                localization.getBaseText(),
                                                localization.getShortText(),
                                                localization.getLongText(),
                                                localization.getOrderBy()));
                            });
                });
}

So here I have two steps:

  1. retrieving data from repository and constructing Message list
  2. streaming Message list and retrieving data from other repository for its localizations

Can this be rewritten somehow simpler (for example include the second step in first one)?

Thanks

Upvotes: 2

Views: 331

Answers (2)

bilak
bilak

Reputation: 4922

Thanks to to @Holger I've finished with this construction (maybe this will be useful for someone in future)

List<Message> messages = StreamSupport.stream(messageRepository.findAll().spliterator(), false)
                .map(message -> new Message(message.getId(),
                        message.getMessageKey(),
                        // list localizations
                        StreamSupport
                                .stream(localizationRepository.findAllByObjectIdAndLocalizedType(message.getId(), LocalizedType.MESSAGE).spliterator(),
                                        false)
                                .map(localization -> new MessageLocalization(localization.getId(),
                                        localization.getLanguage(),
                                        localization.getBaseText(),
                                        localization.getShortText(),
                                        localization.getLongText(),
                                        localization.getOrderBy()))
                                .collect(Collectors.toList()),
                        // list categories
                        StreamSupport.stream(messageCategoryRepository.findAllByMessageId(message.getId()).spliterator(), false)
                                .map(msgCategory -> new MessageCategory(msgCategory.getId(), msgCategory.getMessageId(), msgCategory.getCategoryId()))
                                .collect(Collectors.toList())

                )).collect(Collectors.toList());

Upvotes: 0

Holger
Holger

Reputation: 298103

Consider the initialization of the localizations list as part of the Message object’s initialization:

public List<Message> getAllMessages() {
    return StreamSupport.stream(messageRepository.findAll().spliterator(), false)
        .map(message -> {
            Message newMessage = new Message(message.getId(), message.getMessageKey());
            localizationRepository.findAllByObjectIdAndLocalizedType(message.getId(), LocalizedType.MESSAGE)
                .forEach(localization -> {
                    newMessage.getLocalizations().add(
                        new MessageLocalization(localization.getId(),
                            localization.getLanguage(),
                            localization.getBaseText(),
                            localization.getShortText(),
                            localization.getLongText(),
                            localization.getOrderBy()));
            });
            return newMessage;
        })
        .collect(Collectors.toList());
}

This naturally leads to the conclusion that the code could be even simpler if the Message constructor would accept a list of localizations…

Upvotes: 1

Related Questions