Unlock Java 8: Master Lambda Expressions and Stream API with Real Code Examples
This article introduces Java 8’s key functional programming features—lambda expressions, functional interfaces, and the Stream API—explaining concepts such as lazy and eager evaluation, and demonstrating common operations like filter, map, flatMap, collect, reduce, and grouping with clear code examples.
1. Introduction
Java 8’s biggest feature is the introduction of lambda expressions, enabling functional programming by passing behavior as immutable values processed by functions.
2. Important Functional Interfaces in Java
2.1 What is a functional interface
A functional interface has a single abstract method and can be used as the type of a lambda expression. The @FunctionalInterface annotation forces the compiler to verify this constraint. It may also contain default and static methods.
2.1.1 Common built‑in functional interfaces
public class Test {
public static void main(String[] args) {
Predicate<Integer> predicate = x -> x > 185;
Student student = new Student("9龙", 23, 175);
System.out.println("9龙的身高高于185吗?:" + predicate.test(student.getStature()));
Consumer<String> consumer = System.out::println;
consumer.accept("命运由我不由天");
Function<Student, String> function = Student::getName;
String name = function.apply(student);
System.out.println(name);
Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());
System.out.println(supplier.get());
UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;
Boolean apply2 = unaryOperator.apply(true);
System.out.println(apply2);
BinaryOperator<Integer> operator = (x, y) -> x * y;
Integer integer = operator.apply(2, 3);
System.out.println(integer);
test(() -> "我是一个演示的函数式接口");
}
/** 演示自定义函数式接口使用 */
public static void test(Worker worker) {
String work = worker.work();
System.out.println(work);
}
public interface Worker {
String work();
}
}The example demonstrates using lambda‑based interfaces such as Predicate, Consumer, Function, Supplier, UnaryOperator, BinaryOperator, and a custom functional interface.
2.2 Lazy and eager evaluation
Lazy evaluation describes operations that return another Stream, allowing chaining similar to the Builder pattern; the final result is obtained through an eager operation that produces a concrete value.
3. Common Stream Operations
3.1 collect(Collectors.toList())
Converts a Stream into a List (also toSet, toMap, etc.) – an eager operation.
public class TestCase {
public static void main(String[] args) {
List<Student> 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}]3.2 filter
Filters elements using a Predicate; the operation is lazy.
public class TestCase {
public static void main(String[] args) {
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
List<Student> list = students.stream()
.filter(stu -> stu.getStature() < 180)
.collect(Collectors.toList());
System.out.println(list);
}
}
// Output:
//[Student{name='路飞', age=22, stature=175, specialities=null}]Example filters students with height less than 180.
3.3 map
Transforms each element, internally using the Function interface; lazy.
public class TestCase {
public static void main(String[] args) {
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
List<String> names = students.stream()
.map(Student::getName)
.collect(Collectors.toList());
System.out.println(names);
}
}
// Output:
//[路飞, 红发, 白胡子]3.4 flatMap
Merges multiple Streams into one; lazy.
public class TestCase {
public static void main(String[] args) {
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
List<Student> studentList = Stream.of(
students,
asList(
new Student("艾斯", 25, 183),
new Student("雷利", 48, 176)
))
.flatMap(students1 -> students1.stream())
.collect(Collectors.toList());
System.out.println(studentList);
}
}
// Output:
//[Student{name='路飞', ...}, Student{name='红发', ...}, Student{name='白胡子', ...}, Student{name='艾斯', ...}, Student{name='雷利', ...}]3.5 max and min
Finds the maximum or minimum element using a Comparator, returning an Optional to avoid null pointer exceptions.
public class TestCase {
public static void main(String[] args) {
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
Optional<Student> max = students.stream()
.max(Comparator.comparing(stu -> stu.getAge()));
Optional<Student> min = students.stream()
.min(Comparator.comparing(stu -> stu.getAge()));
max.ifPresent(s -> System.out.println(s));
min.ifPresent(s -> System.out.println(s));
}
}
// Output:
//Student{name='白胡子', age=50, ...}
//Student{name='路飞', age=22, ...}3.6 count
Counts elements, usually combined with filter; eager.
public class TestCase {
public static void main(String[] args) {
List<Student> 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岁的人数是:23.7 reduce
Reduces a Stream to a single value; the example sums numbers 1‑4.
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:
//104. Advanced Collectors
4.1 Common collectors
Collectors are generic tools that turn a Stream into complex results. Examples include averagingInt, maxBy, minBy, partitioningBy, groupingBy, and joining.
public class CollectorsTest {
public static void main(String[] args) {
List<Student> 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<Student> students2 = new ArrayList<>(students1);
students2.remove(1);
OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);
OutstandingClass biggest = biggestGroup(classStream);
System.out.println("人数最多的班级是:" + biggest.getName());
System.out.println("一班平均年龄是:" + averageNumberOfStudent(students1));
}
private static OutstandingClass biggestGroup(Stream<OutstandingClass> classes) {
return classes.collect(maxBy(comparing(oc -> oc.getStudents().size())))
.orElseGet(OutstandingClass::new);
}
private static double averageNumberOfStudent(List<Student> students) {
return students.stream().collect(averagingInt(Student::getAge));
}
}
// Output:
//人数最多的班级是:一班
//一班平均年龄是:37.6666666666666644.2 partitioningBy
Splits data into two groups based on a Predicate.
Map<Boolean, List<Student>> map = students.stream()
.collect(Collectors.partitioningBy(s -> s.getSpecialities().contains(SpecialityEnum.SING)));4.3 groupingBy
Groups data by an arbitrary key, similar to SQL GROUP BY.
Map<SpecialityEnum, List<Student>> map = students.stream()
.collect(Collectors.groupingBy(s -> s.getSpecialities().get(0)));4.4 joining
Concatenates strings from a Stream, optionally with delimiter, prefix, and suffix.
String names = students.stream()
.map(Student::getName)
.collect(Collectors.joining(",", "[", "]"));
System.out.println(names);
// Output: [路飞,红发,白胡子]5. Conclusion
The article shows how Java 8’s functional features and Stream API enable concise, expressive code for common collection‑processing tasks. Readers are encouraged to refactor existing codebases to take advantage of these capabilities.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
