Java 8

This is a basic introduction to the Java 8 new features.

  • Lambda
  • Functional Interfaces
  • Method references
  • Streams
  • Default methods
  • Nashorn
  • New Date and Time API
  • Comparisons to Java 7

Lambda

  • Maintainability and Readability vs Less code writing. However, Java has an excessive verbosity
  • Less boilerplate code
  • “Kind of syntatic sugar for annonymous classes”
  • “Lambda support is one of the most visible enhancements of java 8”.
  • Cleaner syntax to event listeners

This:

button.addClickListener(new Button.ClickListener() {
    @Override
    public void buttonClick(ClickEvent event) {
        // Your code here
    }
});

Can be written like this:

button.addClickListener(e->{
    // Your code here
 });

And even in one line:

button.addClickListener(e->System.out.println("Yes, it works"));

With the Runnable interface:

import static java.lang.System.out;
 
public class Hello {
 	Runnable r1 = () -> out.println(this);
 	Runnable r2 = () -> out.println(toString());
 
 	public String toString() { return "Hello, world!"; }
 
 	public static void main(String... args) {
		new Hello().r1.run(); //Hello, world!
		new Hello().r2.run(); //Hello, world!
	}
}

Functional Interfaces

  • You still need to type your references (Java 8 will not infer it).
  • Markup interfaces for ‘functional style’ code blocks.
  • An interface with exactly one abstract method.
  • java.util.function contains some of them

Can be assigned to anything that fullfill their contract. Example:

Function<String, String> atr = (name) -> {return "@" + name;};
Function<String, Integer> leng = (name) -> name.length();
Function<String, Integer> leng2 = String::length;

Sample java.util.function functional interfaces:

  • Function<T,R> - takes an object of type T and returns R.
  • Predicate<T> - returns a boolean value based on input of type T.
  • Consumer<T> - performs an action with given object of type T.

Method references

  • Not abuse of lambda expressions.
  • Can refer to a method in its context.

Example:

public class FileFilters {
	public static boolean fileIsPdf(File file) {/*code*/}
	public static boolean fileIsTxt(File file) {/*code*/}
	public static boolean fileIsRtf(File file) {/*code*/}
}

...

// getFiles() returns a Stream.

Stream<File> pdfs = getFiles().filter(FileFilters::fileIsPdf);
Stream<File> txts = getFiles().filter(FileFilters::fileIsTxt);
Stream<File> rtfs = getFiles().filter(FileFilters::fileIsRtf);

Streams

  • java.util.stream package
  • Supports functional style operations on streams of values
  • Something like an iterator. Can be traversed once, and can also be infinite.
  • Sequential or Parallel. Can be switched using stream.sequential() and stream.parallel()
  • Some operations available: map, filter, flatMap, sorted,forEach,count, and more.

To obtain a stream from a collection:

Stream<T> stream = collection.stream();

Example of functional operations on a stream:

int sumOfWeights = blocks.stream().filter(b -> b.getColor() == RED)
                                  .mapToInt(b -> b.getWeight())
                                  .sum();

Default methods

  • Default methods = Defender Methods = Virtual Extension methods
  • Backwards compatibility
  • Collections API needed to support a new feature to
  • Can be added to any interface
  • Any class that implements the interface, but doesn’t override the method will get the default implementation.
default public Stream stream() {
	return StreamSupport.stream(spliterator());
}

Multiple defaults:

interface Foo {
 	default void talk() {
 		out.println("Foo!");
 	}
}

interface Bar {
	default void talk() {
 		out.println("Bar!");
 	}
}
class FooBar implements Foo, Bar {
	@Override
	void talk() { Foo.super.talk(); }			
}

Nashorn

  • Successor of Rhino
  • JavaScript integrated to the JVM
  • Proposal: Nashorn JEP

New Date and Time API

  • Historically bad in Java
  • Often requires external libraries (e.g. JodaTime)

Comparisons to Java 7

Creating an ActionListener

// Java 7
ActionListener al = new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println(e.getActionCommand());
	}
};

// Java 8
ActionListener al8 = e -> System.out.println(e.getActionCommand());

Printing out a list of Strings

// Java 7
for (String s : list) {
	System.out.println(s);
}

//Java 8
list.forEach(System.out::println);

Sorting a list of Strings

// Java 7
Collections.sort(list, new Comparator<String>() {
	@Override
 	public int compare(String s1, String s2) {
 		return s1.length() - s2.length();
 	}
});

//Java 8
Collections.sort(list, (s1, s2) -> s1.length() - s2.length());

// or
list.sort(Comparator.comparingInt(String::length));

Sorting complex objects:

list.sort(Comparator.comparing(Person::getLastName)
		 .thenComparing(Person::getFirstName));

References:

  • https://leanpub.com/whatsnewinjava8/read
  • https://www.techempower.com/blog/2013/03/26/everything-about-java-8/