Java 8+ Functional Programming :: Collections & Streams (2)

Structure of Java Stream Operations

Any Java Stream operation has to have three components to make it work:

  • a source
  • one or more intermediate operations
  • terminal operation

Source –> Intermediate Operation 1 –> Intermediate Operation 2 –> … –> Terminal Operation

  • Source – the source of data from which a stream is generated. It could be a collection, an array, a Supplier instance generating infinite stream elements and so on.
  • Intermediate Operations (Stream-producing) – are invoked on a Stream instance and after they finish their processing they give a Stream instance as output. Actual processing doesn’t start till a terminal operation is invoked – intermediate operations are always lazy. Such a “lazy” operation of Streams gives Java designers the ability to optimize and process Stream operation execution in a variety of ways.
  • Terminal Operations (value- or side-effect-producing) – do not return a Stream as their output. Terminal operations can return any value, or even no value (void).

Types of Intermediate Operations

  • Stateful Intermediate Operations – are those which maintain information from a previous invocation internally – aka state to be used again in a future invocation of the method.
  • Stateless Intermediate Operations – are the opposite of stateful and do not store any state across passes (filter(), map(), findAny(),…).

Stream intermediate operations:

  • filter()
  • map()
  • flatMap()
  • distinct()
  • sorted()
  • peek()
  • limit()
  • skip()

Stream terminal operations:

  • toArray()
  • collect()
  • count()
  • reduce()
  • forEach()
  • forEachOrdered()
  • min()
  • max()
  • anyMatch()
  • allMatch()
  • noneMatch()
  • findAny()
  • findFirst()

Creating Java Streams

Stream.of()

Stream stream = Stream.of(1,2,3,4);
Stream stream = Stream.of(new Integer[]{1,2,3,4}); 

 

From Arrays

String[] stringArr = {"a", "b", "c"};
Stream stream = Arrays.stream(stringArr);

 

From Collection

Collection collection = Arrays.asList("a", "b", "c");
Stream streamOfCollection = collection.stream();

 

Stream of Primitives
Java 8 offers a possibility to create streams out of three primitive types: int, long and double. Three new special interfaces were created: IntStream, LongStream, DoubleStream.

IntStream intStream = IntStream.range(1, 3);
IntStream intStream = IntStream.of(2, 4, 6, 1, 5, 9);

LongStream longStream = LongStream.rangeClosed(1, 3);
LongStream longStream = LongStream.of(1L, 2L, 3L); 

Random random = new Random();
DoubleStream doubleStream = random.doubles(3);

DoubleStream doubleStream = DoubleStream.of(1.2, 1.34);
//doubleStream.forEach(e -> System.out.println(e));

 

Stream.builder()

	public static void main(String[] args) {
		Stream stream = Stream.builder().add("a").add("b").add("c").build();
		stream.forEach(e -> System.out.println(e));
	}

 

Stream.generate()

	public static void main(String[] args) {
		Stream stream = Stream.generate(() -> "element").limit(5);
		stream.forEach(e -> System.out.println(e));
	}

As the resulting stream is infinite, developer should specify the desired size or the generate() method will work until it reaches the memory limit.

 

Stream.iterate()
Another way of creating an infinite stream is by using the iterate() method:

	public static void main(String[] args) {
		Stream stream = Stream.iterate(10, n -> n + 4).limit(5);
		stream.forEach(e -> System.out.println(e));
	}

 

This entry was posted in functional interface, functional programming, java stream, lambda, lambda expression and tagged , , , , . Bookmark the permalink.

Leave a Reply