Lambda functions in Java
satya - 7/29/2017, 9:19:45 AM
Lambda functions in Java
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?
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
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
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?
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: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
satya - 7/29/2017, 12:40:54 PM
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
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
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
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?
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, 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 - 8/1/2017, 10:21:07 AM
Relationship between mutability and covariance
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!! :)