Lambda functions in Java

satya - 7/29/2017, 9:19:45 AM

Lambda functions in Java

Lambda functions in Java

Search for: Lambda functions in Java

satya - 7/29/2017, 9:20:47 AM

When are they introduced? Java 8

When are they introduced? Java 8

satya - 7/29/2017, 9:21:21 AM

What are they?

They provide a clear and concise way to represent one method interface using an expression

satya - 7/29/2017, 9:21:59 AM

Primary impact

Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection.

In addition, new concurrency features improve performance in multicore environments.

satya - 7/29/2017, 9:23:13 AM

Some useful packages


java.util.function
Predicate
Function

satya - 7/29/2017, 9:25:36 AM

Lets understand anonymous inner class


JButton testButton = new JButton("Test Button");
testButton.addActionListener(new ActionListener(){
    @Override public void actionPerformed(ActionEvent ae){
          System.out.println("Click Detected by Anon Class");
    }
});

satya - 7/29/2017, 9:29:23 AM

What is anonymous? What is inner in this case?

The class born out of new ActionListener() has no name. So it does not get into the namespace issues.

It is inner to the parent class in which this code appears. That means the method body has access to the instance variables defined in the parent class where this code appears. (I think).

The rules of inner classes and static inner classes throw me off! Hope languages make these a bit more explicit and not hidden rules and exceptions.

satya - 7/29/2017, 9:33:04 AM

What is a functional interface, nevertheless mind you still an interface?

The ActionListener example is an interface with only one method. With Java SE 8, an interface that follows this pattern is known as a "functional interface."

This type of interface, was previously known as a Single Abstract Method type (SAM).

Using functional interfaces with anonymous inner classes are a common pattern in Java.

In addition to the EventListener classes, interfaces like Runnable and Comparator are used in a similar manner. Therefore, functional interfaces are leveraged for use with lambda expressions.

satya - 7/29/2017, 9:43:35 AM

Now to the syntax part of it

A lambda expression is (appears to be) a syntactical shortcut to defining an anonymous inner class just like the one above

Being a shortcut, more than one is possible to arrive at an implementation of a single method as required by the functional interfaces like Runnable.

It seem to come in 2 key flavors: a) An expression and b) a block

satya - 7/29/2017, 9:48:03 AM

Expression Example: (x,y) -> x + y

This is equivalent to an object of the instantiation of an anonymous inner class


new SomeFunctionalInterface()
{
    @Override int somesingleMethod(int x, int y)
    {
        return (x+y);
    }
}

Going forward I will not show you this equivalency but it is the same for all shortcuts.

In the expression form (single statement) the expression is evaluated and returned.

No return statement is necessary. It is not the case with block which you will see next.

satya - 7/29/2017, 9:53:10 AM

A block form: (String s) -> { System.out.println(s); }

In this example, the method takes an input of string and prints it.

There is no return statement so nothing is returned.

In a block form you have to have a return statement if something needs to be returned

In a block form break and and continue are not allowed at the main line while allowed in loops.

satya - 7/29/2017, 9:54:28 AM

Another expression example: () -> 42

A function that returns a number 42. Again a shortcut. Concept is same.

satya - 7/29/2017, 10:09:14 AM

In summary


//Expression forms
(x,y) -> x + y //notice no semicolon
() -> 42

//A block form
(string s) { System.out.println(s); } //proper code block

satya - 7/29/2017, 10:12:57 AM

One more time


() -> 42

Any lambda expression means, create me an object which confirms to the interface and whose method implementation is as I say here.

satya - 7/29/2017, 10:15:55 AM

So see how this applies to a Runnable


Runnable x = () -> System.out.println("hello");

//or you could have said

Runnable x = new SomeSuitableRunnableClass();

So it is a syntax to create object instances of anonymous inner classes. Wherever an object reference can be passed in what ever language context you can use this syntax.

satya - 7/29/2017, 10:19:41 AM

Another example


Collections.sort(personList, 
  (Person p1, Person p2) -> 
     p1.getSurName().compareTo(p2.getSurName())
);

The second argument to sort is an object reference whose compare method takes 2 persons and returns an int based on their comparison. The list will then be sorted by that order.

satya - 7/29/2017, 10:20:37 AM

What is target typing in Java?

What is target typing in Java?

Search for: What is target typing in Java?

satya - 7/29/2017, 10:52:05 AM

Let's consider something now


public interface Predicate {
   public boolean test(T t);
}

Generics are quite sneaky. This predicate is a contract to say I will test something on the object you pass and tell you true or false. What I test i will tell you later.

What object get passed is also not known at this time. I will leave that to the future implementations.

