Modern Java Features

Lambda Expressions

Basic Syntax

// Single parameter (parentheses optional)
x -> x * 2

// Multiple parameters
(x, y) -> x + y

// No parameters
() -> System.out.println("Hello")

// Block body with return
(x, y) -> {
    int sum = x + y;
    return sum * 2;
}

Functional Interfaces

// Using with Runnable
Runnable task = () -> System.out.println("Running");
new Thread(task).start();

// Comparator
Comparator<String> byLength = (a, b) -> a.length() - b.length();
list.sort(byLength);

// Custom functional interface
interface Calculator {
    int calculate(int a, int b);
}

Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;

Variable Capture

int factor = 10;
Function<Integer, Integer> multiplier = x -> x * factor;
// factor must be effectively final

Method References

Types of Method References

TypeSyntaxExample
Static methodClassName::staticMethodInteger::parseInt
Instance method (bound)instance::methodstr::length
Instance method (unbound)ClassName::methodString::toLowerCase
ConstructorClassName::newArrayList::new

Examples

// Static method reference
list.forEach(System.out::println);

// Instance method on specific object
String prefix = "Hello, ";
names.stream().map(prefix::concat).forEach(System.out::println);

// Instance method on parameter
names.stream().map(String::toUpperCase).forEach(System.out::println);

// Constructor reference
Supplier<List<String>> listFactory = ArrayList::new;
List<String> newList = listFactory.get();

Stream API

Creating Streams

// From collection
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();

// From array
String[] array = {"a", "b", "c"};
Stream<String> arrayStream = Arrays.stream(array);

// From values
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);

Intermediate Operations

// filter - keep elements matching predicate
list.stream()
    .filter(s -> s.length() > 3)
    .forEach(System.out::println);

// map - transform elements
list.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);

// sorted - sort elements
list.stream()
    .sorted()
    .forEach(System.out::println);

// limit - take first n elements
list.stream()
    .limit(5)
    .forEach(System.out::println);

// skip - skip first n elements
list.stream()
    .skip(2)
    .forEach(System.out::println);

Terminal Operations

// forEach - process each element
list.stream().forEach(System.out::println);

// count - count elements
long count = list.stream().filter(s -> s.length() > 3).count();

// collect - gather results
List<String> result = list.stream()
    .filter(s -> s.startsWith("A"))
    .collect(Collectors.toList());

Chaining Operations

List<String> result = names.stream()
    .filter(name -> name.length() > 3)
    .map(String::toUpperCase)
    .sorted()
    .limit(10)
    .collect(Collectors.toList());

Pattern Matching

instanceof with Pattern

// Traditional
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

// With pattern matching (Java 16+)
if (obj instanceof String s) {
    System.out.println(s.length());
}

// In boolean expressions
if (obj instanceof String s && s.length() > 5) {
    System.out.println(s);
}

Pattern Matching in switch

String describe(Object obj) {
    return switch (obj) {
        case Integer i -> "Integer: " + i;
        case String s -> "String of length " + s.length();
        case Double d -> "Double: " + d;
        case null -> "null value";
        default -> "Unknown type";
    };
}

Text Blocks

Multi-line Strings

String html = """
    <html>
        <body>
            <h1>Hello, World!</h1>
        </body>
    </html>
    """;

String json = """
    {
        "name": "John",
        "age": 30,
        "city": "New York"
    }
    """;

String sql = """
    SELECT id, name, email
    FROM users
    WHERE active = true
    ORDER BY name
    """;

Indentation Handling

// Leading whitespace relative to closing """ is preserved
String code = """
        public class Hello {
            public static void main(String[] args) {
                System.out.println("Hello");
            }
        }
        """;
// Minimal indentation is stripped

Local Variable Type Inference

var Keyword

// Inferred as int
var number = 42;

// Inferred as String
var message = "Hello";

// Inferred as ArrayList<String>
var list = new ArrayList<String>();

// Inferred as HashMap<String, Integer>
var map = new HashMap<String, Integer>();

// In enhanced for loop
for (var item : list) {
    System.out.println(item);
}

// In traditional for loop
for (var i = 0; i < 10; i++) {
    System.out.println(i);
}

Where var Cannot Be Used

// NOT allowed:
var x;                    // No initializer
var arr = {1, 2, 3};     // Array initializer
var lambda = x -> x + 1; // Lambda without target type
class Foo {
    var field = 10;      // Fields
}
void method(var param) {} // Parameters

Records (Java 14+)

Basic Record

// Declares immutable data carrier
record Point(int x, int y) {}

// Usage
Point p = new Point(10, 20);
int x = p.x();  // Accessor method
int y = p.y();
System.out.println(p);  // Point[x=10, y=20]

Record with Additional Methods

record Rectangle(int width, int height) {
    // Compact constructor for validation
    public Rectangle {
        if (width < 0 || height < 0) {
            throw new IllegalArgumentException("Negative dimensions");
        }
    }

    // Additional method
    public int area() {
        return width * height;
    }

    // Static factory
    public static Rectangle square(int size) {
        return new Rectangle(size, size);
    }
}

Sealed Classes (Java 17+)

Declaring Sealed Classes

public sealed class Shape permits Circle, Rectangle, Triangle {
    public abstract double area();
}

// Must be final, sealed, or non-sealed
public final class Circle extends Shape {
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

// non-sealed allows further extension
public non-sealed class Rectangle extends Shape {
    private final double width, height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double area() {
        return width * height;
    }
}

Sealed Interfaces

public sealed interface Vehicle permits Car, Truck, Motorcycle {
    void start();
}

public final class Car implements Vehicle {
    public void start() {
        System.out.println("Car starting");
    }
}