Java 8 Features

Naveen AnamaneniUpdated · 4 min read

Java 8, released in March 2014, is one of the most important releases in the history of Java. It added functional programming features to the language: you can now pass behavior, such as "keep only even numbers", as a value, and process collections in a short, readable pipeline. Most modern Java code is written in this style. In this lesson, you will get an overview of every major Java 8 feature, with a small example of each. The lessons that follow cover each one in detail.

Main Features of Java 8

FeatureWhat it gives you
Lambda expressionsIt is used to write a short, unnamed function: x -> x * 2.
Functional interfacesInterfaces with one abstract method, which lambdas implement.
Method referencesA shorter form of a lambda that just calls a method: String::length.
Stream APIProcess collections with filter, map, sorted, collect and more.
OptionalA container that may or may not hold a value, to avoid null checks.
Default and static methods in interfacesInterfaces can have method bodies (see "Default, Static and Private Methods in Interfaces").
forEach methodLoop over any Iterable or Map with a lambda.
Date and Time APILocalDate, LocalDateTime, Duration and more in java.time.
Base64Built-in encoding and decoding with java.util.Base64.
Collection improvementsremoveIf, replaceAll, Map.merge, computeIfAbsent, getOrDefault.

Example: Before and After Java 8

Let's see an example that prints the names longer than six letters, in upper case and sorted, first in the old style and then with Java 8 features.

BeforeAfter.java▶ Try it
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class BeforeAfter {
    public static void main(String[] args) {
        List<String> names =
            List.of("Srihitha", "Navika", "Advitha", "Anamaneni");
 
        List<String> oldWay = new ArrayList<>();
        for (String n : names) {
            if (n.length() > 6) {
                oldWay.add(n.toUpperCase());
            }
        }
        Collections.sort(oldWay);
        System.out.println("Before Java 8: " + oldWay);
 
        List<String> newWay = names.stream()
            .filter(n -> n.length() > 6)
            .map(String::toUpperCase)
            .sorted()
            .toList();
        System.out.println("With streams:  " + newWay);
    }
}
Output
Before Java 8: [ADVITHA, ANAMANENI, SRIHITHA]
With streams:  [ADVITHA, ANAMANENI, SRIHITHA]

Explanation: Both versions give the same result. The old style needs a new list, a loop, an if and a separate sort. The stream version reads like a description of the task: filter the long names, convert them to upper case, sort them, and collect them into a list. (toList() itself was added later, in Java 16.)

Example: A Quick Tour

Tour.java▶ Try it
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
 
public class Tour {
    public static void main(String[] args) {
        Predicate<Integer> isEven = n -> n % 2 == 0;
        System.out.println("Lambda: is 10 even? " + isEven.test(10));
 
        List<String> names = List.of("Navika", "Srihitha", "Advitha");
        names.forEach(System.out::println);
 
        int total = List.of(91, 78, 85).stream()
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println("Stream sum: " + total);
 
        Optional<String> first = names.stream()
            .filter(n -> n.startsWith("Z"))
            .findFirst();
        System.out.println("Optional: " + first.orElse("no match"));
    }
}
Output
Lambda: is 10 even? true
Navika
Srihitha
Advitha
Stream sum: 254
Optional: no match

Explanation: isEven stores a lambda in a Predicate, a built-in functional interface. forEach(System.out::println) uses a method reference. The stream adds up the marks, and findFirst returns an Optional that is empty because no name starts with Z, so orElse supplies a default.

Common Mistakes

Thinking streams replace every loop. A simple loop is often clearer for small tasks with side effects.

Forgetting that streams don't change the source list. They produce a new result.

Mixing up Java 8 and later features. var (Java 10), toList() (Java 16) and records (Java 16) came after Java 8.

Interview Corner

What are the main features of Java 8?

Lambda expressions, functional interfaces (with the java.util.function package), method references, the Stream API, Optional, default and static methods in interfaces, the forEach method on Iterable and Map, the new java.time Date and Time API, Base64 encoding, new collection methods such as removeIf and Map.merge, and CompletableFuture for asynchronous programming.

Practice

  1. Easy: Rewrite a loop that prints every even number in a list using forEach and a lambda with an if.
  2. Harder: Given a list of words, use a stream to produce a sorted list of the distinct first letters in upper case.

Quick check: Java 8 features

4 questions
1When was Java 8 released?
2Which is a Java 8 feature?
3What does a stream do to its source list?
4What is Optional used for?

Key Takeaways

Was this tutorial helpful?

Lesson 302 of 482