Not only the method is specialized later, the type itself is unknown at this time.

Generics and the patterns they allow is a book by itself. But in this case this is a fairly simple "generic" interface.

satya - 7/29/2017, 10:55:33 AM

Now consider this code


Predicate allDrivers = p -> p.getAge() >= 16;
Predicate LionPredicate = animal -> animal.hasMane();

Now any normal java class can use the object references "allDrivers" and "LionPredicate" to test if a "Person" object is a driver or an "Animal" object is a lion.

satya - 7/29/2017, 11:03:09 AM

Lets see another lambda interfaces


Function westernStyle = p -> {
       return "\nName: " + p.getGivenName() + " " + p.getSurName() + "\n" +
              "Age: " + p.getAge() + "  " + "Gender: " + p.getGender() + "\n" +
              "EMail: " + p.getEmail() + "\n" + 
              "Phone: " + p.getPhone() + "\n" +
              "Address: " + p.getAddress();
     };
     
Function easternStyle =  p -> "\nName: " + p.getSurName() + " " 
             + p.getGivenName() + "\n" + "Age: " + p.getAge() + "  " + 
             "Gender: " + p.getGender() + "\n" +
             "EMail: " + p.getEmail() + "\n" + 
             "Phone: " + p.getPhone() + "\n" +
             "Address: " + p.getAddress(); 

satya - 7/29/2017, 11:17:27 AM

Lets explore what is going on: Target Typing

Function is an interface that takes object of one type and converts it to another type.

As with generics the types can be any input type and any output type.

In this case a person object is taken and a properly formatted string is returned.

How does it know by looking at the code above if the input is a person and the output is a string. No such information is present in the above valid java segment.

Well, when the reference easternStyle and westernStyle are of type "Function". So the type information is accurately read from the definition of Function and also the method of the Function.

Although Function is a generic with 2 type arguments, it becomes de-genericized based on where these object references are used. The method in to which this object is passed will declare a Function object correctly.


//An example
Class Person
{
  doSomething(Function transformer)
  {
    //Generics know the apply method takes a Person
    //return transformer.apply(this);
  }
}

satya - 7/29/2017, 11:20:20 AM

Here are some functions out of the box


Predicate: A property of the object passed as argument

Consumer: An action to be performed with the object passed as argument

Function: Transform a T to a U

Supplier: Provide an instance of a T (such as a factory)

UnaryOperator: A unary operator from T -> T

BinaryOperator: A binary operator from (T, T) -> T

satya - 7/29/2017, 11:36:21 AM

Here is how collections become streams that can be acted upon


 public class Test03toList {
   
   public static void main(String[] args) {
     
     List pl = Person.createShortList();
     
     SearchCriteria search = SearchCriteria.getInstance();
     
     // Make a new list after filtering.
     List pilotList = pl
             .stream()
             .filter(search.getCriteria("allPilots"))
             .collect(Collectors.toList());
     
     System.out.println("\n=== Western Pilot Phone List ===");
     pilotList.forEach(Person::printWesternName);
 
   }
 
 }

Start with a collection and get a stream out of it. Apply filter to get another stream, then collect the resulting stream into a list.

Input streams are undisturbed. In that sense they are immutable as they go through processing like unix pipes.

Streams are lazy loaded

satya - 7/29/2017, 11:40:15 AM

Parallel streams in Java 8

Parallel streams in Java 8

Search for: Parallel streams in Java 8

satya - 7/29/2017, 11:44:04 AM

Project Lambda Website

Project Lambda Website

satya - 7/29/2017, 11:45:30 AM

Real background into the design approaches of lamdas in java

Real background into the design approaches of lamdas in java

satya - 7/29/2017, 11:47:11 AM

There is a lot of material here to go over to fully understand intricacies

There is a lot of material here to go over to fully understand intricacies

satya - 7/29/2017, 11:48:25 AM

A similar meaty discussion on streams

A similar meaty discussion on streams

satya - 7/29/2017, 11:49:41 AM

A video: Jump-Starting Lambda Programming

satya - 7/29/2017, 11:58:20 AM

what is modeling code as data paradigm?

what is modeling code as data paradigm?

Search for: what is modeling code as data paradigm?

satya - 7/29/2017, 12:04:15 PM

What is a vertical problem in java code?

Refers to the verbose nature of specializing a single method and derive a new class and the number of lines it takes "vertically" taking space in your java file.

satya - 7/29/2017, 12:06:26 PM

Read about Target typing here

Read about Target typing here

satya - 7/29/2017, 12:08:50 PM

Target typing

