Skip to content

pratikaambani/Java-8

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Lambda Expression Practise - Koushik

While updating this file, update Java 8 Notes also parallelly

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

About

Practice examples and notes of Java 8

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages