Revising Java 8
- Supports functional programming
- embraces creating immutable objects
- Example
- Streams API: The Streams API introduced in Java 8 encourages a functional programming style that works well with immutable objects. Operations on streams do not modify the underlying data source; instead, they return a new stream that reflects the result. This aligns with the principle of immutability, where instead of changing an object, you create a new object with the modified state.
- Example
- more concise and readable
- allows passing of functions as a method parameters
- Useful when you are implemting callbacks
- declarative way of writing code
- We are only worried about the result not the algorithm behind it.
- Ex: SQl quires
- We are only worried about the result not the algorithm behind it.
- embraces creating immutable objects
- Effective utilization of system resources
- provides many concurrent libraries
- parallel streams
- Imperative
- Mutable objects
- can result in problems while running in multithreaded environment
- Not Readable Code
- Mutable objects
- Declarative
- Logic is abstracted
- Don't worry about how it is done
- More readable
- Logic is abstracted
Note : Examples are present in ImperativeDeclarative Package
-
Same has method without a name
-
Anonymous Function
-
Can be assigned to a variable and can be passed around
-
Not tied to class
-
Usage
- used to implement Function Interfaces
-
Syntax
No {} & return keyword
- if single statement is presentDropping Input parameters type
- we can drop the type of parameters if compiler is able to resolve themDropping ()
- if there is only one parameter
-
Restrictions on local variables
-
No Restrictions on instance and class(static) variables
- Interface Which has only one abstract method is known as functional interface
- but can have any no of default and static methods
@FunctionalInterface
annotation id used to represent the functional interfaces- Functional interfaces make it easier to write functional-style code by reducing the verbosity of anonymous inner classes.
- Java libraries like Streams and Collections have written to support functional interfaces
- Example enhanced forEach loop
- Its makes code readable, reusable and maintainable
- All functional interfaces are present in following package
import java.util.function
- Represents an operation that accepts a single input argument and returns no result.
- has void
accept(T t)
method - Consumer Chaining
andThen(Consumer)
-- See Functional Interfaces Example Two
- BiConsumer
accept(T t, T t)
addThen(Consumer)
- Represents a predicate (boolean-valued function) of one argument.
boolean test(T t)
-Evaluates this predicate on the given argument.- Chaining
- And
default Predicate<T> and(Predicate<? super T> other)
- Or
default Predicate<T> or(Predicate<? super T> other)
- Negate
default Predicate<T> negate()
- Equal - Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).
static <T> Predicate<T> isEqual(Object targetRef)
- And
- BiPredicate
- Represents a predicate (boolean-valued function) of two arguments. This is the two-arity specialization of Predicate.
boolean test(T t, U u)
- Evaluates this predicate on the given arguments.- Chaining
- And
default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other)
- Or
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other)
- negate
default BiPredicate<T, U> negate()
- And
-
Represents a function that accepts one argument and returns a result.
-
R apply(T t)
-- takes input a returns output -
Chaining
-
Compose - Returns a composed function that first applies the before function to its input, and then applies this function to the result.
default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
-
addThen - Returns a composed function that first applies this function to its input, and then applies the after function to the result. 2.
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
-
-
BiFunction
- Takes two arguments and returns one
R apply(T t, U u);
- Chaining
- addThen -Returns a composed function that first applies this function to its input, and then applies the after function to the result.
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after)
- addThen -Returns a composed function that first applies this function to its input, and then applies the after function to the result.
- Takes two arguments and returns one
- If input and output of same type
- Inherits the functionality of Function Functional Interface
- Example
- If 2 input and output of same time
- Inherits the functionality of BiFunction Functional Interface
- Utility Methods
- minBy - return min of two input parameters based on provided comparator
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator)
- maxBy - return max of two input parameters based on provided comparator
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator)
- minBy - return min of two input parameters based on provided comparator
- Example
- Method reference is used to refer method of functional interface.
- Reuse to existing method via method reference to represent lambda expression
- Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
- Types of method references
- Method reference to an instance method of a particular object of a class
- Method reference to the static method of a class
- Reference to an Instance Method of an Arbitrary Object of a Particular Type
- Method reference to a constructor
- Intro
- Streams are introduced to promote declarative way of programming
- Makes developer life easy to work with collection framework
- Functional interfaces, lambda expressions, streams will go in handy to make code readable and reusable
- Example
- How Streams Work
- Debugging a stream
Peek(Consumer)
intermediate method is used to see state of stream after every intermediate operation Collection vs Stream
- we cannot modify a stream once created. It is immutable explicitly
- No random access of an element from a stream
- Streams are lazy, and are activated by terminal operations
- Stream can only be used once
- Ex : We can't iterate a stream twice
- Streams are iterated internally vai forEach Method
- It is an intermediate operation
- Transform the input to required format
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
- Similar to map() it transforms input to different required format
- Usually used to transform Stream of Multivalued Objects
- findFirst
- return first element encountered ( if there is parallel it will return first encountered element among all parallel streams)
- findAny
- returns first element encountered
- returns
Optional<>
- Example
- Ignores rest of the stream as soon a value is encountered
- of
- to create a stream
public static<T> Stream<T> of(T... values)
- iterate
- Infinite stream
- limit() can be used to stop infinity
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
- generate
- Infinite stream
- limit() can be used to stop infinity
public static<T> Stream<T> generate(Supplier<T> s)
- Example
- Used to represent
primitive
values in a stream - Types
- Aggregate Functions
- Boxing and UnBoxing
-
joining
-
counting
-
mapping
-
maxBy & minBy
-
summingInt & averagingInt
-
summingLong || summingDouble || averagingLong || averagingDouble
- Same as
summingInt & averagingInt
- Same as
-
groupingBy
- same as SQL groupBy
- Types
-
Type 1
-
Type 2
- Two level
- syntax
-
Type 3
-
- to work with Optional<>
- syntax
public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)
- Example
- Similar to groupBy
- accepts a predicate
- returns a map
- keys will only be true and false
- syntax
- Improves the application performance by utilizing system resource optimally
- Internally Fork/Join framework to achieve efficiency
- Example
- Not to use Parallel Streams
- If not used wisely parallel stream will perform badly compared to sequential
- if you are having a chance of race condition ( updating mutable object )
- Always check the performance of a method under sequential and parallel scenarios before using them
- The purpose of the class is to provide a type-level solution for representing optional values instead of null references.
- Why
- Let's start with an example to see the dangers of null. Let's consider a nested object structure for a Computer, as illustrated in Figure 1.
- What can you do to prevent unintended null pointer exceptions? You can be defensive and add checks to prevent null dereferences, as shown in Listing
- you can see that the code in Listing 1 quickly becomes very ugly due to the nested checks. Unfortunately, we need a lot of boilerplate code to make sure we don't get a NullPointerException. In addition, it's just annoying that these checks get in the way of the business logic. In fact, they are decreasing the overall readability of our program.
- Let's start with an example to see the dangers of null. Let's consider a nested object structure for a Computer, as illustrated in Figure 1.
- Methods
- ofNullable
- of
- empty
- orElse
- orElseGet
- orElseThrow
- ifPresent
- filter and map
- filter
- If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional.
- Syntax
public Optional<T> filter(Predicate<? super T> predicate)
- map
- filter
- flatMap
- Used only Nested Optional inside an object
- If a value is present, apply the provided Optional-bearing mapping function to it, return that result, otherwise return an empty Optional. This method is similar to map(Function), but the provided mapper is one whose result is already an Optional, and if invoked, flatMap does not wrap it with an additional Optional.
- syntax
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
- Example
- Check OptionalClass.flatMapExample.java
![image](https://private-user-images.githubusercontent.com/38384536/311501165-afc63098-ee14-41d2-b91a-d26455db5b2d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEwNjcyODAsIm5iZiI6MTcyMTA2Njk4MCwicGF0aCI6Ii8zODM4NDUzNi8zMTE1MDExNjUtYWZjNjMwOTgtZWUxNC00MWQyLWI5MWEtZDI2NDU1ZGI1YjJkLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE1VDE4MDk0MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTQzMDU3NTk2NWZiODM1YzFhMDZkNWQxZDJmMmJlZmVjMWNhZTkzYTkzNDAzYjM5OGU5MGE5Mzg4N2M5OTE1OTImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.CgEXdQRANZgMcVl8N9blopcqCSQ4f6-zU3eCrHlSFPI)