Java 8 APIs & Features

Java 8 is a revolutionary Long-Term Support (LTS) release that transformed Java programming by introducing lambda expressions, the Stream API, and functional programming paradigms. This landmark release remains one of the most widely adopted Java versions, setting the foundation for modern Java development with its powerful collection processing capabilities and enhanced developer productivity features.

Released: March 2014
Long-Term Support (LTS)
Long-Term Support

Java 8 Overview

Release Information

Release Date:

March 2014

Support Type:
Long-Term Support (LTS)

Quick Summary

Java 8 is a revolutionary Long-Term Support (LTS) release that transformed Java programming by introducing lambda expressions, the Stream API, and functional programming paradigms. This landmark release remains one of the most widely adopted Java versions, setting the foundation for modern Java development with its powerful collection processing capabilities and enhanced developer productivity features.

Top Features

  • Lambda Expressions and Functional Interfaces
  • Stream API for collection processing
  • Optional class to handle null values
  • New Date and Time API (JSR 310)
  • Default methods in interfaces
  • Method references and constructor references

API Examples

forEach() method in Iterable interface

Enhanced iteration over collections using lambda expressions and method references.

List<String> list = Arrays.asList("A", "B", "C");
// Using lambda expression
list.forEach(item -> System.out.println(item));
// Using method reference
list.forEach(System.out::println);

default and static methods in Interfaces

Interfaces can now have default and static methods with implementations.

interface MyInterface {
    default void defaultMethod() {
        System.out.println("Default method");
    }
    static void staticMethod() {
        System.out.println("Static method");
    }
}

class MyClass implements MyInterface {}

MyClass obj = new MyClass();
obj.defaultMethod(); // Output: Default method
MyInterface.staticMethod(); // Output: Static method

Functional Interfaces and Lambda Expressions

Lambda expressions in Java 8 enable functional programming by allowing you to treat functionality as a method argument or to create concise anonymous functions. A functional interface is an interface with just one abstract method, and lambda expressions can be used to instantiate them. This makes code more readable and enables powerful operations with the Stream API and other features.

// Functional Interface
interface MyFunctionalInterface {
    void myMethod();
}

// Lambda Expression implementing the interface
MyFunctionalInterface f = () -> System.out.println("MyMethod");
f.myMethod(); // Output: MyMethod

// Example with built-in functional interface and lambda
List<String> list = Arrays.asList("A", "B", "C");
list.forEach(item -> System.out.println(item)); // Output: A B C

Java Stream API for Bulk Data Operations on Collections

Functional-style processing of collections. Process collections of objects in a functional style for filtering, mapping, and reducing data.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// Filter names starting with 'A' and convert to uppercase
List<String> result = names.stream()
    .filter(name -> name.startsWith("A"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// Parallel processing
long count = names.parallelStream()
    .filter(name -> name.length() > 3)
    .count();

// Simple mapping example
List<String> upper = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
// upper = ["ALICE", "BOB", "CHARLIE", "DAVID"]

Java Time API

A new, comprehensive date and time API for easier and more accurate time calculations.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

LocalDate today = LocalDate.now();
System.out.println(today); // e.g., 2024-07-13

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
System.out.println(today.format(formatter)); // e.g., 13/07/2024

Collection API improvements

New methods and enhancements for working with collections more efficiently.

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.replaceAll(String::toLowerCase); // ["a", "b"]
list.removeIf(s -> s.equals("a")); // ["b"]

Concurrency API improvements

Better support for parallelism and asynchronous programming.

ExecutorService executor = Executors.newWorkStealingPool();
executor.submit(() -> System.out.println("Task executed in parallel"));
executor.shutdown();

Java IO improvements

Improvements to the IO API for better performance and usability.

Files.lines(Paths.get("file.txt"))
    .forEach(System.out::println);

Java Parallel Array Sorting

The parallelSort() method is introduced in the Array class of java.util package. It uses the concept of multithreading to sort the array faster. It first divides the array into subarrays, sorted individually by multiple threads, and then merged.

import java.util.Arrays;

// Traditional sorting
int[] arr1 = {5, 8, 1, 0, 6, 9, 50, -3};
Arrays.sort(arr1);
System.out.println("Sorted array: " + Arrays.toString(arr1));

// Parallel sorting (Java 8)
int[] arr2 = {5, 8, 1, 0, 6, 9, 50, -3};
Arrays.parallelSort(arr2);
System.out.println("Parallel sorted array: " + Arrays.toString(arr2));

// Parallel sorting with range
int[] arr3 = {5, 8, 1, 0, 6, 9, 50, -3};
Arrays.parallelSort(arr3, 0, 4); // Sort only first 4 elements
System.out.println("Partial parallel sorted: " + Arrays.toString(arr3));

Optional Class

Java 8 introduced the Optional class to provide a better way to handle null values and prevent NullPointerExceptions. This container object helps developers write more robust code by explicitly handling the presence or absence of values, making null checking more elegant and reducing the risk of runtime errors.

import java.util.Optional;

// Creating Optional objects
Optional<String> optionalWithValue = Optional.of("Hello");
Optional<String> optionalEmpty = Optional.empty();
Optional<String> optionalNullable = Optional.ofNullable(null);

// Checking if value is present
if (optionalWithValue.isPresent()) {
    System.out.println("Value: " + optionalWithValue.get());
}

// Using ifPresent for cleaner code
optionalWithValue.ifPresent(value -> System.out.println("Value: " + value));

// Providing default values
String result = optionalEmpty.orElse("Default Value");
String result2 = optionalEmpty.orElseGet(() -> "Computed Default");

// Chaining operations
Optional<String> processed = optionalWithValue
    .map(String::toUpperCase)
    .filter(s -> s.length() > 3);

// Throwing exceptions for empty values
String value = optionalEmpty.orElseThrow(() -> 
    new IllegalArgumentException("Value is required"));

// Example with method chaining
public Optional<String> findUserById(Long id) {
    // Simulate database lookup
    if (id > 0) {
        return Optional.of("User " + id);
    }
    return Optional.empty();
}

// Usage
findUserById(1L)
    .map(String::toUpperCase)
    .ifPresent(System.out::println);