11

I want to convert the following code using the Java 8 stream API

List<Card> deck = new ArrayList<>();
for (Suit s: Suit.values())
{
    for (Rank r: Rank.values())
    {
        deck .add(new Card(r, s));
    }
}

I came out with this

List<Card> deck = new ArrayList<>();
Arrays.stream(Suit.values())
    .forEach(s -> Arrays.stream(Rank.values())
        .forEach(r -> deck.add(new Card(r, s))));

but I don't like it as it has a side-effect on the list.

Is there another elegant way, producing a list from a stream instead maybe?

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
Francesco
  • 857
  • 1
  • 11
  • 26
  • 1
    What do you mean "*it has a side-effect on the list*"? What is the side-effect? – Vince Jan 14 '17 at 19:03
  • As the above comment points out, what does 'side-effects' mean? Also you can try to see if you can stream both lists and then collect your outcome in a new list. Bear in mind though, that it's not always efficient to use streams as they tend to have big processing overhead. – akortex Jan 14 '17 at 19:09

1 Answers1

13

Use

List<Card> cards = Arrays.stream(Suit.values())
                .flatMap(s -> Arrays.stream(Rank.values()).map(r -> new Card(r, s)))
                .collect(Collectors.toList());

Actually it is simple Cartesian product. I took an example from Cartesian product of streams in Java 8 as stream (using streams only) and adapted to your case. If you want to make third loop inside you need to use code from this answer.

Community
  • 1
  • 1
Dmitry Gorkovets
  • 2,208
  • 1
  • 10
  • 19