Java 8 Stream API tips & tricks

The target of this article is to show some features of Java 8 by example. In special, the features of Stream API, Lambda Expressions, and Functional Interfaces.

What is a Functional Interface?

An interface with Single abstract  method is called as Functional interface.

@FunctionalInterface
public interface Comparator {
  int compare(T obj1, T obj2);
 }

Types of Functional Interface’s:

Mainly there are 4 functional interface types.

  1. Supplier:
  2. Consumer
  3. Predicate
  4. Function

Supplier:
@FunctionalInterface
public interface Supplier<T> {
T get();
}

Consumer:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}

Examples:
x -> System.out.println(x) // System.out::println
x -> x.doSomething()

Predicate:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}

Examples:
x -> x.isDirectory() // File::isDirectory
x -> x % 2 == 0
Function:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}

Examples:
x -> x.length() // File::length
x -> x.getId()

FUNCTIONAL INTERFACE PARAMETER TYPES RETURN TYPE DESCRIPTION
Supplier<T> NONE T Supplies a value of type T
Consumer<T> T void Consumes a value of type T
Predicate<T> T boolean A boolean-valued function
Function<T, R> T R A function with argument T and return R
ToIntFunction<T> T int An int-valued function
ToLongFunction<T> T long A long-valued function
ToDoubleFunction<T> T double A double-valued function
IntFunction<R> int R A function with argument of type int
LongFunction<R> long R A function with argument of type long
DoubleFunction<R> double R A function with argument of type double
UnaryOperator<T> T T A unary operator of type T

Functional Interface and Lambda Expressions

Given a method that takes a functional interface as parameter:

public abstract class AbstractButton extends JComponent implements ItemSelectable, SwingConstants {
 /* ... */
 public void addActionListener(ActionListener l) { /* ... */ }
 /* ... */
}

And a functional interface:

public interface ActionListener extends EventListener {
void actionPerformed(ActionEvent e);
}

You can code in the old-fashioned way using an anonymous class:

 JButton button = new JButton("DON'T PANIC");
 
button.addActionListener(
 
 new ActionListener() {
 
 @Override
 
 public void actionPerformed(ActionEvent e) {
 
 System.out.println(e);
 
 }
 
 }
 
);

Or you can code in a new way using a lambda expressions:

JButton button = new JButton(“DON’T PANIC”);

// LAMBDA EXPRESSION

button.addActionListener(e -> System.out.println(e));

Or even more concise using a method reference:

JButton button = new JButton(“DON’T PANIC”);

// LAMBDA EXPRESSION WITH METHOD REFERENCE

button.addActionListener(System.out::println);

Method Reference:

object::instanceMethod
Class::instanceMethod
Class::staticMethod

Constructor Reference:

Class::new

Streams:

  1. All in one package: java.util.stream
  2. Supports functional-style operations
  3. All stream operations take lambda expressions as arguments
  4. Integrated into the Collections API (but streams are not collections)
  5. Enables bulk operations on collections through convenient methods
  6. Enables filter and map-reduce transformations
  7. Enables lazy evaluation and short-circuit operations
  8. Never modify the underlying data structure
  9. Supports infinite (unbounded) streams
  10. Supports parallel execution

Working With Streams:

  1. Create streams from collections, arrays, generators or iterators
  2. Collect streams results in collections, arrays, strings, or maps
  3. Work with null values using Optional type
  4. Use specialized streams for primitive types
  5. Use filter operation to select
  6. Use map operation to transform

Pipeline of Operations:

  1. Create a stream
  2. Specify intermediate operations (for transforming the initial stream into others)
  3. Apply a terminal operation to produce a result

 

Leave a comment