Java 8 lambda walkthrough

For work I have made a presentation about Java 8 project lambda and of course also some simple code illustrating some of the points. The overall reasons for Java 8 are:

  • More concise code (for classes that have just one method & collections). “We want the reader of the code to have to wade through as little syntax as possible before arriving at the “meat” of the lambda expression.” – Brian Goetz (http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html)
  • Ability to pass around functionality, not just data
  • Better support for multi core processing

All examples are runnable on the following version of Java 8 downloaded from here:

openjdk version "1.8.0-ea"OpenJDK Runtime Environment (build 1.8.0-ea-lambda-nightly-h3876-20130403-b84-b00)OpenJDK 64-Bit Server VM (build 25.0-b21, mixed mode)

The simplest case:

public class ThreadA {    public static void main(String[] args) {        new Thread(new Runnable() {            @Override            public void run() {                System.err.println("Hello from anonymous class");            }        }).start();    }}
public class ThreadB {    public static void main(String[] args) {        new Thread(() -> {            System.err.println("Hello from lambda");        }).start();    }}

Note the syntax, informally as

()|x|(x,..,z) -> expr|stmt

The arrow is a new operator. And note the conciseness of the second piece of code compared to the more bulky first piece.

Collections:

First let me introduce an simple domain and some helpers

public class Something {    private double amount;    public Something(double amount) {        this.amount = amount;    }    public double getAmount() {        return amount;    }    public String toString() {        return "Amount: " + amount;    }}public class Helper {    public static List<Something> someThings() {        List<Something> things = new ArrayList<>();        things.add(new Something(99.9));        things.add(new Something(199.9));        things.add(new Something(299.9));        things.add(new Something(399.9));        things.add(new Something(1199.9));        return things;    }}public interface Doer<T> {    void doSomething(T t);}

Lets do some filtering and sorting Java 7 style:

public class CollectionA {    public static void main(String... args) {        List<Something> things = Helper.someThings();        System.err.println("Filter");        List<Something> filtered = filter(things);        System.err.println(filtered);        System.err.println("Sum");        double sum = sum(filtered);        System.err.println(sum);    }    public static List<Something> filter(List<Something> things) {        List<Something> filtered = new ArrayList<>();        for (Something s : things) {            if (s.getAmount() > 100.00) {                if (s.getAmount() < 1000.00) {                    filtered.add(s);                }            }        }        return filtered;    }    public static double sum(List<Something> things) {        double d = 0.0;        for (Something s : things) {            d += s.getAmount();        }        return d;    }}

And now Java 8 style – streaming:

import java.util.stream.Collectors;public class CollectionB {    public static void main(String... args) {        List<Something> things = Helper.someThings();        System.err.println("Filter lambda");        List<Something> filtered = things.stream().parallel().filter( t -> t.getAmount() > 100.00 && t.getAmount() < 1000.00).collect(Collectors.toList());        System.err.println(filtered);        System.err.println("Sum lambda");        double sum = filtered.stream().mapToDouble(t -> t.getAmount()).sum();        System.err.println(sum);    }}

The import java.util.function.* interfaces & method references

public class CollectionC {    public static void main(String... args) {        List<Something> things = Helper.someThings();        System.err.println("Do something");        doSomething(things, new Doer<Something>() {            @Override            public void doSomething(Something t) {                System.err.println(t);            }        });    }    public static void doSomething(List<Something> things, Doer<Something> doer) {        for (Something s : things) {            doer.doSomething(s);        }    }}

Replace our Doer interface with the standard Consumer interface (previously known as Block)

import java.util.function.Consumer;public class CollectionD {    public static void main(String... args) {        List<Something> things = Helper.someThings();        System.err.println("Do something functional interfaces");        consumeSomething(things, new Consumer<Something>() {            @Override            public void accept(Something t) {                System.err.println(t);            }        });        System.err.println("Do something functional interfaces, using lambda");        consumeSomething(things, (t) -> System.err.println(t));        System.err.println("Do something functional interfaces, using lambda method reference (new operator ::) ");        consumeSomething(things, System.err::println);        System.err.println("Do something functional interfaces, using stream");        things.stream().forEach(new Consumer<Something>() {            @Override            public void accept(Something t) {                System.err.println(t);            }        });        System.err.println("Do something functional interfaces, using stream and method reference");        things.stream().forEach(System.err::println);    }    public static void doSomething(List<Something> things, Doer<Something> doer) {        for (Something s : things) {            doer.doSomething(s);        }    }    public static void consumeSomething(List<Something> things, Consumer<Something> consumer) {        for (Something s : things) {            consumer.accept(s);        }    }}

Map, reduce, lazy & optional

import java.util.List;import java.util.NoSuchElementException;import java.util.Optional;import java.util.stream.Collectors;public class Various {    public static void main(String... args) {        List<Something> things = Helper.someThings();        //Map        System.err.println(things.stream().map((Something t) -> t.getAmount()).collect(Collectors.toList()));        //Reduce        double d = things.stream().reduce(new Something(0.0), (Something t, Something u) -> new Something(t.getAmount() + u.getAmount())).getAmount();        System.err.println(d);        //Reduce again        System.err.println(things.stream().reduce((Something t, Something u) -> new Something(t.getAmount() + u.getAmount())).get());        //Map/reduce        System.err.println(things.stream().map((Something t) -> t.getAmount()).reduce(0.0, (x, y) -> x + y));        //Lazy        Optional<Something> findFirst = things.stream().filter(t -> t.getAmount() > 1000).findFirst();        System.err.println(findFirst.get());        //Lazy no value        Optional<Something> findFirstNotThere = things.stream().filter(t -> t.getAmount() > 2000).findFirst();        try {            System.err.println(findFirstNotThere.get());        } catch (NoSuchElementException e) {            System.err.println("Optional was not null, but its value was");        }        //Optional one step deeper        things.stream().filter(t -> t.getAmount() > 1000).findFirst().ifPresent(t -> System.err.println("Here I am"));    }}
Reference: Java 8 lambda walkthrough from our JCG partner Kim Saabye Pedersen at the Kim Saabye Pedersen’s blog blog.



Source : http://www.javacodegeeks.com/2013/06/java-8-lambda-walkthrough.html

Back to Top