Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Another Java Lambda Post: Functional Interfaces

DZone's Guide to

Another Java Lambda Post: Functional Interfaces

This in-depth look at Java lambdas focus on the functional interface and the ability to have a SAM (single abstract method) in your interfaces.

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

I held back writing this post because I felt the last thing the Java world needs is another Lambda post, but the main reason I blog is to improve my ability to explain technologies, so I decided to do it anyway.

The syntax of a lambda is simple:

(parameters) -> expression (parameters) -> { statements; }

Examples

Runnable r1 = () -> System.out.println("Hello World"); 

// or Streams 
List<String> winnersOfToursLessThan3500km = 
  tdfWinners
     .stream()
     .filter(d -> d.getLengthKm() < 3500) // Separate out Tours less than 3500km
     .map(Winner::getName) // Get names of winners
     .collect(toList()); // Return a list

Key points are:

  • Concise: Before Java 8, we would use anonymous classes to deliver “similar” functionality.
  • Anonymous: no explicit name.
  • Function: not associated with a particular class.
  • Argument: can be passed as an argument or stored in a variable.

Functional Interfaces

The key requirement for a lambda is that the interface it implements can only have a Single Abstract Method (SAM). However, they can have any number of default and static methods

@FunctionalInterface Annotation

@FunctionalInterface is Optional and enforces this rule by generating a compiler error:

Invalid '@FunctionalInterface' annotation; 
NotFunctionalInteface is not a functional interface

Java 8 contains a number of useful interfaces in java.util.function:

Predicate<T>   
  - boolean test(T t) 
  - True/False condition on t 
  
Consumer<T>    
  - void accept(T t)  
  - Accepts t but returns no result 
  
Function<T, R> 
  - R apply(T t)      
  - Takes t and returns an instance of R

Functional Descriptor

Describes the signature of the Functional Interface:

Predicate - t -> boolean Consumer  - t  -> void Function  - t  -> R

Accessing Class Variables

Final or “effectively final”(not changed after initialization)

final String finalString = "final string";         
String effectivelyFinalString = "effectively final string";         
Runnable r = () -> {             
  System.out.println("Hi im " + finalString);             
  System.out.println("Hi im " + effectivelyFinalString);         
};         
new Thread(r).start();

But trying to change effectivelyFinalString results stops it from compiling:

String finalString = "final string";         
String effectivelyFinalString = "effectively final string";         
Runnable r = () -> {             
  System.out.println("Hi im " + finalString);             
  System.out.println("Hi im " + effectivelyFinalString);         
};         
effectivelyFinalString = "now i wont compile";         
new Thread(r).start();

The reason this works is that the lambda is accessing a copy of the final or “effectively final” field.

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:
java ,jvm ,lambda expressions ,functional interface

Published at DZone with permission of Martin Farrell, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}