Refer package for lambda exercises: com.unit1practise.
- com.unit1practise.java8 : Implementing sample behavior to run a logic in Java7
* Why Lambda required:
- Enables functional programming
- Readable and concise
- Easier to use APIs and libraries
- Enables support for parallel processing
* This course:
- Understanding Lambdas
- Using Lambdas
- Functional Interface
- Method references
- Collection improvements
* What if we can pass action instead of class of that action(Greeting)
ie. class: public void greet(Greeting greeting) {
greeting.perform();
}
Action: public void greet(action) {
action();
}
We can achieve this using lambdas, using functions only. Not even methods of a class. only functions which works in isolation.
---
Similar to inline values i.e. String name = "Pratik";
we can assign block of code to a variable. i.e. aBlockOfCode = {
.......
.......
.......
}
i.e. aBlockOfCode = public void perform() {
System.out.println("Print this message");
}
How??
public/private/protected: Makes sense when a function is part of a class
i.e. aBlockOfCode = void perform() {
System.out.println("Print this message");
}
name: for a variable, only two things are there, name and value, we've already given name
i.e. aBlockOfCode = void () {
System.out.println("Print this message");
}
Return type: void(or anything else) not required, just look at body and guess what should be return type.
Compiler is smart enough to understand what should be type
i.e. aBlockOfCode = () {
System.out.println("Print this message");
}
A minor addition.
i.e. aBlockOfCode = () -> {
System.out.println("Print this message");
}
Additionally, ONLY if body is single line, remove braces
i.e. aBlockOfCode = () -> System.out.println("Print this message");
Examples:
greetingFunction = () -> System.out.println("Hello World");
functions can also have arguments:
Q: doubleNumberFunction = public int double (int a) {
return a * 2;
}
A.a: doubleNumberFunction = int double (int a) {
return a * 2;
}
A.b: doubleNumberFunction = int (int a) {
return a * 2;
}
A.c: doubleNumberFunction = (int a) {
return a * 2;
}
A.d: doubleNumberFunction = (int a) -> {
return a * 2;
}
It is one liner, so,
A.e: doubleNumberFunction = (int a) -> return a * 2;
Another one: addFunction = (int a, int b) -> a + b;
One more:
safeDivideFunction = (int a, int b) -> a/b;
to make it safe, we'll add curly braces, because multi line
safeDivideFunction = (int a, int b) -> {
if(b==0) return 0;
return a/b;
};
One more,
stringLengthCountFunction = (String s) -> s.length();
---
Tutorial 8:
Now what about type?? of variable greetingFunction().
Check below example
- com.unit1practise.java8Lambda : Implementing Lambda
Create Interface having exact 1 method + same signature
Now if created multiple methods in interface, compiler won't
understand which one we are referring to.
Rule: While using interface to declare lambda expression,
interface should have only one method
Line 10: Greeting helloWorldGreeting = new HelloWorldGreeting();
Line 15: Greeting lyLambdaGreeting = () -> System.out.println("Print this message");
both does same thing
Lambda expressions kinda behaving like an implementation of interface. Actually it is a function.
- com.unit1practise.java8LambdaInlineClass : Implementing inner classes
class defined inside other class
Though, Lambda is not replacement of Inner Classes.
- com.unit1practise.typeinterface
Type Interface
In example directly passed lambda value in interface
Check examples how optimally we can write Lambdas
----
- com.unit1practise.runnable
- Example of using lambda in existing implementation
Tutorial 12 : Functional Interface
- Interface who has method implementation
- Interface who has only 1 abstract method
- Interface created for lambda should be kept totally
separate than the ones for class creation
- To ensure nobody adds more methods on such interfaces
use @FunctionalInterface, check inside Greeting Interface
----
- package com.unit1practise.unit1exercise;
Example of implementation using 7 and 8
Refer three examples
------------------------------------------------------------------------------------
Refer package for Predicates: package com.unit2practise.;
package com.unit2practise.java8Predicates;
Using Functional Interface
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
Same example of previous package where Condition interface is kinda overhead.
Java 8 has some OOTB components which can be used to perform such scenarios
where returns true/false, prints output
import java.util.function. package
This package contains test()
So if we ever need a lambda expression that
return a boolean, no need to create interface
Use this test() method of predicate
* Represents a predicate (boolean-valued function) of one argument.
Other methods of Predicate: and, isEqual, negate, or, test
Condition interface no more required
But, how it worked even though interface contained multiple methods?
Reason: only test method is abstract, to use lambda only 1 method should be abstract
package com.unit2practise.java8Predicates.UsingConsumer;
Represent operation that accepts single input argument and returns no result
Whole method also eliminated using this, check class
BiConsumer: andThen
BiFunction: andThen
Exception Handling in Lambda and BiConsumer
package com.unit2practise.java8Predicates.exceptionHandling;
We don't know which exception can be thrown id used try catch inside process() implementation
use where process is called: but it //doesn't look elegant
create separate lambda(wrapper lambda) having exception and u
In example, given is Integer type, making it generic would handle all Bigeneric exceptions
-----
Closures:
Seen in Java 7
Class: ClosureExample
Here process() is called inside doProcess()
So value of newly created variable b is retrieved, compiler knows this values
have to be taken into consideration
b cannot be modified inside process()
Doubt: retaining both the methods will execute both of them, why?
-----
this reference in lamdba | not so frequently used
Class: ThisReferenceExample
doProcess, non static
this refers to instance of inner class
beaviour of this is different with lambda than inner class
-----------
unit3practise package
Method references and collections
MethodReferenceExample1 class
Method Reference Expression
() -> printMessage() === ReferenceExample1::printMessage
whenever without any pararmeter<->method i.e. () -> method()
we can replace it with ReferenceExample1::printMessage
--
Foreach iteration:
Combining collection with lambda in Java 8 --> Stream
CollectionIterationExample
External Iterators:
Example 1: Simple for loop
Example 2: for in loop
Internal Iterators: Giving control to some body else
Example 3: Simple for loop
--
Streams: A sequence of elements supporting sequential and parallel
aggregate operations.
- Separate than Lambda
Ex. Collection
1 2 3 4 5
Now multiple people requires action on these 1 2 3 4 5 elements:
StreamsExample:
people.stream()
.forEach(p -> System.out.println(p.getfName()));
Now what if we want to add more mechanism.
Use filter: it returns a stream consisting of elements of this stream
that match given predicate
if fiter is true, it goes to second one
people.stream()
.filter(p -> p.getlName().startsWith("C"))
.forEach(p -> System.out.println(p.getfName()));
A stream has always something that has resource.
Stream has 3 things:
1. Source: Contains informations/provides elements(people)
2. Operations to be performed: filter
3. Terminal Condition: End operation(forEach)
Example: Check extra activities in StreamsExample class
Termination: Adding count terminates stream, cant change
anymore(more operations)
* Parallel Processing: In below example, stream takes control from us,
people.stream()
.filter(p -> p.getlName().startsWith("C"))
.forEach(p -> System.out.println(p.getfName()));
Here different portions of collection can be handled in different
cores(processors) of multi core processor, USING:
parallelStream()
Trick:
In iteration,
for (FieldError fieldError : bindException.getBindingResult().getFieldErrors()) {
System.out.println(fieldError);
fields.add(fieldError.getField());
messages.add(fieldError.getDefaultMessage());
}
==
for(A b : c) {
b
}
then lambda,
bindException.getBindingResult().getFieldErrors().forEach(fieldError -> fields.add(fieldError.getField())) ;
c.forEach(b -> b(with some operation))
---------------------------------
java.util.stream
IntStream
StreamsCollections
Functional Interfaces:
java.util.function
Predicate:boolean valued
BiPredicate:Represents a predicate (boolean-valued function) of two arguments.
DoublePredicate: Represents a predicate (boolean-valued function) of one(double) valued argument
LongPredicate: Represents a predicate (boolean-valued function) of one (long)valued argument.
Supplier: Represents a supplier of results. Supplies valule.
T get()
public Integer getInteger() {
return new Random().nextInt();
}
Consumer: accepts a single input argument and returns no result. Consumes value.
void accept()
BiConsumer: accepts two input arguments and returns no result
public void sum(Integer a, Integer b) {
System.out.println(a + b);
}
BiFunction: Represents a function that accepts two arguments and produces a result.
DoubleToIntFunction: Represents a function that accepts a double-valued argument and produces an int-valued result.
Function: Represents a function that accepts one argument and produces a result.
Why default and static methods:
https://www.journaldev.com/2752/java-8-interface-changes-static-method-default-method
======================================================================
Another example of default and static methods
Refer to package: defaultstatic
https://www.onlinetutorialspoint.com/java/default-static-methods-interface-java-8.html
https://beginnersbook.com/2017/10/java-8-interface-changes-default-method-and-static-method/
======================================================================
Java8 DateTime API:
Refer to package datetime
======================================================================
try with resource
We don't need to close file.io operations
pratikaambani/Java-8
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|