Tuesday, August 9, 2016

Java 8 Tutorial


package java8tut;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import javax.swing.JButton;

public class Java8Tut {
 
 public static void main(String [] args) {
  
  //lambdas
  Converter converter = (from) -> Integer.valueOf(from);
  Integer convertedVal = converter.convert("123");
  System.out.println(convertedVal);
  
  converter = Integer::valueOf;
  convertedVal=converter.convert("256");
  System.out.println(convertedVal);
  
  PersonFactory pfactory = Person::new;
  Person p=pfactory.createPerson("hello", "there");
  System.out.println(p.firstName + " " + p.lastName);
  
  List names = Arrays.asList("Matt", "martin", "devi", "ashish", "gaili", "Brad");
  Collections.sort(names, (String a, String b) -> { return a.compareTo(b);});
  System.out.println(names);
  
  names = Arrays.asList("matt", "martin", "devi", "ashish", "gaili", "brad");
  Collections.sort(names, (a, b) -> a.compareTo(b));
  System.out.println(names);
  
  //consumer
  Consumer greeter = (person) -> System.out.println("Hello, " + person.firstName);
  greeter.accept(new Person("Luke", "Skywalker"));
  
  //supplier -- returns an object
  Supplier personSupplier = Person::new;
  Person newPerson = personSupplier.get();   // new Person
  newPerson.firstName="hello";
  newPerson.lastName = "newperson";
  System.out.println(newPerson.firstName + " " + newPerson.lastName);
  
  //predicates accept one argument
  //return true or false
  Predicate predicate = (s) -> s.length() > 0;

  predicate.test("foo");              // true
  predicate.negate().test("foo");     // false

  Predicate nonNull = Objects::nonNull;
  Predicate isNull = Objects::isNull;

  Predicate isEmpty = String::isEmpty;
  Predicate isNotEmpty = isEmpty.negate();
  
  //functions accept one argument and return a result 
  Function toInteger = Integer::valueOf;
  Function backToString = toInteger.andThen(String::valueOf);

  backToString.apply("123");     // "123"
  
  //optional
  //return null or non-null with optional????????
  
  String friend="bam";
  Optional optional = Optional.of(friend);
  optional.isPresent();           // true
  optional.get();                 // "bam"
  optional.orElse("fallback");    // "bam"

  optional.ifPresent((s) -> System.out.println(s.charAt(0)));     // "b"
  
  Supplier stringSupplier = String::new;
  String newString = (String)stringSupplier.get();
  System.out.println("newString:<" + newString + "> optinal output:<" + optional.orElseGet(stringSupplier) + ">");
  
  //to show function usage  
   List persons = new ArrayList();
         persons.add(new NamedPerson("Albert", 80));
         persons.add(new NamedPerson("Ben", 15));
         persons.add(new NamedPerson("Charlote", 20));
         persons.add(new NamedPerson("Dean", 6));
         persons.add(new NamedPerson("Elaine", 17));
         
         
        List allAges = Java8Tut.listAllAges(persons, NamedPerson::getAge);
        System.out.println("Printing out all ages \n"+allAges);
      
        //to show consumer usage
        
        List myNames = new ArrayList();
        myNames.add("David");
        myNames.add("Richard");
        myNames.add("Samuel");
        myNames.add("Rose");
        myNames.add("John");

        System.out.println("Print Names--->");
        Java8Tut.printNames(myNames,System.out::println);

        //to show function usage vs predicate usage
        List  numbers = Arrays.asList(4,9,16,25,36);
        List squaredNumbers = Java8Tut.findSquareRoot(numbers,Double::new);
        System.out.println("Square root of numbers = "+squaredNumbers);
        
        List primes = findPrimesUsingFunction(numbers, Java8Tut::isPrime);
        System.out.println("Function Primes: " + primes);
        primes = findPrimesUsingPredicate(numbers, Java8Tut::isPrime);
        System.out.println("Predicate Primes: " + primes);
        
        primes = findPrimeNumbersUsingPredictaeAndStreamAndFilter(numbers, Java8Tut::isPrime);
        System.out.println("Predicate2 Primes: " + primes);
        
        //method parameters
        //running with java8Tut -parameters will show the parameter names for methods that are PUBLIC
        Method[] methods = Java8Tut.class.getMethods();
        for (Method method : methods) {
            System.out.print(method.getName() + "(");
            Parameter[] parameters = method.getParameters();
            for (Parameter parameter : parameters) {
                System.out.print(parameter.getType().getName() + " " + parameter.getName() + " ");
            }
            System.out.println(")");
        }
        
        //in Swing
     // Before Java 8:
        JButton show =  new JButton("Show");
        show.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
                   System.out.println("Event handling without lambda expression is boring");
                }
             });


        // Java 8 way:
        show.addActionListener((e) -> {
            System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
        });
        
      //Prior Java 8 :
        List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        for (String feature : features) {
           System.out.println(feature);
        }

        //In Java 8:
        features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        features.forEach(n -> System.out.println(n));

        // Even better use Method reference feature of Java 8
        // method reference is denoted by :: (double colon) operator
        // looks similar to score resolution operator of C++
        features.forEach(System.out::println);
        
        List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");

        System.out.println("Languages which starts with J :");
        filter1(languages, (str)-> ((String)str).startsWith("J"));

        System.out.println("Languages which ends with a ");
        filter1(languages, (str)-> ((String)str).endsWith("a"));

        System.out.println("Print all languages :");
        filter2(languages, (str)->true);

         System.out.println("Print no language : ");
         filter2(languages, (str)->false);

         System.out.println("Print language whose length greater than 4:");
         filter1(languages, (str)->((String)str).length() > 4);
         
      // We can even combine Predicate using and(), or() And xor() logical functions
         // for example to find names, which starts with J and four letters long, you
         // can pass combination of two Predicate
         Predicate startsWithJ = (n) -> n.startsWith("J");
         Predicate fourLetterLong = (n) -> n.length() == 4;
           
         languages.stream()
              .filter(startsWithJ.and(fourLetterLong))
              .forEach((n) -> System.out.print("\nName, which starts with 'J' and four letter long is : " + n));

   
         
      // Applying 12% VAT on each purchase
      // Old way:
      List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
      double total = 0;
      for (Integer cost : costBeforeTax) {
       double price = cost + .12*cost;
       total = total + price;
       
      }
      System.out.println("\nTotal Old Way : " + total);

      // New way:
      costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
      double bill = costBeforeTax.stream().map((cost) -> cost + .12*cost).reduce((sum, cost) -> sum + cost).get();
      System.out.println("Total New Way : " + bill);
      
      
   // Convert String to Uppercase and join them using coma
      List G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
      String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
      System.out.println(G7Countries);
      
   // Create List of square of all distinct numbers
      List myNumbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
      List distinct = myNumbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
      System.out.printf("Original List : %s,  Square Without duplicates : %s %n", numbers, distinct);

    }
