Welcome back, Java enthusiasts! Today, we’re diving into some of the most significant features introduced in Java 8: Lambda expressions and the Stream API. These two features brought a functional programming style to Java, which can significantly improve code readability and reduce boilerplate code.
Lambda Expressions
Lambda expressions allow you to treat functionality as a method argument. They enable the implementation of functional interfaces (an interface with a single abstract method) in a more compact and expressive way.
What is a Lambda Expression?
A lambda expression is defined using a combination of parameters and a body. The general syntax looks like this:
(parameters) -> expression
Or, if the body has multiple statements:
(parameters) -> { statements }
Example of a Lambda Expression
import java.util.Arrays;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Using a Lambda expression to print names
names.forEach(name -> System.out.println(name));
}
}
In this example, we use a lambda expression to iterate over a list of names and print each one. The expression name -> System.out.println(name)
is passed to the forEach
method.
Functional Interfaces
A functional interface is an interface that contains only one abstract method. In Java 8, several built-in functional interfaces are provided in the java.util.function
package, such as:
- Consumer: Represents an operation that accepts a single input argument and returns no result.
- Supplier: Represents a supplier of results, with no input arguments.
- Function: Represents a function that takes an argument and produces a result.
- Predicate: Represents a predicate (boolean-valued function) of one argument.
Example Using Functional Interfaces
import java.util.function.Consumer;
public class FunctionalInterfaceExample {
public static void main(String[] args) {
Consumer<String> greet = name -> System.out.println("Hello, " + name);
greet.accept("Alice"); // Output: Hello, Alice
}
}
In this example, we create a Consumer functional interface that takes a String
and prints a greeting.
The Stream API
The Stream API provides a powerful way to process sequences of elements (e.g., collections) in a functional style. Streams allow you to perform operations such as filtering, mapping, and reducing without modifying the underlying data structure.
Creating Streams
Streams can be created from various data sources, including collections, arrays, or I/O channels.
Example of Creating a Stream from a List
import java.util.Arrays;
import java.util.List;
public class StreamCreationExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().filter(name -> name.startsWith("A"))
.forEach(System.out::println); // Output: Alice
}
}
Here, we create a stream from the names
list, filter it for names starting with “A,” and print the result.
Stream Operations
The Stream API includes two types of operations: intermediate and terminal.
- Intermediate Operations: These operations return a new stream, allowing for method chaining. Examples include
filter()
,map()
, andsorted()
. - Terminal Operations: These operations produce a result or a side effect and terminate the stream. Examples include
forEach()
,collect()
, andreduce()
.
Example of Stream Operations
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamOperationsExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> filteredNames = names.stream()
.filter(name -> name.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(filteredNames); // Output: [ALICE, CHARLIE]
}
}
In this example, we filter the names to include only those longer than three characters, transform them to uppercase, and collect the results into a new list.
Conclusion
Java 8’s introduction of Lambda expressions and the Stream API revolutionized how we write Java code, making it more concise and expressive. By leveraging these features, you can improve code readability and write efficient data processing logic.
Want to learn more about Java Core? Join the Java Core in Practice course now!
To learn more about ITER Academy, visit our website.