Streams in Java
Creating a Stream Application
A stream application typically starts with a
public static void main
method.Streams are often used with collections, such as lists.
Example: A list of strings called
names
.java List<String> names = new ArrayList<>();
Import necessary classes from
java.util
(e.g.,List
,ArrayList
).
Populating the List
A method,
populateNames
, can be created to add names to the list.java private static void populateNames(List<String> names) { // Add names to the list }
Using a random name generator to get a variety of names for the list.
Introduction to Streams
Streams were introduced in Java 8.
Streams are specifically used on collections.
Streams provide a way to iterate through data structures.
Iterating Through a List: Old Way vs. New Way
Old Way: Using a for-each loop.
java for (String name : names) { System.out.println(name); }
New Way: Using streams.
java names.stream().forEach(name -> System.out.println(name));
names.stream()
returns aStream<String>
. There are two versions of this method.After obtaining a stream, various operations can be performed on it.
Stream Syntax and Readability
For multiple operations on a stream, align the dots vertically for readability.
java names.stream() .forEach(name -> System.out.println(name));
Lambda Expressions with Streams
The
forEach
method takes aConsumer
.A
Consumer
is a functional interface with one abstract method calledaccept
. It's a void method.Using lambda expressions to implement the
Consumer
interface.java names.stream().forEach(name -> System.out.println(name));
Can also be written with a code body
java names.stream().forEach(name -> {System.out.println(name);});
Can also be written with data type
java names.stream().forEach((String name) -> {System.out.println(name);});
Concise Lambda Syntax
The data type of the parameter in the lambda expression does not need to be specified.
If there is only one parameter, the brackets are not needed.
If the body of the lambda expression is a single line, the curly brackets and semicolon can be omitted.
Example:
java names.stream().forEach(name -> System.out.println(name));
The variable name in the lambda expression can be any valid name, but it should be meaningful.
Parallel Streams for Multithreading
Using
parallelStream
for multithreading.java names.parallelStream().forEach(name -> System.out.println(name));
Multithreading can improve performance by utilizing multiple CPU cores.
With parallel streams, the order of elements may not be preserved due to asynchronous execution.
Understanding Multithreading
Modern CPUs often have multiple cores.
Multithreading allows utilizing these cores simultaneously.
Parallel streams make use of all the cores to the the for each looped code.
Asynchronous Nature of Parallel Streams
Parallel streams introduce asynchronous processing.
Asynchronous means operations don't necessarily execute in a sequential order.
Be cautious when using parallel streams due to potential asynchronous issues.
Alternatives to Lambda Expressions
Using the
Consumer
interface directly (less concise).java names.stream().forEach(new Consumer<String>() { @Override public void accept(String t) { System.out.println(t); } });
Using lambda expressions is cleaner and more concise.
Conclusion
Streams provide a powerful way to process collections in Java.
Lambda expressions are commonly used with streams for concise code.
Parallel streams enable multithreading for improved performance.