Consists of..
Compared to collections..
A collection is a set of values spread out in space, a stream is a set of values spread out in time.
// Creating Streams
Collection.stream()
Stream.of(T...)
Stream.generate(Supplier)
Stream.iterate(T, UnaryOperator)
Arrays.stream(T[])
// Transformations
Stream.filter(Predicate)
Stream.map(Function)
Stream.flatMap(Function)
Stream.skip(long)
Stream.limit(long)
Stream.distinct()
Stream.sorted(Comparator)
Stream.mapToInt(ToIntFunction)
Stream.flatMapToInt(Function)
// Terminations
Stream.count()
Stream.min(Comparator)
Stream.max(Comparator)
Stream.findAny()
Stream.anyMatch(Predicate)
Stream.toArray(IntFunction)
Stream.collect(Collector)
Collection<Integer> ints = Arrays.asList(new Integer(1), new Integer(2));
ints.stream(); // Stream<Integer>
// passing an array of Integer objects
Stream.of(new Integer[]{new Integer(1), new Integer(2)}); // Stream<Integer>
// harnessing varargs
Stream.of(new Integer(1), new Integer(2)); // Stream<Integer>
// Generating an infinite Stream<Integer>,
// initialised with random values between 1 and 10
Stream.generate(() -> new Integer(ThreadLocalRandom.current().nextInt(1, 11)));
// An infinite Stream of Integers, initialised with incremented values
Stream.iterate(new Integer(1), i -> new Integer(i.val + 1)); // Stream<Integer>
Arrays.stream(new Integer[]{new Integer(1), new Integer(2)}); // Stream<Integer>
// Arrays.stream(new Integer(1), new Integer(2)) will not work!
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.Arrays.*;
import static java.util.stream.Stream.*;
class Foo {
void foo() {
Stream<Foo> foo;
foo = of(new Foo(), new Foo());
// foo = stream(new Foo(), new Foo()); not possible
foo = of(new Foo[]{new Foo(), new Foo()});
foo = stream(new Foo[]{new Foo(), new Foo()});
Stream<Integer> integerStream;
integerStream = of(1, 2);
// integerStream = stream(1, 2); not possible
integerStream = of(new Integer[]{1, 2});
integerStream = stream(new Integer[]{1, 2});
Stream<int[]> intArrayStream = of(new int[]{1, 2}); // count = 1!
IntStream intStream = stream(new int[]{1, 2}); // count = 2!
}
}
Stream.of(1, 2).filter(i -> i < 2); // Only Integer[1] remains
Stream
using the provided Function
Stream
with the return type of the provided Function
Stream.of(1, 2).map(i -> String.valueOf(i)); // Stream<String>
import java.util.stream.Stream;
class Foo {
String foo, bar;
Foo(String foo, String bar) {this.foo = foo; this.bar = bar;}
void flatMap() {
// returns Stream<String> : ["foo", "bar", "baz", "qux"]
Stream.of(new Foo("foo", "bar"), new Foo("baz", "qux"))
.flatMap(f -> Stream.of(f.foo, f.bar));
}
}
Stream.iterate(new Integer(1), i -> new Integer(i.val + 1)).skip(2).limit(2);
Stream.of(1, 2).distinct();
Reference: Stream.sorted(Comparator)
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
class Foo {
List<String> strings;
Integer val;
Foo(Integer val, List<String> strings) {
this.val = val;
this.strings = strings;
}
void foo(){
// Initial data
Foo foo = new Foo(4, Arrays.asList("foo"));
Foo fooBar = new Foo(3, Arrays.asList("foo", "bar"));
Foo fooBarBaz = new Foo(2, Arrays.asList("foo", "bar", "baz"));
Foo fooBarBazQx = new Foo(1, Arrays.asList("foo", "bar", "baz", "qux"));
List<Foo> fooList = Arrays.asList(foo, fooBarBazQx, fooBarBaz, fooBar);
// Sort by value
List<Foo> sorted = fooList.stream()
.sorted(Comparator.comparing(Foo::getVal))
.collect(Collectors.toList());
System.out.println(sorted);
// [[foo, bar, baz, qux], [foo, bar, baz], [foo, bar], [foo]]
// Sort by length of strings
sorted = fooList
.stream()
.sorted(Comparator.comparing(Foo::getStrings,
Comparator.comparing(List::size)))
.collect(Collectors.toList());
System.out.println(sorted);
// [[foo], [foo, bar], [foo, bar, baz], [foo, bar, baz, qux]]
}
List<String> getStrings() {
return strings;
}
Integer getVal() {
return val;
}
public String toString() {
return strings.toString();
}
}
// Do not try on an infinite stream!
Stream.of(1, 2).count(); // 2
import java.util.Comparator;
import java.util.stream.Stream;
class Foo implements Comparable<Foo> {
int foo;
Foo(int foo) {this.foo = foo;}
void foo() {
Stream<Foo> fooStream =
Stream.of(new Foo(1), new Foo(2), new Foo(3), new Foo(4));
// Using Comparator.naturalOrder
fooStream.min(Comparator.naturalOrder()); // Optional[Foo[1]]
}
@Override
public int compareTo(Foo o) {
return Integer.compare(foo, o.foo);
}
}
import java.util.Comparator;
import java.util.stream.Stream;
class Foo {
int foo;
Foo(int foo) {this.foo = foo;}
void foo() {
Stream.of(new Foo(1), new Foo(2))
.max(Comparator.comparing(f -> f.foo)); // Optional[Foo[2]]
}
}
import java.util.Comparator;
import java.util.stream.Stream;
class Foo {
void foo() {
// All of the examples above return Optional[foo]
// Using Comparator.comparing
Stream.of("foo", "bar")
.max(Comparator.comparing(s -> s.toLowerCase()));
// Using Method References
Stream.of("foo", "bar").max(String::compareToIgnoreCase);
// Providing custom method definition with Lambdas
Stream.of("foo", "bar").max((o1, o2) -> o1.compareToIgnoreCase(o2));
}
}
// findAny
Stream.of(1, 2, 3 ,4).findAny(); // Optional[1|2|3|4]
// anyMatch
Stream.of(new Foo(1), new Foo(2), new Foo(3), new Foo(4))
.anyMatch(f -> f.foo < 2); // true
Stream.of(1).toArray(Integer[]::new); // Integer[]{1}
Stream.of(1).collect(Collectors.toList()); // List<Integer>
Stream.unordered()
import static java.util.concurrent.ThreadLocalRandom.current;
import static java.lang.Integer.MAX_VALUE;
import java.util.stream.Stream;
/**
* A program demonstrating the execution times of parallel and unordered streams
* by finding number of distinct integers in a randomly generated stream of ints
*/
class App {
public static void main(String[] args) {
int div = 32;
long start;
// Initial..
start = System.currentTimeMillis();
Stream.generate(() -> current().nextInt(0, Math.floorDiv(MAX_VALUE, 4)))
.limit(MAX_VALUE / div).distinct().count();
log(start, System.currentTimeMillis());
// Took 71467 milliseconds.
// unordered
start = System.currentTimeMillis();
Stream.generate(() -> current().nextInt(0, Math.floorDiv(MAX_VALUE, 4)))
.limit(MAX_VALUE / div).unordered().distinct().count();
log(start, System.currentTimeMillis());
// Took 59521 milliseconds.
// parallel
start = System.currentTimeMillis();
Stream.generate(() -> current().nextInt(0, Math.floorDiv(MAX_VALUE, 4)))
.limit(MAX_VALUE / div).parallel().distinct().count();
log(start, System.currentTimeMillis());
// Took 47279 milliseconds.
// unordered and parallel
start = System.currentTimeMillis();
Stream.generate(() -> current().nextInt(0, Math.floorDiv(MAX_VALUE, 4)))
.limit(MAX_VALUE / div).unordered().parallel().distinct().count();
log(start, System.currentTimeMillis());
// Took 31375 milliseconds.
}
static void log(long start, long end) {
println(join(" ", "Took", valueOf((end - start)), "milliseconds."));
}
}
import java.util.List;
import java.util.stream.Collectors;
import static java.util.concurrent.ThreadLocalRandom.current;
import static java.util.stream.IntStream.iterate;
class RandomWalk {
void randomWalk() {
List<Integer> randomWalk =
iterate(0, i -> current().nextBoolean() ? i - 1 : i + 1)
.boxed()
.limit(10)
.collect(Collectors.toList()); // [0, -1, 0, 1, 2, 3, 4, 5, 4, 5]
}
}
// Generate 1000 random numbers between 0 and 100
// Store in a LinkedList
IntStream.generate(() -> ThreadLocalRandom.current().nextInt(0, 100))
.limit(1000)
.boxed()
.collect(Collectors.toCollection(LinkedList::new));