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.
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
//10Advanced 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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.