CoreJava Java8

Features of Java 8 – Complete Overview with Examples

Features of Java 8 – Complete Overview with Examples

Java 8 (released March 2014) is the most significant Java release since Java 5. It introduced functional programming constructs, a completely new Date/Time API, and major performance improvements to the JVM. This post gives a quick overview of every major feature, with links to detailed posts for each one.

Java 8 Features at a Glance

# Feature Package / Location Purpose
1 Lambda Expressions Language syntax Write anonymous functions concisely
2 Functional Interfaces java.util.function Standard interfaces for lambdas (Predicate, Function, Consumer, Supplier)
3 Stream API java.util.stream Process collections with filter, map, reduce, collect
4 Default Methods Language syntax (interfaces) Add method implementations to interfaces without breaking existing classes
5 Method References Language syntax Shorthand for lambdas that call a single method
6 Optional java.util.Optional Avoid NullPointerException — explicit absent value handling
7 New Date/Time API java.time Replace broken java.util.Date with immutable, thread-safe classes
8 Nashorn JavaScript Engine javax.script Run JavaScript code inside the JVM (replaced Rhino)
9 Base64 Encoding/Decoding java.util.Base64 Built-in Base64 support without external libraries
10 forEach() on Collections java.lang.Iterable Iterate collections with a lambda instead of a for loop

1. Lambda Expressions

Lambdas let you write a function inline without a class or method name. The syntax is: (parameters) -> expression

// Old way — anonymous class
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Running without lambda");
    }
};

// Java 8 — lambda
Runnable r2 = () -> System.out.println("Running with lambda");

r1.run();
r2.run();
Running without lambda
Running with lambda

2. Functional Interfaces

A functional interface has exactly one abstract method. Java 8 ships with many in java.util.function:

import java.util.function.*;

Predicate<String>  isLong   = s -> s.length() > 5;
Function<String, Integer> len = String::length;
Consumer<String>   print    = System.out::println;
Supplier<String>   hello    = () -> "Hello, Java 8!";

System.out.println(isLong.test("Lambda"));    // false
System.out.println(len.apply("Java8"));       // 5
print.accept("Consumer example");             // Consumer example
System.out.println(hello.get());              // Hello, Java 8!

3. Stream API

Streams let you process collections in a declarative, pipeline style:

import java.util.*;
import java.util.stream.*;

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Filter even numbers, square them, collect to list
List<Integer> result = numbers.stream()
    .filter(n -> n % 2 == 0)       // 2,4,6,8,10
    .map(n -> n * n)               // 4,16,36,64,100
    .collect(Collectors.toList());

System.out.println(result);        // [4, 16, 36, 64, 100]

// Sum all numbers
int sum = numbers.stream().mapToInt(Integer::intValue).sum();
System.out.println("Sum: " + sum); // Sum: 55

4. Default Methods in Interfaces

Interfaces can now have concrete method implementations using the default keyword:

interface Greeting {
    String greet(String name);

    default String greetLoud(String name) {
        return greet(name).toUpperCase();
    }
}

class Hello implements Greeting {
    @Override
    public String greet(String name) {
        return "Hello, " + name + "!";
    }
}

Greeting g = new Hello();
System.out.println(g.greet("Ravi"));      // Hello, Ravi!
System.out.println(g.greetLoud("Ravi")); // HELLO, RAVI!

5. Method References

When a lambda just calls an existing method, use a method reference (::) for cleaner code:

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

// Lambda
names.forEach(name -> System.out.println(name));

// Method reference — equivalent, shorter
names.forEach(System.out::println);

// Static method reference
names.stream()
     .map(String::toUpperCase)
     .forEach(System.out::println);

6. Optional

Optional wraps a value that may or may not be present, forcing you to handle the absent case:

import java.util.Optional;

Optional<String> name = Optional.of("Java 8");
Optional<String> empty = Optional.empty();

System.out.println(name.get());                    // Java 8
System.out.println(name.isPresent());              // true
System.out.println(empty.orElse("Default"));       // Default
System.out.println(name.map(String::length).get()); // 6

7. New Date/Time API

The new java.time package replaces the error-prone java.util.Date:

import java.time.*;
import java.time.format.DateTimeFormatter;

LocalDate today     = LocalDate.now();
LocalTime now       = LocalTime.now();
LocalDateTime dt    = LocalDateTime.now();
ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));

System.out.println("Date:  " + today);
System.out.println("Time:  " + now);
System.out.println("Both:  " + dt);
System.out.println("Zoned: " + zoned);

// Formatting
String formatted = dt.format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"));
System.out.println("Formatted: " + formatted);

8. Base64 Encoding/Decoding

import java.util.Base64;

String original  = "Java 8 Base64 Example";
String encoded   = Base64.getEncoder().encodeToString(original.getBytes());
byte[] decoded   = Base64.getDecoder().decode(encoded);

System.out.println("Original: " + original);
System.out.println("Encoded:  " + encoded);
System.out.println("Decoded:  " + new String(decoded));
Original: Java 8 Base64 Example
Encoded:  SmF2YSA4IEJhc2U2NCBFeGFtcGxl
Decoded:  Java 8 Base64 Example

9. forEach() on Collections

import java.util.*;

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob",   87);
scores.put("Carol", 92);

// Old way
for (Map.Entry<String, Integer> e : scores.entrySet()) {
    System.out.println(e.getKey() + ": " + e.getValue());
}

// Java 8 — forEach with lambda
scores.forEach((name, score) ->
    System.out.println(name + ": " + score));

Summary

Java 8's most impactful additions are Lambda Expressions, the Stream API, and the new Date/Time API. Lambdas and streams enable a functional, pipeline-oriented style that dramatically reduces boilerplate — a 10-line for-loop becomes a 3-line stream chain. The new java.time package finally makes date and time handling correct, immutable, and thread-safe. Optional prevents NullPointerException at the API boundary. Together these features modernized Java and make it competitive with languages like Scala and Kotlin for everyday programming tasks.

Topics: CoreJava Java8
← Newer Post Older Post →

Comments

https://www.blogger.com/comment/frame/6690124484600543990?po=507246531704538312&hl=en&saa=85391&origin=https://www.java9r.com