Showing posts with label JAVA 8. Show all posts
Showing posts with label JAVA 8. Show all posts

Friday, March 10, 2017

Functional Interface in Java 8

INTRODUCTION

Functional Interfaces meant for performing a single task. In programming way, a Functional Interface will have only one method. Some of the examples are:
  1. Runnable - has only run() method.
  2. Callable - has only call() method.
  3. Comparable - has only compareTo() method.
  4. ActionListener - has only actionPerformed() method.
Java 8 introduced lot more functional interfaces and all are packaged into java.util.function. The notable point here is that there is NO Class defined in this package.
Some of the major Functional Interfaces are:
  1. Function
  2. Predicate
  3. Consumer
  4. Supplier
In this post, we are going see how can we use those Functional Interfaces.
Java 8 also introduced a separate Annotation called @FunctionalInterface to indicate the Interface is Functional Interface. Using this annotation, we can create our own Functional Interfaces.
Let us have a Model Class: Person
public class Person {
 private String firstname;
 private String lastname;
 private Gender gender;
 private String address;
 private int age;
 private int phone;
.....
}

More details on each Functional Interface below.

FUNCTION INTERFACE

Function interface will be assigned as the result of Lambda expression or Method references.
Function<T,R> -> here T denotes the Type of the input and R denotes the Result of the output.
Consider If we want to print the firstname first followed by lastname from the list of person, we can do as below.
Create a list of the person object.
List<Person> persons = Arrays.asList(new Person[]{
  new Person("Arun", "Kumar", Gender.MALE, "Hydrabad", 55, 88000),
  new Person("Bala", "Ram", Gender.MALE, "Chennai", 23, 96000),
  new Person("Cavin", "Raj", Gender.MALE, "Bangalore", 3, 86000),
  new Person("Nancy", "David", Gender.FEMALE, "Delhi", 1, 97000) });

Function<Person, String> firstNameFirst = p -> "Name: "
+ p.getFirstname() + "," + p.getLastname()
+  "\nAddress: " + p.getAddress() + "\nPhone: " + p.getPhone();
here Type of the Input is Person Class and Result of the output is String. And go on print as below.
for (Person person : persons){
 System.out.println(person.printMe(firstNameFirst));
}

Chain operations are helpful to reduce the complexity of the code. For example, if we want to calculate multiplication of input after the sum, then we can do it easily by below example.
public static int calc(int value, Function<Integer, Integer> operation) {
return operation.apply(value);
}

Function<Integer, Integer> increment = e -> e + 1;
Function<Integer, Integer> multiplication = e -> e * 2;
System.out.println("Sum and Multi: "
+ calc(10, increment.andThen(multiplication)));
And very easy to add another into that existing chain.

Function<Integer, Integer> division = e -> e / 2;
System.out.println("Sum, Multi and Division: " +
  calc(10,increment.andThen(multiplication).andThen(division)));     

PREDICATE INTERFACE

Same as Function, Predicate also can be assigned as the result of Lambda expression or Method references.
Predicate<T> - T indicates the Type of the input. Only one input and output the result as boolean.
Consider if we want to categorize the persons based on their age, then we can apply the Predicate and group them as below.
Create an Enum for person category.

public enum PersonCategory {
 CHILDREN, TEEN, OLD;
}
Create a method which will accept the PersonCategory and result in the person who belongs to which category.

public static Predicate<Person> getCategory(PersonCategory category) {
 Map<PersonCategory, Predicate<Person>> categories
      = new HashMap<PersonCategory, Predicate<Person>>();

 Predicate<Person> children = p -> p.getAge() < 12;
 Predicate<Person> teenage = p -> p.getAge() > 12 && p.getAge() < 25;
 Predicate<Person> older = p -> p.getAge() > 25;

 categories.put(PersonCategory.CHILDREN, children);
 categories.put(PersonCategory.TEEN, teenage);
 categories.put(PersonCategory.OLD, older);

 return categories.get(category);
}
Now apply the filter using this Category and print it.

persons.stream().filter(getCategory(PersonCategory.OLD))
               .forEach(Person::firstNameFirst);

CONSUMER INTERFACE

Consumer<T> - T denotes the type of the input and it will not return any result.

List<Person> persons = Arrays.asList(new Person[] {
       new Person("A", "a", Gender.MALE, "Hydrabad", 55, 88000),
       new Person("B", "b", Gender.MALE, "Chennai", 23, 96000),
       new Person("C", "c", Gender.MALE, "Bangalore", 3, 86000),
       new Person("D", "d", Gender.FEMALE, "Delhi", 1, 97000) });
