title: Recursive use of Stream.flatMap()
body: <p>Consider the following class:</p>
  
  <pre><code>public class Order {
  
      private String id;
  
      private List&lt;Order&gt; orders = new ArrayList&lt;&gt;();
  
      @Override
      public String toString() {
          return this.id;
      }
  
      // getters &amp; setters
  }
  </code></pre>
  
  <p>NOTE: <em>It is important to note that I <strong>cannot modify</strong> this class</em>, because I'm consuming it from an external API.</p>
  
  <p>Also consider the following hierarchy of orders:</p>
  
  <pre><code>Order o1 = new Order();
  o1.setId("1");
  Order o11 = new Order();
  o11.setId("1.1");
  Order o111 = new Order();
  o111.setId("1.1.1");
  List&lt;Order&gt; o11Children = new ArrayList&lt;&gt;(Arrays.asList(o111));
  o11.setOrders(o11Children);
  
  Order o12 = new Order();
  o12.setId("1.2");
  List&lt;Order&gt; o1Children = new ArrayList&lt;&gt;(Arrays.asList(o11, o12));
  o1.setOrders(o1Children);
  
  Order o2 = new Order();
  o2.setId("2");
  Order o21 = new Order();
  o21.setId("2.1");
  Order o22 = new Order();
  o22.setId("2.2");
  Order o23 = new Order();
  o23.setId("2.3");
  List&lt;Order&gt; o2Children = new ArrayList&lt;&gt;(Arrays.asList(o21, o22, o23));
  o2.setOrders(o2Children);
  
  List&lt;Order&gt; orders = new ArrayList&lt;&gt;(Arrays.asList(o1, o2));
  </code></pre>
  
  <p>Which could be visually represented this way:</p>
  
  <pre><code>1
  1.1
  1.1.1
  1.2
  2
  2.1
  2.2
  2.3
  </code></pre>
  
  <p>Now, I want to flatten this hierarchy of orders into a <code>List</code>, so that I get the following:</p>
  
  <pre><code>[1, 1.1, 1.1.1, 1.2, 2, 2.1, 2.2, 2.3]
  </code></pre>
  
  <p>I've managed to do it by recursively using <code>flatMap()</code> (along with a helper class), as follows:</p>
  
  <pre><code>List&lt;Order&gt; flattened = orders.stream()
      .flatMap(Helper::flatten)
      .collect(Collectors.toList());
  </code></pre>
  
  <p>This is the helper class:</p>
  
  <pre><code>public final class Helper {
  
      private Helper() {
      }
  
      public static Stream&lt;Order&gt; flatten(Order order) {
          return Stream.concat(
              Stream.of(order), 
              order.getOrders().stream().flatMap(Helper::flatten)); // recursion here
      }
  }
  </code></pre>
  
  <p>The following line:</p>
  
  <pre><code>System.out.println(flattened);
  </code></pre>
  
  <p>Produces the following output:</p>
  
  <pre><code>[1, 1.1, 1.1.1, 1.2, 2, 2.1, 2.2, 2.3]
  </code></pre>
  
  <p>So far so good. The result is absolutely correct.</p>
  
  <p>However, <a href="https://stackoverflow.com/questions/29229373/why-filter-after-flatmap-is-not-completely-lazy-in-java-streams"><strong>after reading this question</strong></a>, I had some concerns regarding the usage of <code>flatMap()</code> within a recursive method. Particularly, I wanted to know how the stream was being expanded (if that's the term). So I modified the <code>Helper</code> class and used <code>peek(System.out::println)</code> to check this:</p>
  
  <pre><code>public static final class Helper {
  
      private Helper() {
      }
  
      public static Stream&lt;Order&gt; flatten(Order order) {
          return Stream.concat(
              Stream.of(order), 
              order.getOrders().stream().flatMap(Helper::flatten))
          .peek(System.out::println);
      }
  }
  </code></pre>
  
  <p>And the output was:</p>
  
  <pre><code>1
  1.1
  1.1
  1.1.1
  1.1.1
  1.1.1
  1.2
  1.2
  2
  2.1
  2.1
  2.2
  2.2
  2.3
  2.3
  </code></pre>
  
  <p>I'm not sure if this is the output that should be printed.</p>
  
  <p>So, I wonder if it's OK to let intermediate streams contain repeated elements. Furthermore, what are the pros and cons of this approach? Is it correct, after all, to use <code>flatMap()</code> this way? Is there a better way to achieve the same?</p>