User Tools

Site Tools


java_api_8

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
java_api_8 [2016/11/02 11:08]
178.237.8.52 [Terminal Operation / Collection]
java_api_8 [2016/11/02 14:24] (current)
178.237.8.52 [Stream API]
Line 1: Line 1:
 ====== Stream API ====== ====== Stream API ======
  
-The ''​stream'' ​API is a step in the field of functional programming,​ that is a different programming style that is more declarative. It is actually much more similar to SQL than to OOP. At any rate, Java introduced the ''​Stream API''​ and the ''​lambda''​ to go in this direction.+The [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​stream/​package-summary.html#​package.description | stream API]] is a step in the field of functional programming,​ that is a different programming style that is more declarative. It is actually much more similar to SQL than to OOP. At any rate, Java introduced the ''​Stream API''​ and the ''​lambda''​ to go in this direction.
  
 ===== The pipeline ===== ===== The pipeline =====
Line 13: Line 13:
 ==== Begin ===== ==== Begin =====
  
-The beginning of the pipeline must provide the data. There are few ways to provide data: from data or by generating it.+The beginning of the pipeline must provide the data.  
 +Streams can be obtained in number of ways. Some examples include:
  
 +  *  From a ''​Collection''​ via the ''​stream()''​ and ''​parallelStream()''​ methods;
 +  *  From an array via ''​Arrays.stream(Object[]);''​
 +  *  From static factory methods on the stream classes, such as ''​Stream.of(Object[])'',​ ''​IntStream.range(int,​ int)''​ or ''​Stream.iterate(Object,​ UnaryOperator)'';​
 +  *  The lines of a file can be obtained from ''​BufferedReader.lines()'';​
 +  *  Streams of file paths can be obtained from methods in ''​Files'';​
 +  *  Streams of random numbers can be obtained from ''​Random.ints()'';​
 +  *  Numerous other stream-bearing methods in the JDK, including ''​BitSet.stream()'',​ ''​Pattern.splitAsStream(java.lang.CharSequence)'',​ and ''​JarFile.stream()''​.
 +
 +Some examples:
 <code java> <code java>
 String[] stringArr = {"​a",​ "​b",​ "​c",​ "​d"​};​ String[] stringArr = {"​a",​ "​b",​ "​c",​ "​d"​};​
Line 41: Line 51:
 </​code>​ </​code>​
  
-==== Middle ​(Elaboration) =====+==== Intermediate Operations ​(Elaboration) =====
  
 +From [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​stream/​package-summary.html#​StreamOps | javadoc]]:
 +
 +Intermediate operations return a new stream. They are always lazy; executing an intermediate operation such as filter() does not actually perform any filtering, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given predicate. Traversal of the pipeline source does not begin until the terminal operation of the pipeline is executed. ​
 ==== Terminal Operation / Collection ==== ==== Terminal Operation / Collection ====
  
-A stream is lazily created and executed. So it won't work unless you terminate it. Most common terminations are:+A stream is lazily created and executed. So it won't work unless you terminate it. Termination change the stream to something more usable like a List or a Number or whatever you need. Most common terminations are:
  
   * ''​collect()'',​ it collects the result of the stream into a mutable objects as Collection   * ''​collect()'',​ it collects the result of the stream into a mutable objects as Collection
Line 60: Line 73:
  
  
-=== ''​reduce()'' ​===+=== reduce() ===
  
 The signature is  The signature is 
 +
 +
 <code java> <code java>
-Optional<​Treduce(BinaryOperator<​T>​ accumulator)+T reduce(T identity, ​BinaryOperator<​T>​ accumulator)
 </​code>​ </​code>​
  
-It uses a ''​BinaryOperator''​ functional interface to accumulate the result. It has 2 inputs and 1 output of the same type. You can use it, for example to calculate the 'pi=3.1415' with the [[https://​en.wikipedia.org/​wiki/​Leibniz_formula_for_%CF%80 | Gregory-Leibniz series]]+It uses a ''​BinaryOperator''​ functional interface to accumulate the result, by setting an initial value (''​identity''​). It has 2 inputs and 1 output of the same type. You can use it, for example to calculate the ''pi=3.14...'' with the [[https://​en.wikipedia.org/​wiki/​Leibniz_formula_for_%CF%80 | Gregory-Leibniz series]]
  
 <code java GregoryLeibniz.java>​ <code java GregoryLeibniz.java>​
Line 81: Line 96:
   
   
- Double pi = IntStream.iterate(0,​ n -> n+1)+ Double pi = 4 * IntStream.iterate(0,​ n -> n+1)
                               .limit(limit) // limit the infinite stream                               .limit(limit) // limit the infinite stream
        .mapToDouble(v -> (double)v)        .mapToDouble(v -> (double)v)
-       .reduce(0., (a,x) -> a + (x%2==0?​1:​-1) / (2*x+1) ​ ); +       .reduce(0., ​ //​identity,​ i.e. the starting point 
- System.out.println("​pi= " + 4*pi_3); // 3.140592653839794+                                      ​(a,x) -> a + (x%2==0?​1:​-1) / (2*x+1) ​//​BinaryOperator<​Double> ​  
 +                                      ​); 
 + System.out.println("​pi= " + pi); // 3.140592653839794
         }         }
 } }
 </​code> ​ </​code> ​
  
 +There is another signature:
 <code java> <code java>