Now create a consumer with list of person with first name first.
Consumer<Person> consumer = Person::firstNameFirst;
Now using consumer object, we can add a new Person as below.
consumer.accept(new Person("E", "e", Gender.MALE, "Kerala", 33, 87874));

the main beauty of this code is, we are not at all modifying the existing person list rather we are adding a new Person dynamically.

SUPPLIER INTERFACE

Supplier<T> - T denotes the type of output by the Supplier.
Consider the below example to print the age of the person. It will accept the value but will not return anything.

public class SupplierInterface {
 public static void main(String[] args) {
   Supplier<Person> supplier = () ->
          new Person("Anand", "Kumar", Gender.MALE, "Hydrabad", 55, 88000);
   printAge(supplier);
 }
 private static void printAge(Supplier<Person> supplier) {
   System.out.println(supplier.get().getAge());
 }
}

CUSTOM FUNCTIONAL INTERFACE

We can create our own functional interfaces using @FunctionalInterface annotation.
For example, if we want to calculate Sum, multiplication, we can do it as below.

public class CustomFuncationInterfaces {
 public static void main(String[] args) {
   Sum sum = (a, b) -> a + b;
   System.out.println("Sum is: " + sum.add(2, 4));

   Multiplication mul = (x, y, z) -> x * y * z;
   System.out.println("Multiplication is: " + mul.mul(2, 3, 4));
 }
}

@FunctionalInterface
interface Sum {
 int add(int a, int b);
}

@FunctionalInterface
interface Multiplication {
 int mul(int a, int b, int c);
}
Hope this post throws some lights on Functional Interfaces in Java 8.
Please share your thoughts in the comment box.
Happy Knowledge Sharing!!!

Friday, March 3, 2017

Java 8 New Features - Introduction

INTRODUCTION

Java 8 came up with a lot of enhancements. Features like Lambda Expression and Streams plays a major role on simplicity and maintainable code.
This post aims to provide the outline of Java 8 new features.
  1. Lambda Expressions
  2. Functional Interfaces
  3. Method References
  4. Streams
  5. Interface Enhancements
  6. Collection Enhancements
  7. Date & Time API Enhancements

LAMBDA EXPRESSIONS

  • Lambda expression enables functional programming in java which is not present till Java 8
  • Simplifies the code and removes unwanted codes(boilerplate codes).
  • @FunctionalInterface annotation helps to create our own Functional Interfaces. A functional interface can contain only one method. An example is a Runnable Interface.
  • Syntax : argument(s) -> expression
  • Lambda expression can be defined without argument, one argument or multiple arguments
  • without argument
MyLambda myLambda = () -> System.out.println("Test");
myLambda.foo();
  • one argument
(a) -> System.out.println(a);
  • multiple argument
MyMath add = (a, b) -> a + b;
System.out.println("Sum is: " + add.calc(8, 4));

FUNCTIONAL INTERFACES

  • Functional Interfaces are the java interfaces which will contain only one method.
  • In Java 8, new package java.util.function has been introduced.
  • Main interfaces are:
    • Function - assignment for any lambda expressions
    • Predicate
    • Consumer
    • Supplier

METHOD REFERENCES

  • Method reference help to access the public & non-static method of any class.
  • Syntax : Class::method
  • Example: mylist.forEach(System.out::println)

STREAMS

  • Streams are functional style.
  • Mainly process the list of elements of any type.
  • In Java 8, new package java.util.stream has been introduced.
  • Main classes & Interfaces are
    • Stream
    • Collector
    • Collectors
  • Streams are processed without or multiple intermediate operations (intermediate streams) and terminal operations (final output).
  • Intermediate operations are lazy operations which mean it will accept the input and wait for processing till the terminal operation is encountered. Example operations are
    • filter
    • map
    • mapToInt
  • Terminal operations are
    • sum
    • average
    • min
    • max

INTERFACE ENHANCEMENTS

  • Java 8 provides another interesting feature in the interface like having concrete methods in it.
  • concrete methods in the interfaces are either static or default access modifier.
Example:

public interface Test {
 void food();
 
 default void speak() {
   System.out.println("i can't speak :(");
 }
 
 default double average() {
          return 20 / 5;
 }
 
 static void fly() {
   System.out.println("i can't fly :(");
 }
 
 static int add() {
   return 5 + 4;
 }
 
 static List<String> cities() {
   return Arrays.asList("Chennai", "Mumbai", "Bangalore");
 }
}

Hope this post gives a brief introduction to Java 8 new features and enhancements.
Please share your thoughts in the comment box.
Happy Knowledge Sharing!!!