Showing posts with label lambda. Show all posts
Showing posts with label lambda. Show all posts

Saturday, June 14, 2014

Java 8 : Frequently Asked Questions for Interviews - 6

How can a Lambda Expression be converted to Functional Interface? Example.
When a Lambda expression is executed 
  • an object of some class that implements the functional interface is created behind the scenes.
  • when the abstract method on this object is invoked, the body of lambda expression is executed.
PTR: The management of these classes and objects are totally dependent on implementation but its still very efficient than using traditional inner classes.
  • This conversion to interfaces is what makes Lambda Expressions so compelling as the syntax is short and simple, easier to read.
Example:
Array.sort(cars, (Car firstCar, Car secondCar) ->
        firstCar.getColor().compareTo(secondCar.getColor() 
    );

Can you Assign a lambda expression to a variable ( ofcourse of type Object) ?
No, Since Object is not a Functional Interface. It does not have any abstract method.

Can we declare function types such as (String, String) -> int, as used in other programming languages that support function literals?
No, CONVERSION TO FUNCTIONAL INTERFACE is the ONLY THING that one can do with Lambda Expressions in Java.

  • There are no function types added to Java language in Java 8.
  • There are only Lambda expressions that can be converted to functional interfaces.
  • This is natural for Java programmers as they know that certain interfaces e.g.. Comparator has a specific purpose. Its not just a method with given params and return type. So when you want to use Lamdba Expressions , its important to keep the purpose in perspective and have a specific functional interface for it.
For example: java.util.function has various generic functional interfaces. One such interface is BiFunction(T, U, R), describes functions with parameter types T and U and a return type R. We can use it as
BiFunction comp = (int first, int second) -> Integer.compare(first.length(), second.length())
However, that does not help with sorting, as Arrays.sort does not want a BiFunction. It wants a Comparator.

Are there any annotations introduced to help identify Functional Interfaces?
Yes, the annotation @FunctionalInterfaces can be used to tag any functional interface. It has two advantages 

  • The compiler will check the annotated entity to see if it has a single abstract interface or not.
  • The Javadoc page will include an statement that the annotated entity is a functional interfaces
However, the use of @FunctionalInterface is totally optional. Any interface having a single abstract method can be used a functional interface.

Does Checked exceptions matter in lambda Expressions? If yes, when and when not?
Yes, Checked exceptions matter when a lambda is converted to an instance of a functional interface. In case the body of lambda expression throws a checked exception, that exception needs to be declared in the abstract method of functional interface.
For example, Callable interface has an abstract call method that throws "Exception". However, the Run method in Runnable interface throws no exception of any sort.
Declaration :

public interface Callable<V> has abstract method V call throws Exception
Callable sleepDuringCall = () -> { 
    System.out.println("Calling"); 
    Thread.sleep(10000);} 
Thread.sleep (declared as public static void sleep(long miliseconds) throws InterruptedException) can throw checked exception.

Whereas,
public interface Runnable has abstract method void run()
Runnable sleepWhileRunning = () -> { 
    System.out.println("Sleeping during run"); 
    Thread.sleep(10); }
// will error out as Thread.sleep throws a checked exception.
However, you can catch the checked exception inside of the lambda body to keep the assignment legal.
Runnable sleepWhileRunning = () -> { 
    System.out.println("Sleeping during run"); 
    try{ 
        Thread.sleep(10); 
    }catch( InterrrupedException e){
        e.printStackTrace();
    }
}

Friday, June 13, 2014

Java 8 : Frequently Asked Questions for Interview - 3

What is Lambda Expression?
Lamdba expressions are just a block of code that can be passed around, which can be executed later, once or multiple times. A detailed answer here

Follow-up Question - Where have you seen similar code blocks in Java all along, before Java 8?

There are several examples where you write code in Java at some point, and it is executed at a later time. However, since Java is Object Oriented language, its not easy to pass or give somebody a block of code without having to construct an object belonging to a class that has the method with the desired behavior ( the method is the only behavior we want to execute ).
  1. run Method of a Runnable : while working with separate threads, we put the work in run method of a Runnable. Which we either execute by constructing an instance of the class that implements Runnable or simply submit the instance to a thread pool to start it in queue.
  2. class Task implements Runnable {
        public void run() {
            for(int i = 0; i < 10 ; i++) doTask(); 
        }
    }
    
    Task task = new Task();
    new Thread(w).start();
    
  3. sorting with custom comparator :while primitive sorts can work without any custom comparator code, sometimes the need arises to sort values based on different criteria. For instance  sorting an array of car objects, based on first their color, or their ratings or based on their prices. One can construct separate comparators and pass it to Array.sort method to defer the sorting at runtime. Note: the current code works with Java7 which has static method Integer.compare implemented in core java library.
  4. class ColorComparator implements Comparator<Car> {
        public int compare(Car firstCar, Car secondCar) {
            return firstCar.getColor().compareTo(secondCar.getColor()); 
        }
    }
    class RatingComparator implements Comparator<Car> {
        public int compare(Car firstCar, Car secondCar) {
            return Float.compare(firstCar.getRatings(),secondCar.getRatings());
        }
    }
    
    class PriceComparator implements Comparator<Car> {
        public int compare(Car firstCar, Car secondCar) {
            return Integer.compare(firstCar.getPrice(),secondCar.getPrice());
        }
    }
    
    
    Car cars = new Car[] { new Car("blue", 5.2f, 12000), new Car("green", 5.1f, 200000), new Car("grey", 6.2f, 1000), new Car("blue", 5.25f, 12090)}
    Arrays.sort(cars, newColorComparator());
    Color Cars
    Car [ blue, 5.2 12000 ]
    Car [ blue, 5.25 12090 ]
    Car [ green, 5.1 200000 ]
    Car [ grey, 6.2 1000 ]
    
    Arrays.sort(cars, new RatingComparator());
    Ratings Cars
    Car [ green, 5.1 200000 ]
    Car [ blue, 5.2 12000 ]
    Car [ blue, 5.25 12090 ]
    Car [ grey, 6.2 1000 ]
    
    Arrays.sort(cars, new PriceComparator());
    Price Cars
    Car [ grey, 6.2 1000 ]
    Car [ blue, 5.2 12000 ]
    Car [ blue, 5.25 12090 ]
    Car [ green, 5.1 200000 ]
    
    
  5. button callback : Button callback is another example of deferred execution. A callback action added to a class implementing the listener interface is a good example of that sort. For button, we can construct an instance of the class implementing the listener interface and then register it to the button class. In fact, the strategy is used often for creating GUI component callback actions the most listeners use "anonymous instance of the anonymous class".
  6. button.setOnAction(new EventHandler<actionEvent>() {
        public void handle(ActionEvent event) {
            System.out.Println("Event registered with User's click!!!")
        }
    }
    
    
    The callback is executed only on the click of the button, which eventually calls the code inside the handle method.
NOTE : It is possible to work with blocks of code in directly in other languages, However, in those languages it is vary easy to spawn a thread or to register a button click handler. In java, one could accomplish similar goals by writing similar API, but such API would be very unpleasant to use.