the name of a functional interface is not part of the lambda expression syntax. So what kind of object does a lambda expression represent? Its type is inferred from the surrounding context

The compiler is responsible for inferring the type of each lambda expression. It uses the type expected in the context in which the expression appears; this type is called the target type. A lambda expression can only appear in a context that has a target type.

Of course, no lambda expression will be compatible with every possible target type. The compiler checks that the types used by the lambda expression are consistent with the target type's method signature.

satya - 7/29/2017, 12:09:20 PM

a lambda expression is compatible with a target type T if all of the following conditions hold

T is a functional interface type

The lambda expression has the same number of parameters as T's method, and those parameters' types are the same

Each expression returned by the lambda body is compatible with T's method's return type

Each exception thrown by the lambda body is allowed by T's method's throws clause

satya - 7/29/2017, 12:10:31 PM

Don't turn a vertical problem into a horizontal problem :)

Don't turn a vertical problem into a horizontal problem :)

satya - 7/29/2017, 12:11:13 PM

Where can type be inferred: Target typing

Variable declarations

Assignments

Return statements

Array initializers

Method or constructor arguments

Lambda expression bodies

Conditional expressions ?:

Cast expressions

satya - 7/29/2017, 12:13:33 PM

Inner classes scoping

Determining the meaning of names (and this) in inner classes is significantly more difficult and error-prone than when classes are limited to the top level. Inherited members?including methods of class Object?can accidentally shadow outer declarations, and unqualified references to this always refer to the inner class itself.

satya - 7/29/2017, 12:16:59 PM

Scoping in lamda classes

Lambda expressions are much simpler: they do not inherit any names from a supertype, nor do they introduce a new level of scoping. Instead, they are lexically scoped, meaning names in the body are interpreted just as they are in the enclosing environment (with the addition of new names for the lambda expression's formal parameters). As a natural extension, the this keyword and references to its members have the same meaning as they would immediately outside the lambda expression.

satya - 7/29/2017, 12:18:18 PM

Implications to "this"

Of course, if this inside a lambda expression refers to the enclosing class, it cannot also be used to refer to the function value described by the lambda expression. It is not usually necessary to do so, but on some occasions?say, when defining a recursive function?it is important.

satya - 7/29/2017, 12:19:30 PM

Further

Consistent with the lexical-scoping approach, and following the pattern set by other local parameterized constructs like for loops and catch clauses, the parameters of a lambda expression must not shadow any local variables in the enclosing context.

satya - 7/29/2017, 12:40:34 PM

Java reduce function

Java reduce function

Search for: Java reduce function

satya - 7/29/2017, 12:40:54 PM

A tutorial on aggregate functions in Java

A tutorial on aggregate functions in Java

satya - 7/29/2017, 1:04:18 PM

A reduce is like this


foreach()
  cur = reduce(cur,next);

satya - 7/31/2017, 11:11:15 AM

A few java lambda expression predicates

It is a way to simulate functions, the ordinary, run of the mill type, in an OO language like java

It is a way to instantiate [materialized] interfaces

An object instantiated thus from a lambda expression is like a singleton object with no state [instance variables]

Any number of clients can call such an object with "no" effect due to parallelism.

Objects with instance variables cannot be paralleled, so an object born out of lambda expression not having any instance variables [leave aside read-only] can be used by anyone and doesn't have to be "new" ed for every usage. In other words it acts like a "function"

Signature of a lambda expression is defined by a single method interface. java.util.function package defines templates for a number of these reusable functions.

satya - 7/31/2017, 12:20:31 PM

Role of method references in java lambda expressions

Role of method references in java lambda expressions

Search for: Role of method references in java lambda expressions

satya - 7/31/2017, 12:20:45 PM

Role of default methods in java interfaces

Role of default methods in java interfaces

Search for: Role of default methods in java interfaces

satya - 7/31/2017, 1:21:37 PM

Formal definition of functional interfaces in Java

Formal definition of functional interfaces in Java

Search for: Formal definition of functional interfaces in Java

satya - 7/31/2017, 1:27:01 PM

Java 8 allows a few more things in interface definitions


static methods
static variables

//These used to be in abstract classes
//now can be in interfaces itself
default functions

satya - 7/31/2017, 1:29:56 PM

default methods in java interfaces

default methods in java interfaces

Search for: default methods in java interfaces

satya - 7/31/2017, 1:35:42 PM

Adding default methods don't change the interface of a class

That means clients compiled with older interface still works when the interface is modified by adding new methods that are default.

satya - 7/31/2017, 1:45:06 PM

Default methods have no idea of state because interfaces do not have state

This is a key distinction with abstract classes which can have a constructor and an implemented object state.

These default methods are more like templates in hook and template pattern where the template defines the semantics of calling while the hooks define the work.

satya - 7/31/2017, 1:47:34 PM

PDF: Evolving interfaces, Brian Goetz

PDF: Evolving interfaces, Brian Goetz

satya - 7/31/2017, 1:58:33 PM

Default methods as virtual

From the perspective of a client of the interface, extension methods are no different from ordinary interface methods. They are invoked via invokeinterface, they can be discovered and invoked reflectively, and the client does not care where the implementation comes from.

satya - 7/31/2017, 2:00:58 PM

what are covariants?

what are covariants?

Search for: what are covariants?

satya - 7/31/2017, 2:07:08 PM

covariants and contravariants in programming languages

covariants and contravariants in programming languages

Search for: covariants and contravariants in programming languages

satya - 7/31/2017, 2:10:45 PM

Here is an SOF article on this

Here is an SOF article on this

satya - 7/31/2017, 7:13:51 PM

This looks like a deep dive into generics leading to covariants and their contra versions

This looks like a deep dive into generics leading to covariants and their contra versions

satya - 7/31/2017, 7:17:04 PM

Worth reading Tomas Petricek

Worth reading Tomas Petricek

satya - 8/1/2017, 10:21:07 AM

Relationship between mutability and covariance

Relationship between mutability and covariance

Search for: Relationship between mutability and covariance

satya - 8/1/2017, 10:24:37 AM

True type substitution, mutability and covariance

True type substitution, mutability and covariance

Search for: True type substitution, mutability and covariance

satya - 8/1/2017, 10:27:19 AM

Banana as a fruit

Banana is an object

Banana is a fruit

You can see banana as a fruit but still underneath it is a banana

when you see banana as a "fruit" there are no methods on "fruit" that will violate the contract that the underneath object is a banana.

So a banana is truly type compatible and substitutable as a fruit

satya - 8/1/2017, 10:35:15 AM

:) So can I see a bucket of bananas as a bucket of fruits? Trickier it becomes...

