Fundamentals 15 min read

Java 8 Functional Interfaces and Stream Operations: A Comprehensive Guide

This article explains Java 8's functional interfaces, lambda expressions, method references, lazy versus eager evaluation, and demonstrates how to use the Stream API—including collect, filter, map, flatMap, max/min, count, reduce, and various collectors—to write concise, expressive code for processing collections.

Top Architect
Top Architect
Top Architect
Java 8 Functional Interfaces and Stream Operations: A Comprehensive Guide

Introduction

Java 8 introduced lambda expressions and functional programming, allowing behavior to be passed as immutable values processed by functions, which greatly simplifies collection handling.

Functional Interfaces

A functional interface contains exactly one abstract method and can be marked with @FunctionalInterface . Common built‑in interfaces are:

Interface

Method

Purpose

Predicate

test(T t)

boolean test

Consumer

accept(T t)

void consumer

Function

apply(T t)

R result

Supplier

get()

T supplier

UnaryOperator

apply(T t)

T unary

BinaryOperator

apply(T t, U u)

T binary

public class Test {
    public static void main(String[] args) {
        Predicate
predicate = x -> x > 185;
        Student student = new Student("9龙", 23, 175);
        System.out.println("9龙的身高高于185吗?:" + predicate.test(student.getStature()));
        Consumer
consumer = System.out::println;
        consumer.accept("命运由我不由天");
        Function
function = Student::getName;
        String name = function.apply(student);
        System.out.println(name);
        Supplier
supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());
        System.out.println(supplier.get());
        UnaryOperator
unaryOperator = uglily -> !uglily;
        System.out.println(unaryOperator.apply(true));
        BinaryOperator
operator = (x, y) -> x * y;
        System.out.println(operator.apply(2, 3));
        test(() -> "我是一个演示的函数式接口");
    }
    public static void test(Worker worker) {
        System.out.println(worker.work());
    }
    public interface Worker {
        String work();
    }
}
//9龙的身高高于185吗?:false
//命运由我不由天
//9龙
//10
//false
//6
//我是一个演示的函数式接口

Stream API and Lazy Evaluation

Streams describe a pipeline of operations that are evaluated lazily until a terminal operation forces eager evaluation. Typical intermediate operations include filter , map , flatMap , while terminal operations include collect , max , min , count , and reduce .

Collect to List

public class TestCase {
    public static void main(String[] args) {
        List
studentList = Stream.of(
            new Student("路飞", 22, 175),
            new Student("红发", 40, 180),
            new Student("白胡子", 50, 185)
        ).collect(Collectors.toList());
        System.out.println(studentList);
    }
}
//[Student{name='路飞', age=22, stature=175}, Student{name='红发', age=40, stature=180}, Student{name='白胡子', age=50, stature=185}]

Filter Example

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>();
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));
        List
list = students.stream()
            .filter(stu -> stu.getStature() < 180)
            .collect(Collectors.toList());
        System.out.println(list);
    }
}
//[Student{name='路飞', age=22, stature=175}]

Map Example

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>();
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));
        List
names = students.stream()
            .map(Student::getName)
            .collect(Collectors.toList());
        System.out.println(names);
    }
}
//[路飞, 红发, 白胡子]

FlatMap Example

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>();
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));
        List
studentList = Stream.of(students,
            Arrays.asList(new Student("艾斯", 25, 183), new Student("雷利", 48, 176)))
            .flatMap(List::stream)
            .collect(Collectors.toList());
        System.out.println(studentList);
    }
}
//[Student{name='路飞',...}, Student{name='红发',...}, Student{name='白胡子',...}, Student{name='艾斯',...}, Student{name='雷利',...}]

Max/Min, Count and Reduce

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>();
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));
        Optional
max = students.stream()
            .max(Comparator.comparing(Student::getAge));
        Optional
min = students.stream()
            .min(Comparator.comparing(Student::getAge));
        System.out.println(max.get());
        System.out.println(min.get());
        long count = students.stream().filter(s -> s.getAge() < 45).count();
        System.out.println("年龄小于45岁的人数是:" + count);
        Integer sum = Stream.of(1,2,3,4).reduce(0, (acc,x) -> acc + x);
        System.out.println(sum);
    }
}
//Student{name='白胡子', age=50, stature=185}
//Student{name='路飞', age=22, stature=175}
//年龄小于45岁的人数是:2
//10

Advanced Collectors

Collectors provide powerful ways to transform streams into complex results such as grouped data, partitioned data, or concatenated strings.

Grouping By

Map
> map = students.stream()
    .collect(Collectors.groupingBy(s -> s.getSpecialities().get(0)));

Partitioning By

Map
> partition = students.stream()
    .collect(Collectors.partitioningBy(s -> s.getSpecialities().contains(SpecialityEnum.SING)));

Joining Strings

String names = students.stream()
    .map(Student::getName)
    .collect(Collectors.joining(",", "[", "]"));
System.out.println(names);
//[路飞,红发,白胡子]

Conclusion

The article demonstrates how Java 8’s functional interfaces and Stream API enable concise, expressive code for collection processing; developers are encouraged to refactor existing codebases to leverage these features for clearer, more maintainable implementations.

Javalambdastreamsfunctional interfacescollectors
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.