Core java - Advance Topics
  • Welcome
  • Schedule
  • 1) Exception Handling
    • 1) Introduction to Exception Handling
    • 2) Categories of Exceptions
    • 3) Creating a method that throws an exception
    • 4) Creating Custom Exception Classes
    • 5)What happens when an exception is thrown?
      • 5.1) Creating try-catch-finally blocks
      • 5.2) Using a method that throws a checked exception
      • 5.3) Using a method that throws a runtime exception
      • 5.4) Using a method that throws an error
      • 5.5) Will a finally block execute even if the catch block defines a return statement?
      • 5.6) What happens if both a catch and a finally block define return statement?
      • 5.7) What happens if a finally block modifies the value returned from a catch block?
      • 5.8) Can a try block be followed only by a finally block?
      • 5.9) Does the order of the exceptions caught in the catch blocks matter?
      • 5.10) Can I rethrow an exception or the error I catch?
      • 5.11) Can I declare my methods to throw a checked exception instead of handling it?
      • 5.12) I can create nested loops, so can I create nested try-catch blocks too?
      • 5.13) Should I handle errors?
    • 6) Best Practices
    • 7) Cheat Sheet
    • 8) Problems
  • 2) Wrapper Classes and Enums
    • 2.1) Creating objects of the wrapper classes
    • Enums
  • 3) Inner Classes
    • 3.1) Static nested class (also called static inner class)
    • 3.2) Inner class (also called member class)
    • 3.3) Anonymous inner class
    • 3.4) Method local inner classes
    • CheatSheet
  • 4) Generics
    • Multiple Type parameters in Generic classes
    • Inheritance using Generics
    • Generic interfaces
    • Generic Methods
    • Bounded type parameters
    • Applications
  • 5) Equals and Hashcode
    • Problems
  • CompareTo method overview
  • Basic DS
    • 1) Simple Array List
    • 2) Simple HashMap
  • 5) Collections Framework - Part 1
    • Introducing the collections framework
    • Working with the Collection interface
      • The core Collection interface
      • Methods of the Collection interface
    • Creating and using List, Set, and Deque implementations
      • List interface and its implementations
      • Iterators
      • Sorting List using custom sorting technique
      • Comparable Interface
      • Custom Sorting using comparator
      • ArrayList - Examples and practice problems
    • Stack
    • Linked List
    • LinkedList Operations
  • 6) Collections Framework - Part 2
    • Sets
      • Set Types
      • Array to Set (vice versa)
    • Maps
    • TreeMap
    • Autoboxing And Unboxing
  • Collections Framework - Part 3
    • Basics : DS , Number System
    • Internal Working
      • HashMap
      • HashSet
  • 7) Reflection API
  • 8) Annotations
  • 9) Reading Input From Various Sources
    • File Handling
    • Reading From Xml
    • Reading From JSON
  • 10) Multi-threading (Concurrency)
    • Protect shared data
    • Thread-safe access to shared data
  • 11) Design Patterns
    • Singleton
    • DI
  • 12) Internal Working of JVM
  • 13) Garbage Collection
  • 14) More on Strings (Buffer and Builder)
  • 15) Cloning and Immutable Class
    • 16) Serialization And Deserialization
    • Untitled
  • JAVA 8
    • Interface Changes
    • Lambda
    • Method Ref
    • Optional
    • Streams
    • Predicates
  • Practice Tests
    • Test - Collections
    • OOPS
    • S-OOPS
Powered by GitBook
On this page
  • Java 8 Stream API
  • 1. Java Stream vs. Collection
  • 2. Different ways to create streams
  • Stream, filter , map ,reduce , collectors
  • Readings:

Was this helpful?

  1. JAVA 8

Streams

PreviousOptionalNextPredicates

Last updated 5 years ago

Was this helpful?

Java 8 Stream API

By Lokesh Gupta | Filed Under:

A Stream in Java can be defined as a sequence of elements from a source that supports aggregate operations on them. The source here refers to a or who provides data to a Stream.

Stream keeps the ordering of the data as it is in the source. The aggregate operations or bulk operations are operations which allow us to express common manipulations on stream elements easily and clearly.

java_8_lambdas
Table of Contents

1. Streams vs. Collections
2. Different ways to create streams
3. Converting streams to collections
4. Core stream operations
    4.1. Intermediate operations
    4.2. Terminal operations
5. Short-circuit operations
6. Parallelism

Before going ahead, it is important to learn that Java 8 Streams are designed in such a way that most of the stream operations returns streams only. This help us creating chain of the stream operations. This is called as pipe-lining. I will use this term multiple times in this post, so keep it in mind.

1. Java Stream vs. Collection

All of us have watch online videos on youtube or some other such website. When you start watching video, a small portion of file is first loaded into your computer and start playing. You don’t need to download complete video before start playing it. This is called streaming. I will try to relate this concept with respect to collections and differentiate with Streams.

At the basic level, the difference between Collections and Streams has to do with when things are computed. A Collection is an in-memory data structure, which holds all the values that the data structure currently has—every element in the Collection has to be computed before it can be added to the Collection. A Stream is a conceptually fixed data structure, in which elements are computed on demand. This gives rise to significant programming benefits. The idea is that a user will extract only the values they require from a Stream, and these elements are only produced—invisibly to the user—as and when required. This is a form of a producer-consumer relationship.

In java, java.util.Stream represents a stream on which one or more operations can be performed. Stream operations are either intermediate or terminal. While terminal operations return a result of a certain type, intermediate operations return the stream itself so you can chain multiple method calls in a row. Streams are created on a source, e.g. a java.util.Collection like lists or sets (maps are not supported). Stream operations can either be executed sequential or parallel.