A bucket of bananas are a bucket of fruits

Or is it, when you strictly look at it?

Follow me ....

You are blind folded

You got a gift of a bucket of bananas

Someone said you got a gift of a bucket of fruits

You open it, pick one and you eat it. Yes it is a fruit

You have an apple in your pocket

Apple is a fruit

You take the apple and drop it into the bucket (still blind folded) because you know it is not a bucket of chicken but a bucket of fruits, apple is a fruit, so you drop it.

Kaboom, the bucket BLOWS UP!! Because the sender put a JINX on it that anytime a NON BANANA comes into it, explode itself!

So by looking at a bucket of bananas ALL THE TIME as a bucket of fruits violated the initial contract that IT MUST BE ONLY A BUCKET OF BANANAs.

However there are cases when the bucket of bananas can be seen as a bucket of fruits as long as this special SPECIAL_LIST of fruits don't allow you to change (mutable) what is in the bucket GLOBALLY or (figure out - my extension - how to add only bananas!!!)

This is where immutable collection interfaces can keep type substitutability intact and hence called covariance.

satya - 8/1/2017, 10:39:16 AM

Which means


List<Bananas> CANNOT BE SEEN as a List<Fruits>
But
List<Bananas> CAN BE SEEN as a Readonly_List_Of<Fruits>

:)

satya - 8/1/2017, 10:39:34 AM

A compiler then...

A compiler can then allow correctly the second case if there is a way for the compiler to know that.

satya - 8/1/2017, 10:43:49 AM

Immutability is just one shortcut - then - to ensure type safety!

I get it. By being immutable the methods have ensured it stays. But what if I find a sneaky way to add a banana, then it has changed and yet still holds.

For example there may be another client that keeps adding bananas to that bucket while the other client reading it.

Or perhaps the syntax of generics is in someways generalized that "no update" means "type stays the same".

satya - 8/1/2017, 10:46:00 AM

This whole thing is closely tied to the rules of generics!

This whole thing is closely tied to the rules of generics!

satya - 8/1/2017, 10:49:27 AM

A List is a type. A Fruit is a type. So a List of Fruits is a "Type of Types"

A List is a type. A Fruit is a type. So a List of Fruits is a "Type of Types"

satya - 8/1/2017, 10:49:45 AM

So this idea may extend to any Type of Types and not just collections

So this idea may extend to any Type of Types and not just collections

satya - 8/1/2017, 10:51:22 AM

Call them Parent Type and Child Type

Call them Parent Type and Child Type

satya - 8/1/2017, 10:53:30 AM

Nature of the methods on the Parent type: Covaraints made sense

