Java 8 New Features:
- Lambda Expression
- Stream API
- Default and static methods in Interfaces
- Functional interfaces
- Optional class
- New Date and Time API
- Functional Programming & Why Functional Programming?
- Method reference, Constructor reference
Collections:
Collection => Main interface
List, Set, Map, Queue => Child interfaces of Collection interface.
List => ArrayList, LinkedList, Vector, Stack.
We can have duplicate elements.
Insertion order is maintained.
It allows null values.
Duplicate elements are differentiated by means of index.
ArrayList:
Internal data structure => Growable array.
Use case => Search Operations => ArrayList implements RandomAccess interface
Worst case => Insertion / Deletion in the middle positions. => Shift operations are costly.
LinkedList:
Internal data structure => Doubly linked list.
Use case => Insertion / Deletion in the middle positions.
Worst case => Search Operations => Sequential search.
Set => HashSet, LinkedHashSet, TreeSet
Does not allow duplicates.
Insertion order is not maintained (except for LinkedHashSet).
One null value is allowed.
HashSet:
The underlying data structure is hashtable.
LinkedHashSet:
Underlying data structure hashtable + LinkedList
Insertion order is maintained.
TreeSet:
Elements are sorted (Natural sorting order(Ascending) or customized sorting order)
TreeSet<Employee> employees = new TreeSet<>(); // Employee objects are comparable.
// Employee objects are comparable, which means the Employee class should implement a Comparable interface.
package java.lang;
public interface Comparable<T> {
public int compareTo(T t);
}
public class Employee implements Comparable<Employee> {
private int id;
private String name;
private double salary;
// setXxx() and getXxx()
public int compareTo(Employee e2) {
// Employee e1 = this; // We can directly use "this".
// Comparison logic.
}
}
If a class is not implementing the Comparable interface, we will get an exceptionClassCastException
.
Ascending:
if
e1 < e2 return -ve
e1 > e2 return +ve
e1 == e2 return 0
Descending:
If e1 < e2 retrun +ve
e1 > e2 return -ve
e1 == e2 return 0
Comparator interface:
package java.util;
public interface Comparator<T> {
public int compare(T t1, T t2);
}
Q. Advantages of Comparator interface over Comparable?
Comparators can be used to sort the class based on more than one property of the class because we don't implement the Comparator interface directly in the class, we create another class that implements the Comparator interface and then we specify which property we want to use to sort the main class on
class EmployeeNameComparator implements Comparator<Employee> {
public int compare(Employee e1, Employee e2) {
// Logic of comparison
}
}
TreeSet<Employee> employees = new TreeSet<>(new EmployeeNameCompartor());
Map:
Collection of key-value pair (Entry).
Keys are unique, values can be duplicated.
Map => HashMap, LinkedHashMap, TreeMap, Hashtable, Properties
Q. When we deal with Set or Map collections, it is recommended to override equals() and hashcode() methods, why so?
This is because there is a contract between equals()
and hashcode()
method which states that if two objects are equals, their hashcode should also be the same, but two objects don't need to be equal even if their hashcode is the same.
Hence it is necessary to override hashcode()
if we are overriding equals()
Functional Interfaces:
The interface contains only one abstract method. They may have default and static methods.
Java 8 has introduced a new annotation @FunctionalInterface
Java 8 has also introduced a new package => java.util.function
This package contains 44 functional interfaces. These functional interfaces are used in Stream API.
Example:
public interface Calculator {
public int calculate(int x, int y);
}
1st Way
public class CalculatorImpl implements Calculator {
@Override
public int calculate(int x, int y) {
return x + y;
}
}
2nd Way => Anonymous Inner class.
Calculator c = new Calculator() {
@Override
public int calculate(int x, int y) {
return x + y;
}
}
Lambda Expression:
Calculator c = (x,y)->return x+y;
A lambda expression is a concise representation of an anonymous function that can be passed around, it does not have a name, it has a list of parameters, a body, a return type, and possibly a list of exceptions that can be thrown.
Anonymous => It's anonymous because it has no explicit name.
Function => We say function because lambda isn't associated with a particular class like a method is. But like a method, a lambda expression has a list of parameters, return type, and a list of exceptions that can be thrown.
Passed around => A lambda expression can be passed as an argument to a method or stored in a variable.
Concise => You don't need to write a boilerplate code like we do for anonymous classes.
Functions in in Java
java.util.function
package interfaces are categorized into 4:
- Predicate
- Consumer
- Supplier
- Function
public interface Consumer<T> {
public void accept(T t);
}
public interface Predicate<T> {
public boolean test(T t);
}
public interface Supplier<T> {
public T get();
}
public interface Function<T, R> {
public R apply(T t);
}
Stream API
Collection or Array => Main purpose => To store the data.
Set<Transaction>
Set<Employee>
Find all employees of HR department having salary > 30000.
SELECT * FROM employees
WHERE department='HR' AND salary > 30000
Declarative way => What you want.
Imperative way =>
Streams let you manipulate collections of data in a declarative way (you express a query rather than code and ad-hoc implementation for it).
- A stream does not hold any data. It pulls the data it processes from the source (collection/Array/File).
- A stream does not modify the data it processes.
- The source may be unbound -- It is not finite. -- But most of the time, it only means that the size of the source is not known at build time.
- One Thread => One Task Second Thread => Second Task Most of the computers have multiple cores (dual, quad, octa-core) Parallel streams => It uses multiple cores of your computer.
Q. What is Stream?
=> From a technical point of view: Stream is a typed interface.
public interface Stream<T> extends BaseStream<T, Stream<T>> {
}
We also have IntStream, LongStream, and DoubleStream.
Q. How to build Streams?
From collection object
List<Dish> menu = new ArrayList<>();
Stream<Dish> stream = menu.stream();
Empty stream
Stream stream = Stream.empty();
of()
method that accepts a single parameter.
Stream<String> stream = Stream.of("Anna");
of()
method that accepts multiple parameters.
Stream<String> stream = Stream.of("Anna", "Alex", "Bob", "Peter");
A stream on the lines of text files.
Stream<String> stream = Files.lines(path);
Create a stream from an array.
int arr[] = { 10, 20, 30, 40, 10, 20, 60, 80, 90, 30};
IntStream stream = Arrays.stream(arr);
stream.distinct()
.forEach(n -> System.out.println(n));
Create a stream with infinite data.
Optional class: Added in Java 8.
Available in java.util
package.
It is used to avoid null reference checks.
Creating Optional Object:
Empty Optional
Optional<Car> car = Optional.empty();
Optional From non-null values
Optional<Car> car = Optional.of(car);
// If the Car object is null, NullPointerException will be thrown immediately once you try to access the properties of the Car.
Optional from null.
Optional<Car> car = Optional.ofNullable(car);
// If the Car object is null, then it will return empty Optional.
Method Reference:
There are 3 different kinds of method references:
- A method reference to a static method.
interface S {
void say();
}
class M{
public static void say(){
System.out.println("this is static method say()");
}
public static void main(String a[]){
S s = M:: say;
s.say();
}
}
Output:
this is static method say()
Examples are:
Integer::parseInt
StringUtils::capitalize
Usage:
List<String> names = Arrays.asList("Anna", "Peter", "Alex", "George");
// names.forEach(name -> StringUtils.capitalize(name));
names.forEach(StringUtils::capitalize);
2) A method reference to an instance method of an arbitrary object.
interface S {
void say();
}
class M{
public void say(){
System.out.println("this is instance method say()");
}
public static void main(String a[]){
M m = new M();
S s = m:: say;
s.say();
}
}
Output:
this is instance method say()
For eg. Dish::isVegeterian
String::length
A method reference to an instance method of an existing object.
For eg. System.out::println
- Constructor reference
interface S {
void say();
}
class M{
public M (){
System.out.println("this is constructor reference method say()");
}
public static void main(String a[]){
S s = M :: new;
s.say();
}
}
Output:
this is the constructor reference method say()
Top comments (0)