Based on above points, if we list down the various characteristics of Stream, they will be as follows:

  • Not a data structure

  • Designed for lambdas

  • Do not support indexed access

  • Can easily be outputted as arrays or lists

  • Lazy access supported

  • Parallelizable

2. Different ways to create streams

Below is the most popular different ways to build streams from collections.

package com.gs.iilp.corejava.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Stream1 {
	public static void main(String[] args) {

		// 1) Empty stream
		System.out.println("1) Empty stream");
		Stream<String> emptyStream = Stream.empty();

		emptyStream.forEach(s -> {
			System.out.println(s);
		});

		// 2) Stream.of(val1, val2, val3….)
		System.out.println("2) Stream.of(val1, val2, val3….)");
		Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8);

		stream.forEach(i -> {
			System.out.println(i);
		});

		// 3) Stream.of(arrayOfElements) way 1
		System.out.println("3) Stream.of(arrayOfElements) way 1");
		Stream<Double> doubleStream = Stream.of(new Double[] { 3.23, 6.56, 676.90 });

		doubleStream.forEach(i -> {
			System.out.println(i);
		});

		// 4) Stream.of(arrayOfElements) way 2
		System.out.println("4) Stream.of(arrayOfElements) way 2");
		Long[] numbers = { 435435435l, 543543l, 435345435l, 435435435l, 35435435l };
		Stream<Long> numberStream = Arrays.stream(numbers);

		numberStream.forEach(i -> {
			System.out.println(i);
		});

		// 5) Stream of Collection
		System.out.println("5) Stream of Collection ");
		List<Integer> list = new ArrayList<Integer>();

		for (int i = 1; i < 10; i++) {
			list.add(i);
		}

		Stream<Integer> listStream = list.stream();
		listStream.forEach(p -> System.out.println(p));

		// 6) Stream.builder()
		/*
		 * When builder is used the desired type should be additionally specified in the
		 * right part of the statement, otherwise the build() method will create an
		 * instance of the Stream<Object>:
		 */
		// Stream<String> namesStream =
		// Stream.builder().add("Mohit").add("Rohit").add("Sumit").build();
		System.out.println("6) Stream.builder() ");

		Stream<String> namesStream = Stream.<String>builder().add("Mohit").add("Rohit").add("Sumit").build();
		namesStream.forEach(s -> System.out.println(s));

		// 7) Stream.generate()
		System.out.println("7) Stream.generate()");
		// Stream<Integer> numStreamThroughGenerate = Stream.generate(() -> 2); will
		// give infinite numbers
		Stream<Integer> numStreamThroughGenerate = Stream.generate(() -> 2).limit(4);
		numStreamThroughGenerate.forEach(s -> System.out.println(s));

		// 8) Stream.iterate()
		System.out.println("8) Stream.generate()");
		Stream<Long> numStreamThroughIterate = Stream.iterate(4l, n -> n + 2l).limit(5);
		numStreamThroughIterate.forEach(s -> System.out.println(s));

		// 9) Stream.iterate() exclusive range
		System.out.println("9) Stream.iterate() exclusive range");
		IntStream primitiveIntStream = IntStream.range(3, 6);
		primitiveIntStream.forEach(p -> System.out.println(p));

		// 10) Stream.iterate() inclusive range
		System.out.println("10) Stream.iterate() inclusive range");
		IntStream primitiveIntStreamInc = IntStream.range(3, 6);
		primitiveIntStreamInc.forEach(p -> System.out.println(p));

	}

}

Stream, filter , map ,reduce , collectors

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

class Student {
	private int id;
	private String name;
	private int age;

	public Student(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

}

public class Stream1 {
	public static void main(String[] args) {

		List<Student> students = Arrays.asList(new Student[] { new Student(1, "Mohit", 25), new Student(3, "Rohit", 27),
				new Student(45, "Hohit", 15) });

		// Filter
		students.stream().filter((st) -> (st.getName().startsWith("M") && st.getAge() == 25))
				.forEach(System.out::println);

		// Map (Convert Student objects to String of names where age is divisible by 5)
		students.stream().filter(st -> st.getAge() % 5 == 0).map(Student::getName).forEach(System.out::println);

		// Collectors Receive in a collection like List<String>
		List<String> studentNamesList = students.stream().filter(st -> st.getAge() % 5 == 0).map(Student::getName)
				.collect(Collectors.toList());

		System.out.println(studentNamesList);

		// Reduce names string to a single list with # in between
		Optional<String> str = students.stream().filter(st -> st.getAge() % 5 == 0).map(Student::getName)
				.reduce((s1, s2) -> (s1 + "#" + s2));
		System.out.println(str.get());

		// Ex:2 reduce
		String[] randomStatements = { "This", "is", "amazing" };

		String finalName = Arrays.stream(randomStatements).reduce((s1, s2) -> (s1 + "," + s2)).get();
		System.out.println(finalName);

		// Ex3 :

		Integer totalAge = students.stream().map(Student::getAge).reduce((a, b) -> (a + b)).get();
		System.out.println(totalAge);
	}

}
Student [id=1, name=Mohit, age=25]
Mohit
Hohit
[Mohit, Hohit]
Mohit#Hohit
This,is,amazing
67

Readings:

Java 8
Collections
Arrays
LogoStream.reduce() in Java with examples - GeeksforGeeksGeeksforGeeks
LogoJava 8 Stream reduce() ExampleConcretePage
LogoGuide to Stream.reduce() | BaeldungBaeldung