All the methods on the parent type like the "list" must be valid for ALL derived types of child type (fruit for example)

Then the parent and child types seem to sing the same tune or they are said to be covariants!!

satya - 8/1/2017, 10:58:35 AM

Without generics you can never see a BananaList as FruitList

Because BananaList will have a method that says getBanana() and putBanana().

A FruitList will say getFruit() and putFruit()

You just can't cast it at all!

satya - 8/1/2017, 11:00:35 AM

For all the nice things they do, the woes the types bring... You speak with lisp :)

For all the nice things they do, the woes the types bring... You speak with lisp :)

satya - 8/1/2017, 11:07:17 AM

More symbolism


If (Y is a sub type of X)
   (Apple is a Fruit)
and
if (T(Y) is a syb type of T(X))
   (List(Apples) is a List(Fruits))

Then types "X" and "T" are covariants

X -> Y
T(X) -> T(Y)

satya - 8/1/2017, 1:42:24 PM

I can see a banana from the "lens" of a fruit: covariance

The fruit lens let you browse through a banana as if it is a fruit

Except if the fruit lens allows you slip a fruit through it won't work because the banana will not accept any fruit but only a banana

satya - 8/1/2017, 1:49:11 PM

Can I see now, a fruit from the "lens" of a banana


//Take this function
somefunction(Banana)
{
   //Perform operations involvign a banana
   Banana... getABanana();
   void ..setABanana(Banana)
}

//Clearly I can not pass a fruit
//compiler will not allow
//example
somefunction(fruit);

//sorry fruit is not a banana

Except, we promise in the function that we only use functions that are available with "fruit" and never invoke "banana" functions. Will it work then?

Say we do that. Even then the "get" function of a fruit will return a fruit, and if the someFunction is done through generics, then the compiler will expect a "banana" as the return type. So compiler will fail.

What if the function of the "fruit" is some kind of a set with a number of arguments that take fruits, but now gets passed bananas. This is acceptable for the compiler because the banana type is downcastable to a fruit.

This is contravariance, where we are able to pass functionality that is meant for base classes where a derived class is expected

satya - 8/1/2017, 1:49:47 PM

Seeing Banana as a fruit: Covariant

Seeing Banana as a fruit: Covariant

satya - 8/1/2017, 1:50:12 PM

Seeing fruit as a banana: Contravariance

Seeing fruit as a banana: Contravariance

satya - 8/1/2017, 1:50:59 PM

If a function for a fruit is such that it can be used for a banana in a type safe way that is contravariance

If a function for a fruit is such that it can be used for a banana in a type safe way that is contravariance

satya - 8/1/2017, 1:52:24 PM

So contravariance is upcasting where (Banana)(Any generic fruit)

So contravariance is upcasting where (Banana)(Any generic fruit)

satya - 8/1/2017, 1:52:42 PM

Covariance is downcasting where (Fruit)(Banana)

Covariance is downcasting where (Fruit)(Banana)

satya - 8/1/2017, 1:53:55 PM

Read only interfaces of underlying base classes results in covariance

Read only interfaces of underlying base classes results in covariance

satya - 8/1/2017, 1:54:28 PM

Write only interfaces of underlying base clases results in contravariance

Write only interfaces of underlying base clases results in contravariance

satya - 8/2/2017, 11:40:34 AM

Simulate run of the mill functions in Java: Java Lambda expressions

Java is an OO language. It has classes and objects. functions are not stand alone. they only exist in the context of a class.

Functions, the good old ones, don't carry state. A function CAN choose to update a state outside of its scope, which is usually not very good, but otherwise should return a value like any mathematical function.

An object on the other hand carries state through instance variables. Methods can use that state to accumulate over time or merely use as transitional data between method calls. Either approach makes the object single threaded. Such an object cannot be shared by multiple threads without controlling access to it by taking turns.

Sometimes all we need is a function that can be used a million times without recreating it again and again.

Lambda expressions provide a way to see a single method interfaces as functions. thats it. Everything else is gravy.

Now generics throws another abstraction on top of functions and colors with type safety for reuse etc.

satya - 8/2/2017, 11:44:12 AM

Java Lamda expressions instantiate (materialized) interfaces

You know that interfaces cannot be instantiated and have variables hold the the reference to such instantiated interfaces.

Because an interface has no body to execute code. So it needs a body. Typically this is done through a formal inheritance and only such implementation classes can then be instantiated in place of those interfaces.

Lambda expressions can be seen as materializing an interface on the fly by providing a body in line exactly in the same place where instantiation happens.

So one can see lambda expressions as instantiating interfaces!! :)