What's new in Java 8

Quite a lot.....

Contents

  1. Lambda expressions
  2. Functional Interfaces
  3. Streams
    • Parallel Streams
  4. Optionals
  5. Default Methods
  6. A little functional programming

Lambda Expressions

Lambda Syntax

        
List<String> names = Arrays.asList("Jamie", "Cersei", "Tyrion", "Littlefinger");

// old style
Collections.sort(names, new Comparator<String>() {
      @Override
       public int compare (String a, String b) {
           return a.compareTo(b);
       }
});

// comparator as lambda expression
Collections.sort(names, (String a, String b) -> {return a.compareTo(b);});

// shorter without parenthesis and return statement
Collections.sort(names, (String a, String b) -> a.compareTo(b));
		
// even shorter without parameter types
Collections.sort(names, (a, b) -> a.compareTo(b));   // type inference
        
      

Lambda Scope

        
final String prefix = "pre"; // can user final vars
String postfix = "post";  // lambdas can use non-final vars
name = "Tywin Lannister";  // lambdas can use instance and class vars

Callable<String> job = () ->  prefix + name + postfix;

String concatName = job.call();
        
      

Functional Interfaces

Functional Interfaces

        

// only 1 abstract method  ==> compile error if more
@FunctionalInterface
public interface Callable<T> {
public T call();
}

// implementation of functional interface
Predicate<Integer> isOdd = i -> i % 2 == 1;
// call 
isOdd.test(5);  // true

// create new predicates from predicates
Predicate<Integer> isEven = isOdd.negate();
isEven(5); // false

// new function
Function<Integer,Integer> square = i -> i * i;
square.apply(8); // 64

// other functional interfaces
// Callable.call(), Comparator.compare(), Runnable.run()
// Consumer.accept(), Supplier.get()
        
      

Streams

Streams Examples

        
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

List<Integer> squaresOfEvenElements = 
     numbers.stream()        // create stream from collection
            .filter(p -> isEven(p))
            .map(i -> i * i)  // intermediate function
            .collect(Collectors.toList());  // terminal function
        
      

Lambdas as Parameters

        
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

public void findSumOfOddSquares() {
    Predicate<Integer> isOdd = i -> i % 2 == 1;
    Function<Integer,Integer> square = i -> i * i;
    Integer sumOfOddSquares = 
        numbers.stream()
               .map(square::apply)
               .filter(isOdd::test)  // method reference
               .reduce(0, (x, y) -> x + y);  // terminal function
}

public <T, R> R mapFilterAndReduce
  (List<T> elements, Function<T, R> function, 
   Predicate<R> checker, BinaryOperator<R> accumulator, 
   R initial) 
{
  R result = elements.stream()
   		     .map(function::apply)
		     .filter(checker::test)
		     .reduce(initial, accumulator);
  return result;
}

Integer sumOfOddSquares = mapFilterAndReduce(numbers, i -> i * i, isOdd, (x, y) -> x + y, 0);
        
      

Parallel Streams

        
int max = 1000000  // one million
List<String> values = = new ArrayList<>(max);

// fill values with strings....

// sequential processing
long count = values.stream().sorted().count();

// parallel processing
long count = values.parallelStream().sorted().count();
        
      

Optionals

Optionals

        

public Optional<Integer> calculate(Integer x) {
   Optional<Integer> result = Optional.of(x);
   return result;
}

Optional<Integer> result = calculate(5);

// avoid null pointer
result.ifPresent(System.out::println);
        
      

Default Method

Default Method

        

// add new functionality to existing interfaces without breaking code
// Comparator interface has new methods, e.g. "reversed()"

public interface MyInterface {
	
    // default method 
    default long sum(long a, long b) {
        return a + b;
    }

    // default static method
    // avoid util classes
    static int square(int x) {
         return x * x;
    }

    public long multiply(long x, long y);
}          
        
      

Functional programming
(a little)

Currying

        
// lambda return a lambda
Function<Integer, Function<Integer, Integer>> multiplier = a -> b -> a * b;
Function<Integer, Integer> times100 = multiplier.apply(100);
// b -> 100 * b
Integer result = times100.apply(3);  // 300
        
      

/