Java 8 introduced functional interfaces to support functional programming paradigms using lambdas and streams, making the code more readable and expressive. These interfaces help in handling different real-world programming scenarios such as filtering data, transforming objects, executing operations, and aggregating values efficiently.
| Interface | Description | Example |
| Predicate<T> | Tests a condition and returns true or false. | Filtering employees with a salary above $100,000. |
| Function<T, R> | Transforms an object of type T into R. | Extracting and converting salaries from a list of employees. |
| Consumer<T> | Accepts an object and performs an operation without returning anything. | Logging or printing employee details. |
| Collector<T, A, R> | Collects and reduces elements from a stream. | Grouping employees by department or summing up salaries. |
| Supplier<T> | Supplies an object without any input. | Creating a default employee object when no data is available. |
| UnaryOperator<T> | A Function that takes and returns the same type. | Applying a 10% salary increase to all employees. |
| BinaryOperator<T> | A Function that takes two arguments and returns the same type. | Summing up salaries of employees |
1. Predicate<T> – Represents a boolean-valued function of one argument
Commonly used in filtering operations (e.g., stream().filter(...)).
It tests the given input and returns true or false.
Predicate<Employee> salaryGreaterThan100Thousand = emp -> emp.getSalary().compareTo(new BigDecimal(100000)) > 0;
Predicate<Employee> idGreaterThan1 = emp -> emp.getId() > 1;
// Using Predicate in stream filter
List<Employee> highSalaryEmployees = employees.stream()
.filter(salaryGreaterThan100Thousand.and(idGreaterThan1))
.collect(Collectors.toList());
System.out.println(highSalaryEmployees);
2. Function<T, R> – Represents a function that takes an input T and returns a result R
Useful for transforming objects (e.g., extracting specific fields, mapping objects).
Function<Employee, Integer> getSalary = emp -> emp.getSalary().intValue();
// Example usage: Map employee list to salary list
List<Integer> salaries = employees.stream()
.map(getSalary)
.collect(Collectors.toList());
System.out.println(salaries);
3. Consumer<T> – Represents an operation that accepts a single input and returns no result
Used for performing actions like printing, logging, or modifying objects.
Consumer<Employee> printEmployee = emp -> System.out.println(emp.getName() + " earns " + emp.getSalary());
// Example usage: Print each employee
employees.forEach(printEmployee);
4. Collector<T, A, R> – Used for reducing and collecting elements of a stream
It helps perform operations like grouping, summing, or joining elements.
Map<String, List<Employee>> employeesByDepartment = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
System.out.println(employeesByDepartment);
5. Supplier<T> – Represents a supplier of results
It does not take any arguments but produces an object of type T when called.
Supplier<Employee> newEmployeeSupplier = () -> new Employee(0, "New Employee", new BigDecimal(50000), "HR");
// Example usage: Create a new Employee instance
Employee newEmployee = newEmployeeSupplier.get();
System.out.println(newEmployee);
6. UnaryOperator<T> – A special case of Function<T, T> where the input and output types are the same
Used for performing operations that return the same type, such as modifying values.
UnaryOperator<BigDecimal> incrementSalary = salary -> salary.multiply(BigDecimal.valueOf(1.1)); // Increases salary by 10%
// Example usage: Apply a 10% salary increment
employees.forEach(emp -> emp.setSalary(incrementSalary.apply(emp.getSalary())));
7. BinaryOperator<T> – Represents an operation on two operands of the same type, producing a result of the same type
Useful for performing calculations like summing numbers, finding min/max, etc.
BinaryOperator<BigDecimal> sumSalaries = (sal1, sal2) -> sal1.add(sal2);
// Example usage: Calculate total salary of all employees
BigDecimal totalSalary = employees.stream()
.map(Employee::getSalary)
.reduce(BigDecimal.ZERO, sumSalaries);
System.out.println("Total Salary: " + totalSalary);
These examples demonstrate how Java 8 functional interfaces can simplify common tasks such as filtering, transforming, aggregating, and modifying collections.
Leave a comment