public static void filter1(List names, Predicate condition) {
    for(String name: names)  {
       if(condition.test(name)) {
          System.out.println(name + " ");
       }
    }
  }
 public static void filter2(List names, Predicate condition) {
    names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
        System.out.println(name + " ");
    });
 }

 private static void printNames(List list, Consumer c ){
     list.forEach(x -> c.accept(x));
 }
 private static boolean  isPrime(Integer x) {
  if (x == 0)
   return false;
  if (x % 2==0) return false;
  return true;
 }
 public static List findPrimeNumbersUsingPredictaeAndStreamAndFilter(List list, Predicate predicate) {
  List sortedNumbers = new ArrayList();
  list.stream().filter(predicate).forEach( sortedNumbers::add );
  return sortedNumbers;
  }
 private static List findPrimesUsingPredicate(List numList, Predicate f) {
  List primeList = new ArrayList();
  numList.forEach(x -> {if(f.test((Integer)x)) primeList.add((Integer)x);});
  return primeList;
 }
 
 private static List findPrimesUsingFunction(List numList, Function f) {
  List primeList = new ArrayList();
  numList.forEach(x -> {if(f.apply((Integer)x)) primeList.add((Integer)x);});
  return primeList;
 }
 private static List findSquareRoot(List list, Function f){
     List result = new ArrayList();
     list.forEach(x -> result.add(f.apply(Math.sqrt((Integer)x))));
     return result;
 }
 private static List listAllAges(List persons, Function  f){
     List result = new ArrayList();
     persons.forEach(x -> result.add(f.apply(x)));
     return result;
 }
 private static class NamedPerson {
   
        private final String name;
        private final int age;


        public NamedPerson(String name, int age) {
            this.name = name;
            this.age = age;

        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }


    }
 
 public static class Person {
  public String firstName;
  public String lastName;
  public Person() {
   
  }
  public Person(String fname, String lname) {
   this.firstName = fname;
   this.lastName = lname;
  }
 }
 
 @FunctionalInterface
 public interface PersonFactory 
{ P createPerson(String firstName, String lastName); } }