OCA Java SE 8 Method - Java Lambdas








Functional programming uses lambda expressions to write code.

A lambda expression is a block of code that gets passed around.

A lambda expression is a kind of anonymous method. It has parameters and a body just like full-fledged methods do, but it doesn't have a method name.

Lambda expressions are often referred to as lambdas for short.

A lambda expression is like a method that you can pass as if it were a variable.

Lambdas allow you to write powerful code in Java.

To print out all the animals in a list according to some criteria.

We start out with the Animal class:

class Animal { 
  private String species; 
  private boolean canHop; 
  public Animal(String speciesName, boolean hopper) { 
    species = speciesName; 
    canHop = hopper; 
  } 
   public boolean canHop() { return canHop; } 
   public String toString() { return species; } 
} 

For the OCA exam, you only need to know how to implement lambda expressions that use the Predicate interface.

Remember the one method in the interface called test()? It takes any one reference type parameter and returns a boolean.





Lambda Syntax

One of the simplest lambda expressions you can write is the one you just saw:

a -> a.canHop(); 

This means that Java should call a method with an Animal parameter that returns a boolean value that's the result of a.canHop().

Since we are passing a lambda instead, Java tries to map our lambda to that interface:

boolean test(Animal a); 

The syntax of lambdas is tricky because many parts are optional. These two lines do the exact same thing:

a -> a.canHop() 
(Animal a) -> { return a.canHop(); } 

The parentheses can only be omitted if there is a single parameter and its type is not explicitly stated.

The following code lists examples of valid lambdas for a lambda with zero, one, or two String parameters.

3: print(() -> true);                                // 0 parameters 
4: print(a -> a.startsWith("test"));                 // 1 parameter 
5: print((String a) -> a.startsWith("test"));        // 1 parameter 
6: print((a, b) -> a.startsWith("test"));            // 2 parameters 
7: print((String a, String b) -> a.startsWith("test"));// 2 parameters 
8: print(a, b -> a.startsWith("test"));              // DOES NOT COMPILE 
9: print(a -> { a.startsWith("test"); });            // DOES NOT COMPILE 
10:print(a -> { return a.startsWith("test") });      // DOES NOT COMPILE 

Line 3 takes 0 parameters and returns the Boolean true.

Line 4 takes one parameter and calls a method on it, returning the result.

Line 5 explicitly defines the type of the variable.

Lines 6 and 7 take two parameters and ignore one of them.

Line 8 needs parentheses around the parameter list. The parentheses are only optional when there is one parameter and it doesn't have a type declared.

Line 9 is missing the return keyword.

Line 10 is missing the semicolon.





Predicates

In our earlier example, we created an interface with one method:

boolean test(Animal a); 

Lambdas work with interfaces that have only one method, which is called functional interfaces-interfaces that can be used with functional programming.

Java provides functional interface in the package java.util.function.

The following code lists the Predicate interface for testing.

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

It uses this type T instead of Animal. That's the syntax for generics.

Java 8 integrated the Predicate interface into some existing classes.

ArrayList declares a removeIf() method that takes a Predicate.

3: List<String> myList = new ArrayList<>(); 
4: myList.add("a"); 
5: myList.add("b"); 
6: myList.add("hoppy"); 
7: System.out.println(myList);     
8: myList.removeIf(s -> s.charAt(0) != 'h'); 
9: System.out.println(myList);     // [hoppy]