A Developer's Guide: Java 8 Features

We will look at the newly introduced features of Java 8 on a high level, making this version of Java a very significant one in the industry.

A Developer's Guide: Java 8 Features
Photo by Maximalfocus / Unsplash

Lambda Expressions

Lambda expressions are anonymous functions that can be used to implement a method defined by a functional interface

In simpler terms,

Think of them as a shortcut to write small functions
Instead of writing a full method, you write a quick instruction

Example: Instead of writing a whole class to sort something, you can just write (a, b) -> a.compareTo(b)

It's like giving a quick instruction rather than writing a full set of directions

Syntax

(parameters) -> expression or (parameters) -> { statements; }

Example Code
// Example 1: Without parameters
Runnable runnable = () -> System.out.println("Hello World");

// Example 2: With parameters
Comparator<String> comparator = (String a, String b) -> a.compareTo(b);

// Example 3: With multiple statements
Consumer<String> consumer = (String s) -> {
    String result = s.toUpperCase();
    System.out.println(result);
};

Stream API

Provides a sequence of elements supporting sequential and parallel aggregate operations

In simpler terms,

  • It's like an assembly line for data processing
  • You can take a list of items and work with them step by step
Example: Taking a list of names, filtering out short names, making them uppercase, and sorting them
  • You can also process things in parallel (like having multiple assembly lines working at once)
Example Code
List<String> list = Arrays.asList("a", "b", "c");

// Sequential stream
list.stream()
    .filter(s -> s.startsWith("a"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// Parallel stream
list.parallelStream()
    .filter(s -> s.startsWith("a"))
    .forEach(System.out::println);

Optional Class

A container object that may or may not contain a non-null value

In simpler terms,

  • A way to handle values that might not exist (null values)
  • Instead of getting errors when something is missing, you get a clean way to handle it
  • Like checking if a box contains something before trying to use what's inside
  • Helps prevent crashes in your program
Example Code
// Creating Optional
Optional<String> optional = Optional.of("hello");
Optional<String> empty = Optional.empty();

// Usage
optional.ifPresent(System.out::println);
String result = optional.orElse("default");
String computed = optional.orElseGet(() -> computeValue());

Default Methods in Interfaces

Allows adding new methods to interfaces without breaking existing implementations

In simpler terms,

  • Lets you add new methods to interfaces without breaking old code
  • Like adding a new feature to an existing blueprint
  • Old code keeps working, but new code can use the new features
  • Saves you from having to update all existing code when adding new features
Example Code
interface Vehicle {
    void start();
    
    // Default method
    default void stop() {
        System.out.println("Vehicle stopping...");
    }
}

class Car implements Vehicle {
    @Override
    public void start() {
        System.out.println("Car starting...");
    }
    // stop() method is inherited automatically
}

Method References

A shorthand notation for lambda expressions calling an existing method

In simpler terms,

  • An even shorter way to write lambda expressions
  • Instead of writing how to do something, you just point to an existing method
  • Like saying "do it like this" and pointing to an example
  • Makes code shorter and cleaner
Example Code
// Types of Method References:
// 1. Static Method Reference
List<String> list = Arrays.asList("1", "2", "3");
list.forEach(Integer::parseInt);  // Class::staticMethod

// 2. Instance Method Reference
String str = "hello";
Supplier<Integer> supplier = str::length;  // instance::method

// 3. Constructor Reference
Supplier<List<String>> supplier = ArrayList::new;  // Class::new

New Date and Time API

Improved date-time API addressing the shortcomings of old java.util.Date and Calendar

In simpler terms,

  • A better way to work with dates and times
  • More intuitive and less error-prone than the old system
  • Handles time zones better
  • Makes it easier to calculate time differences and dates
Example Code
// Local Date
LocalDate date = LocalDate.now();
LocalDate specificDate = LocalDate.of(2024, Month.JANUARY, 1);

// Local Time
LocalTime time = LocalTime.now();
LocalTime specificTime = LocalTime.of(12, 30);

// Local Date Time
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime specificDateTime = LocalDateTime.of(2024, Month.JANUARY, 1, 12, 30);

// Zoned Date Time
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("UTC"));

// Period and Duration
Period period = Period.between(LocalDate.of(2024, 1, 1), LocalDate.now());
Duration duration = Duration.between(LocalTime.of(12, 0), LocalTime.now());

Functional Interfaces

An interface with exactly one abstract method

In simpler terms,

  • Interfaces that have just one main method to implement
  • Like a contract that asks for just one specific task
  • Makes it easier to use lambda expressions
  • Examples include things like "compare two items" or "process one item"
Example Code
@FunctionalInterface
interface Calculator {
    int calculate(int x, int y);
    
    // Can have default methods
    default void print(int result) {
        System.out.println("Result: " + result);
    }
}

// Usage with lambda
Calculator addition = (x, y) -> x + y;
Calculator multiplication = (x, y) -> x * y;

Enhanced Collections

New methods added to Collection interfaces

In simpler terms,

  • New, easier ways to work with groups of data
  • Added simple methods to do common tasks
    • For Example,
      • Easily print all items in a list
      • Remove items that match certain conditions
      • Change all items in a list at once
Example Code
// forEach() method
List<String> list = Arrays.asList("a", "b", "c");
list.forEach(System.out::println);

// removeIf() method
List<String> modifiableList = new ArrayList<>(list);
modifiableList.removeIf(s -> s.equals("a"));

// replaceAll() method
modifiableList.replaceAll(String::toUpperCase);

These features made Java easier to use and helped developers write cleaner, more efficient code. They're like new tools in a toolbox - they help you do the same job but in a better way.

We will look deeper at all the new Java 8 features in upcoming posts. Stay tuned!