Fundamentals 17 min read

Java 8 Functional Interfaces and Stream Operations: Concepts, Examples, and Advanced Collectors

This article introduces Java 8's functional interfaces and lambda expressions, explains immutable values and function composition, demonstrates common stream operations such as collect, filter, map, flatMap, max/min, count, and reduce, and shows how to use advanced collectors like groupingBy, partitioningBy, and joining with practical code examples.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Java 8 Functional Interfaces and Stream Operations: Concepts, Examples, and Advanced Collectors

Hello everyone, I'm Lei.

Important Functional Interfaces in Java

1. What is a Functional Interface

A functional interface is an interface that contains exactly one abstract method and can be used as the type of a lambda expression. When a class is annotated with @FunctionalInterface, the compiler checks that it has only one abstract method; otherwise a compilation error occurs. The interface may contain multiple default or static methods.

Note

At the end of the article you will find a link to a 7701‑page collection of interview questions from major internet companies.

1.1 Common Functional Interfaces Built into Java 8

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;
        Boolean apply2 = unaryOperator.apply(true);
        System.out.println(apply2);

        BinaryOperator
operator = (x, y) -> x * y;
        Integer integer = operator.apply(2, 3);
        System.out.println(integer);

        test(() -> "我是一个演示的函数式接口");
    }

    /**
     * Demonstrates a custom functional interface usage
     * @param worker
     */
    public static void test(Worker worker) {
        String work = worker.work();
        System.out.println(work);
    }

    public interface Worker {
        String work();
    }
}
//9龙的身高高于185吗?:false
//命运由我不由天
//9龙
//10
//false
//6
//我是一个演示的函数式接口

The above demonstrates the use of lambda expressions with built‑in functional interfaces and a custom functional interface.

Next, we explore how Java 8 integrates functional interfaces into streams to process collections efficiently. Note that the method reference syntax Student::getName is a concise way to write a lambda expression ( student -> student.getName() ).

1.2 Lazy Evaluation and Eager Evaluation

Lazy evaluation describes a Stream that only defines operations; the result is also a Stream, and the actual computation is deferred until a terminal operation is invoked (eager evaluation).

2. Common Stream Operations

2.1 collect(Collectors.toList())

Converts a Stream into a List . Similar collectors exist for Set and Map . This is an eager operation.

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);
    }
}
// Output:
//[Student{name='路飞', age=22, stature=175, specialities=null},
// Student{name='红发', age=40, stature=180, specialities=null},
// Student{name='白胡子', age=50, stature=185, specialities=null}]

2.2 filter

Filters elements based on a Predicate . This is a lazy operation.

Example: select students with height less than 180.

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>(3);
        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);
    }
}
// Output:
//[Student{name='路飞', age=22, stature=175, specialities=null}]

2.3 map

Transforms each element using a Function . This is a lazy operation.

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>(3);
        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);
    }
}
// Output:
//[路飞, 红发, 白胡子]

2.4 flatMap

Flattens multiple Streams into a single Stream. Lazy evaluation.

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

2.5 max and min

Find the maximum or minimum element using a Comparator . This is an eager operation that returns an Optional to avoid null pointers.

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>(3);
        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));
        max.ifPresent(System.out::println);
        min.ifPresent(System.out::println);
    }
}
// Output:
//Student{name='白胡子', age=50, stature=185, specialities=null}
//Student{name='路飞', age=22, stature=175, specialities=null}

2.6 count

Counts elements that satisfy a predicate, usually combined with filter . Eager evaluation.

public class TestCase {
    public static void main(String[] args) {
        List
students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));
        long count = students.stream()
                .filter(s -> s.getAge() < 45)
                .count();
        System.out.println("年龄小于45岁的人数是:" + count);
    }
}
// Output:
//年龄小于45岁的人数是:2

2.7 reduce

The reduce operation aggregates a stream into a single value. It underlies many other terminal operations such as sum , max , and min . Eager evaluation.

public class TestCase {
    public static void main(String[] args) {
        Integer reduce = Stream.of(1, 2, 3, 4)
                .reduce(0, (acc, x) -> acc + x);
        System.out.println(reduce);
    }
}
// Output:
//10

Advanced Collectors

3.1 Collecting to Values

Collectors are utilities that transform a Stream into a complex result. The examples below use static imports from java.util.stream.Collectors .

public class CollectorsTest {
    public static void main(String[] args) {
        List
students1 = new ArrayList<>(3);
        students1.add(new Student("路飞", 23, 175));
        students1.add(new Student("红发", 40, 180));
        students1.add(new Student("白胡子", 50, 185));
        OutstandingClass ostClass1 = new OutstandingClass("一班", students1);
        List
students2 = new ArrayList<>(students1);
        students2.remove(1);
        OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
        Stream
classStream = Stream.of(ostClass1, ostClass2);
        OutstandingClass biggest = biggestGroup(classStream);
        System.out.println("人数最多的班级是:" + biggest.getName());
        System.out.println("一班平均年龄是:" + averageNumberOfStudent(students1));
    }

    private static OutstandingClass biggestGroup(Stream
classes) {
        return classes.collect(maxBy(comparing(c -> c.getStudents().size())))
                .orElseGet(OutstandingClass::new);
    }

    private static double averageNumberOfStudent(List
students) {
        return students.stream().collect(averagingInt(Student::getAge));
    }
}
// Output:
//人数最多的班级是:一班
//一班平均年龄是:37.666666666666664

3.2 Collecting to Partitions

Partitions a stream into two groups (true/false) based on a Predicate using Collectors.partitioningBy .

public class PartitioningByTest {
    public static void main(String[] args) {
        // Assume List
students is initialized
        Map
> map = students.stream()
                .collect(Collectors.partitioningBy(s -> s.getSpecialities().contains(SpecialityEnum.SING)));
    }
}

3.3 Data Grouping

Groups elements by an arbitrary key using Collectors.groupingBy , similar to SQL's GROUP BY .

public class GroupingByTest {
    public static void main(String[] args) {
        // Assume List
students is initialized
        Map
> map = students.stream()
                .collect(Collectors.groupingBy(s -> s.getSpecialities().get(0)));
    }
}

3.4 String Joining

Concatenates strings from a stream using Collectors.joining . The method can accept a delimiter, a prefix, and a suffix.

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

The article concludes with links to additional resources and a promotion for a 7701‑page PDF containing interview questions from major internet companies.

JavalambdaFunctional ProgrammingFunctional InterfacestreamsJava8collectors
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

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.