Tuesday, September 30, 2014

Jump-Starting Lambda Programming


Stuart Marks
Principle member of technical staff
Java platform group, oracle

Intro level lamba coding and Streams api

Example Person.java
Application robocall()
Forloop over list of persons

Change code to also check age > 18 or 17, etc.
Use parameter age

Parameterization is key.

Change to also check minimum age. Refactor with age range.

Now also need males only in some cases. Hard to parameterize. Nulls can mean don't care or don't know.

After a while, value parameterization becomes a problem.

Caller wants to determine whether to robocall.
Library needs those parameters.

This is a function, takes person, returns boolean.
It's like an anonymous inner class.

Let's create PersonPredicate function takes Person returns boolean or from person to boolean. Uses comparator to determine if should be called based on input and return types.

Pass PersonPredicate as arg to robocall

Caller has to create a PersonPredicate which is ugly. Anonymous inner class.

Passing behaviour before java 8.

Lambda can replace.

robocall(p -> p.getage() >= 16)

Equates to PersonPredicate or compile error. No need to declare types.

Lambda is abbreviation for anonymous inner class.

There are expression lambda that have no return. Also statement lambda with return statement.

Zero args must have ().
Two or more args must be as (a,b)

Method reference Person::tostring
Same as p -> p.tostring

Need another parameter to say what to do with selected persons.
PhoneNumberConsumer with accept()
Now have two function interfaces.

New requirement: multiple numbers.
Create another behaviour parameter.
PhoneNumberFromPerson with apply() takes Person returns number

Now 3 arg lambda expressions or 3 single-method interfaces. Called functional interfaces. You get instance of interface as param but think of it as a function. Lambda can be used where ever functional interface can be expected.

If robocalling want home number, if texting mobile.

Can genericize functional interfaces.

A lot are provided in java.util.function.
@FunctionalInterface not requires but good idea. 
Adds javadoc, compiler checking,

Chain togeher: Source - filter - mapping - foreach (last 3 are lambdas)

List of Person as Stream then filter then map or transform then foreach and operation.

New stream method on list.

New language feature default method. In java 8 interfaces can now have static methods. Default impl also provided. Subclass overrides default impl normally. Class wins over default method impl in interface. A functional interface has an abstract method.

Stream uses builder pattern or pipeline. New streams api.


Streams:
  • 0or more values
  • No storage
  • Not ordered
  • Like iterator
  • Allows serial or Parallel processing

Stream pipeline:
  • A source
  • 0 or more intermediate operations
  • A terminal operation at end.

.skip(3,8) to sublist
.limit(5)
.sorted() overloaded to take comparator
.distinct() drops dupes
.flatmap() Takes in an element and return a different number of elements

A source, 0 or more intermediate operations, a terminal operation at end. 


Stream sources:
  • Stream.empty
  • Stream.of
  • Arrays.stream(arr,2,6)
  • Stream.generate() calls forever must use cutoff like limit()
  • Stream.iterate
  • Stream.range
  • "String".chars().foreach( ch -> sysout) ints so use string.valueof(ch) to output strings
  • Files reader.lines()
  • Splitasstream

Terminal ops:
  • .collect(tolist)
  • .toarray(n -> new string[n]) or string[]::new
  • .count()
  • .anymatch() short circuits
  • .findfirst after filter returns new first element returns Optional possibly containing a result.

Optional:
  • Might contain result
  • Also OptionalInt, etc
  • .get()
  • .orElse( value)

Parallelism:
  • Add .parallel()
  • .foreach becomes jumbled
  • Lambdas must not interfere with stream source. Like ConcurrentModificationException.
  • AtomicLong can be used in parallel ops but contention so long
  • Better is reduction, sum by adding plus between each. Mathematically it doesn't have to be done in order.
  • .reduce()
  • .sum() as convenience

Collector:
  • Deals with immutable objects, e.g ArrayList.
  • Works intermediately with temp lists then aggregated
  • .collect(Collectors.toList()) also tostring
  • Huge family in library.

No comments:

Post a Comment