DEV Community

Prashant Mishra
Prashant Mishra

Posted on

Java 8 features

Java 8 New Features:

  1. Lambda Expression
  2. Stream API
  3. Default and static methods in Interfaces
  4. Functional interfaces
  5. Optional class
  6. New Date and Time API
  7. Functional Programming & Why Functional Programming?
  8. 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.
    }

}
Enter fullscreen mode Exit fullscreen mode

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);

}
Enter fullscreen mode Exit fullscreen mode

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());
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

1st Way

public class CalculatorImpl implements Calculator {

    @Override
    public int calculate(int x, int y) {
        return x + y;
    }

}
Enter fullscreen mode Exit fullscreen mode

2nd Way => Anonymous Inner class.

Calculator c = new Calculator() {
   @Override
   public int calculate(int x, int y) {
      return x + y;
   }  
}
Enter fullscreen mode Exit fullscreen mode

Lambda Expression:

Calculator c = (x,y)->return x+y;
Enter fullscreen mode Exit fullscreen mode

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:

  1. Predicate
  2. Consumer
  3. Supplier
  4. 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);
}

Enter fullscreen mode Exit fullscreen mode

Stream API

Collection or Array => Main purpose => To store the data.

Set<Transaction>
Set<Employee>
Enter fullscreen mode Exit fullscreen mode
Find all employees of HR department having salary > 30000.

SELECT * FROM employees
WHERE department='HR' AND salary > 30000
Enter fullscreen mode Exit fullscreen mode

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).

  1. A stream does not hold any data. It pulls the data it processes from the source (collection/Array/File).
  2. A stream does not modify the data it processes.
  3. 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.
  4. 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>> {

}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

Empty stream

   Stream stream = Stream.empty();
Enter fullscreen mode Exit fullscreen mode

of() method that accepts a single parameter.

   Stream<String> stream = Stream.of("Anna");
Enter fullscreen mode Exit fullscreen mode

of() method that accepts multiple parameters.

   Stream<String> stream = Stream.of("Anna", "Alex", "Bob", "Peter");
Enter fullscreen mode Exit fullscreen mode

A stream on the lines of text files.

   Stream<String> stream = Files.lines(path);
Enter fullscreen mode Exit fullscreen mode

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));

Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

Optional From non-null values

Optional<Car> car = Optional.of(car);
Enter fullscreen mode Exit fullscreen mode

// 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);
Enter fullscreen mode Exit fullscreen mode

// If the Car object is null, then it will return empty Optional.

Method Reference:

There are 3 different kinds of method references:

  1. 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();
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

this is static method say()
Enter fullscreen mode Exit fullscreen mode

Examples are:

   Integer::parseInt  
   StringUtils::capitalize
Enter fullscreen mode Exit fullscreen mode

Usage:

   List<String> names = Arrays.asList("Anna", "Peter", "Alex", "George");

   // names.forEach(name -> StringUtils.capitalize(name));

   names.forEach(StringUtils::capitalize);
Enter fullscreen mode Exit fullscreen mode

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();
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

this is instance method say()
Enter fullscreen mode Exit fullscreen mode

For eg. Dish::isVegeterian
String::length
A method reference to an instance method of an existing object.
For eg. System.out::println

  1. 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();
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

this is the constructor reference method say()
Enter fullscreen mode Exit fullscreen mode

Top comments (0)