title: Are Clojure transducers the same concept as intermediate operations on streams in Java?
body: <p>As I was learning about transducers in Clojure it suddenly struck me what they reminded me of: Java 8 streams!</p>
  
  <blockquote>
    <p><a href="http://clojure.org/reference/transducers" rel="noreferrer"><strong>Transducers</strong> are composable algorithmic transformations. They are independent from the context of their input and output sources and specify only the essence of the transformation in terms of an individual element.</a></p>
  </blockquote>
  
  
  
  <blockquote>
    <p><a href="http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description" rel="noreferrer">A <strong>stream</strong> is not a data structure that stores elements; instead, it conveys elements from a source such as a data structure, an array, a generator function, or an I/O channel, through a pipeline of computational operations.</a></p>
  </blockquote>
  
  <p>Clojure:</p>
  
  <pre class="lang-clj prettyprint-override"><code>(def xf
    (comp
      (filter odd?)
      (map inc)
      (take 5)))
  
  (println
    (transduce xf + (range 100)))  ; =&gt; 30
  (println
    (into [] xf (range 100)))      ; =&gt; [2 4 6 8 10]
  </code></pre>
  
  <p>Java:</p>
  
  <pre class="lang-java prettyprint-override"><code>// Purposely using Function and boxed primitive streams (instead of
  // UnaryOperator&lt;LongStream&gt;) in order to keep it general.
  Function&lt;Stream&lt;Long&gt;, Stream&lt;Long&gt;&gt; xf =
          s -&gt; s.filter(n -&gt; n % 2L == 1L)
                  .map(n -&gt; n + 1L)
                  .limit(5L);
  
  System.out.println(
          xf.apply(LongStream.range(0L, 100L).boxed())
                  .reduce(0L, Math::addExact));    // =&gt; 30
  System.out.println(
          xf.apply(LongStream.range(0L, 100L).boxed())
                  .collect(Collectors.toList()));  // =&gt; [2, 4, 6, 8, 10]
  </code></pre>
  
  <p>Apart from the difference in static/dynamic typing, these seem quite similar to me in purpose and usage.</p>
  
  <p>Is the analogy with transformations of Java streams a reasonable way of thinking about transducers? If not, how is it flawed, or how do the two differ in concept (not to speak of implementation)?</p>