-T reduce(T identity, ​BinaryOperator<​T>​ accumulator)+Optional<​Treduce(BinaryOperator<​T>​ accumulator)
 </​code>​ </​code>​
 +by which you do not pass the ''​identity''​ and you don't get the right type ''​T''​ but an ''​Optional<​T>''​. [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​stream/​Stream.html#​reduce-U-java.util.function.BiFunction-java.util.function.BinaryOperator- | In this case the first value in the accumulator is the first value passed to it]].
 +<code java>
 +OptionalInt sum = IntStream.iterate(1,​ n->n+1)
 + .limit(3)
 + .reduce((a,​x) -> a + x);
 +
 +System.out.println("​sum " + sum.toString());​ // sum OptionalInt[6]
 +System.out.println("​sum " + sum.getAsInt());​ // sum 6
 +// notice that it sums in this way:
 +// x=1 a=1   // first value is the first element
 +// x=2 a=1+2
 +// x=3 a=3+3
 +</​code>​
 +
 +A last [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​stream/​Stream.html#​reduce-U-java.util.function.BiFunction-java.util.function.BinaryOperator- | option]] is:
 <code java> <code java>
 <U> U reduce(U identity, BiFunction<​U,?​ super T,U> accumulator,​ BinaryOperator<​U>​ combiner) <U> U reduce(U identity, BiFunction<​U,?​ super T,U> accumulator,​ BinaryOperator<​U>​ combiner)
 </​code>​ </​code>​
 +
 +Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions. Generally used with parallel streams, it is like splitting the reduction in 2 steps.
 +The identity value must be an identity for the combiner function. This means that for all u, combiner(identity,​ u) is equal to u. Additionally,​ the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:
 +
 +
 +     ​combiner.apply(u,​ accumulator.apply(identity,​ t)) == accumulator.apply(u,​ t)
 + 
 +==== collect() ====
 +
 +The [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​stream/​Stream.html#​collect-java.util.function.Supplier-java.util.function.BiConsumer-java.util.function.BiConsumer- | javadoc]] is pretty explanatory of the first signature:
 +<code java>
 +<R> R collect(Supplier<​R>​ supplier,
 +              BiConsumer<​R,?​ super T> accumulator,​
 +              BiConsumer<​R,​R>​ combiner)
 +</​code>​
 +This produces a result equivalent to:
 +
 +<code java>
 +     R result = supplier.get();​
 +     for (T element : this stream)
 +         ​accumulator.accept(result,​ element);
 +     ​return result;
 +</​code>​
 +
 +So with the ''​supplier''​ you create an object where to store the result (e.g. an ArrayList), the accumulator calls the functional interface that is a ''​BiConsumer''​ and gets 2 elements and combines them (e.g. ''​.add()''​ in an ArrayList). Lastly, if the operation is performed in parallel the combiner combines the result together in another type ''​R''​ container by using its ''​accept''​ method.
 +
 +For example, the following will accumulate strings into an ArrayList:
 +<code java>
 +
 +List<​String>​ asList = stringStream.collect(ArrayList::​new, ​
 +                                           ​ArrayList::​add,​
 +                                           ​ArrayList::​addAll);​
 +</​code>​
 +
 +The following will take a stream of strings and concatenates them into a single string:
 +<code java>
 +
 +String concat = stringStream.collect(StringBuilder::​new, ​
 +                                     ​StringBuilder::​append,​
 +                                     ​StringBuilder::​append)
 +                            .toString();​
 +</​code>​
 +
 ===== Example ===== ===== Example =====
  
java_api_8.1478084901.txt.gz · Last modified: 2016/11/02 11:08 by 178.237.8.52