Saravanan's Corner: Blackberry Dev

Monday, 15 February 2021

Java 8 Features

Some of the important Java 8 features are;

  1. forEach() method in Iterable interface
  2. default and static methods in Interfaces
  3. Functional Interfaces and Lambda Expressions
  4. Java Stream API for Bulk Data Operations on Collections
  5. Java Time API
  6. Collection API improvements
  7. Concurrency API improvements
  8. Java IO improvements
  9. Miscellaneous Core API improvements
  1. forEach() method in Iterable interface

    Whenever we need to traverse through a Collection, we need to create an Iterator whose whole purpose is to iterate over and then we have business logic in a loop for each of the elements in the Collection. We might get ConcurrentModificationException if iterator is not used properly.

    Java 8 has introduced forEach method in java.lang.Iterable interface so that while writing code we focus on business logic only. forEach method takes java.util.function.Consumer object as argument, so it helps in having our business logic at a separate location that we can reuse. Let’s see forEach usage with simple example.

    package com.journaldev.java8.foreach;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.function.Consumer;
    import java.lang.Integer;
    
    public class Java8ForEachExample {
    
    	public static void main(String[] args) {
    		
    		//creating sample Collection
    		List<Integer> myList = new ArrayList<Integer>();
    		for(int i=0; i<10; i++) myList.add(i);
    		
    		//traversing using Iterator
    		Iterator<Integer> it = myList.iterator();
    		while(it.hasNext()){
    			Integer i = it.next();
    			System.out.println("Iterator Value::"+i);
    		}
    		
    		//traversing through forEach method of Iterable with anonymous class
    		myList.forEach(new Consumer<Integer>() {
    
    			public void accept(Integer t) {
    				System.out.println("forEach anonymous class Value::"+t);
    			}
    
    		});
    		
    		//traversing with Consumer interface implementation
    		MyConsumer action = new MyConsumer();
    		myList.forEach(action);
    		
    	}
    
    }
    
    //Consumer implementation that can be reused
    class MyConsumer implements Consumer<Integer>{
    
    	public void accept(Integer t) {
    		System.out.println("Consumer impl Value::"+t);
    	}
    
    
    }
    

    The number of lines might increase but forEach method helps in having the logic for iteration and business logic at separate place resulting in higher separation of concern and cleaner code.

  2. default and static methods in Interfaces

    If you read forEach method details carefully, you will notice that it’s defined in Iterable interface but we know that interfaces can’t have method body. From Java 8, interfaces are enhanced to have method with implementation. We can use default and static keyword to create interfaces with method implementation. forEach method implementation in Iterable interface is:

    	default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    

    We know that Java doesn’t provide multiple inheritance in Classes because it leads to Diamond Problem. So how it will be handled with interfaces now, since interfaces are now similar to abstract classes. The solution is that compiler will throw exception in this scenario and we will have to provide implementation logic in the class implementing the interfaces.

    package com.journaldev.java8.defaultmethod;
    
    @FunctionalInterface
    public interface Interface1 {
    
    	void method1(String str);
    	
    	default void log(String str){
    		System.out.println("I1 logging::"+str);
    	}
    	
    	static void print(String str){
    		System.out.println("Printing "+str);
    	}
    	
    	//trying to override Object method gives compile-time error as
    	//"A default method cannot override a method from java.lang.Object"
    	
    //	default String toString(){
    //		return "i1";
    //	}
    	
    }
    
    package com.journaldev.java8.defaultmethod;
    
    @FunctionalInterface
    public interface Interface2 {
    
    	void method2();
    	
    	default void log(String str){
    		System.out.println("I2 logging::"+str);
    	}
    
    }
    

    Notice that both the interfaces have a common method log() with implementation logic.

    package com.journaldev.java8.defaultmethod;
    
    public class MyClass implements Interface1, Interface2 {
    
    	@Override
    	public void method2() {
    	}
    
    	@Override
    	public void method1(String str) {
    	}
    
    	//MyClass won't compile without having it's own log() implementation
    	@Override
    	public void log(String str){
    		System.out.println("MyClass logging::"+str);
    		Interface1.print("abc");
    	}
    	
    }
    

    As you can see that Interface1 has static method implementation that is used in MyClass.log() method implementation. Java 8 uses default and static methods heavily in Collection API and default methods are added so that our code remains backward compatible.

    If any class in the hierarchy has a method with the same signature, then default methods become irrelevant. Since any class implementing an interface already has Object as a superclass, if we have equals(), hashCode() default methods in the interface, it will become irrelevant. That’s why for better clarity, interfaces are not allowed to have Object default methods.

    For complete details of interface changes in Java 8, please read Java 8 interface changes.

  3. Functional Interfaces and Lambda Expressions

    If you notice above interfaces code, you will notice @FunctionalInterface annotation. Functional interfaces are new concept introduced in Java 8. An interface with exactly one abstract method becomes Functional Interface. We don’t need to use @FunctionalInterface annotation to mark an interface as Functional Interface. @FunctionalInterface annotation is a facility to avoid accidental addition of abstract methods in the functional interfaces. You can think of it like @Override annotation and it’s best practice to use it. java.lang.Runnable with single abstract method run() is a great example of functional interface.

    One of the major benefits of functional interface is the possibility to use lambda expressions to instantiate them. We can instantiate an interface with anonymous class but the code looks bulky.

    Runnable r = new Runnable(){
    			@Override
    			public void run() {
    				System.out.println("My Runnable");
    			}};
    

    Since functional interfaces have only one method, lambda expressions can easily provide the method implementation. We just need to provide method arguments and business logic. For example, we can write above implementation using lambda expression as:

    Runnable r1 = () -> {
    			System.out.println("My Runnable");
    		};
    

    If you have single statement in method implementation, we don’t need curly braces also. For example above Interface1 anonymous class can be instantiated using lambda as follows:

    Interface1 i1 = (s) -> System.out.println(s);
    		
    i1.method1("abc");
    

    So lambda expressions are a means to create anonymous classes of functional interfaces easily. There are no runtime benefits of using lambda expressions, so I will use it cautiously because I don’t mind writing a few extra lines of code.

    A new package java.util.function has been added with bunch of functional interfaces to provide target types for lambda expressions and method references. Lambda expressions are a huge topic, I will write a separate article on that in the future.

    You can read complete tutorial at Java 8 Lambda Expressions Tutorial.

  4. Java Stream API for Bulk Data Operations on Collections

    A new java.util.stream has been added in Java 8 to perform filter/map/reduce like operations with the collection. Stream API will allow sequential as well as parallel execution. This is one of the best features for me because I work a lot with Collections and usually with Big Data, we need to filter out them based on some conditions.

    Collection interface has been extended with stream() and parallelStream() default methods to get the Stream for sequential and parallel execution. Let’s see their usage with simple example.

    package com.journaldev.java8.stream;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Stream;
    
    public class StreamExample {
    
    	public static void main(String[] args) {
    		
    		List<Integer> myList = new ArrayList<>();
    		for(int i=0; i<100; i++) myList.add(i);
    		
    		//sequential stream
    		Stream<Integer> sequentialStream = myList.stream();
    		
    		//parallel stream
    		Stream<Integer> parallelStream = myList.parallelStream();
    		
    		//using lambda with Stream API, filter example
    		Stream<Integer> highNums = parallelStream.filter(p -> p > 90);
    		//using lambda in forEach
    		highNums.forEach(p -> System.out.println("High Nums parallel="+p));
    		
    		Stream<Integer> highNumsSeq = sequentialStream.filter(p -> p > 90);
    		highNumsSeq.forEach(p -> System.out.println("High Nums sequential="+p));
    
    	}
    
    }
    

    If you will run above example code, you will get output like this:

    High Nums parallel=91
    High Nums parallel=96
    High Nums parallel=93
    High Nums parallel=98
    High Nums parallel=94
    High Nums parallel=95
    High Nums parallel=97
    High Nums parallel=92
    High Nums parallel=99
    High Nums sequential=91
    High Nums sequential=92
    High Nums sequential=93
    High Nums sequential=94
    High Nums sequential=95
    High Nums sequential=96
    High Nums sequential=97
    High Nums sequential=98
    High Nums sequential=99
    

    Notice that parallel processing values are not in order, so parallel processing will be very helpful while working with huge collections.
    Covering everything about Stream API is not possible in this post, you can read everything about Stream API at Java 8 Stream API Example Tutorial.

  5. Java Time API

    It has always been hard to work with Date, Time and Time Zones in java. There was no standard approach or API in java for date and time in Java. One of the nice addition in Java 8 is the java.time package that will streamline the process of working with time in java.

    Just by looking at Java Time API packages, I can sense that it will be very easy to use. It has some sub-packages java.time.format that provides classes to print and parse dates and times and java.time.zone provides support for time-zones and their rules.

    The new Time API prefers enums over integer constants for months and days of the week. One of the useful class is DateTimeFormatter for converting DateTime objects to strings.

    For complete tutorial, head over to Java Date Time API Example Tutorial.

  6. Collection API improvements

    We have already seen forEach() method and Stream API for collections. Some new methods added in Collection API are:

    • Iterator default method forEachRemaining(Consumer action) to perform the given action for each remaining element until all elements have been processed or the action throws an exception.
    • Collection default method removeIf(Predicate filter) to remove all of the elements of this collection that satisfy the given predicate.
    • Collection spliterator() method returning Spliterator instance that can be used to traverse elements sequentially or parallel.
    • Map replaceAll()compute()merge() methods.
    • Performance Improvement for HashMap class with Key Collisions
  7. Concurrency API improvements

    Some important concurrent API enhancements are:

    • ConcurrentHashMap compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), reduce() and search() methods.
    • CompletableFuture that may be explicitly completed (setting its value and status).
    • Executors newWorkStealingPool() method to create a work-stealing thread pool using all available processors as its target parallelism level.
  8. Java IO improvements

    Some IO improvements known to me are:

    • Files.list(Path dir) that returns a lazily populated Stream, the elements of which are the entries in the directory.
    • Files.lines(Path path) that reads all lines from a file as a Stream.
    • Files.find() that returns a Stream that is lazily populated with Path by searching for files in a file tree rooted at a given starting file.
    • BufferedReader.lines() that return a Stream, the elements of which are lines read from this BufferedReader.
  9. Miscellaneous Core API improvements

    Some misc API improvements that might come handy are:

    1. ThreadLocal static method withInitial(Supplier supplier) to create instance easily.
    2. Comparator interface has been extended with a lot of default and static methods for natural ordering, reverse order etc.
    3. min(), max() and sum() methods in Integer, Long and Double wrapper classes.
    4. logicalAnd(), logicalOr() and logicalXor() methods in Boolean class.
    5. ZipFile.stream() method to get an ordered Stream over the ZIP file entries. Entries appear in the Stream in the order they appear in the central directory of the ZIP file.
    6. Several utility methods in Math class.
    7. jjs command is added to invoke Nashorn Engine.
    8. jdeps command is added to analyze class files
    9. JDBC-ODBC Bridge has been removed.
    10. PermGen memory space has been removed

That’s all for Java 8 features with example programs. If I have missed some important features of Java 8, please let me know through comments.

Saturday, 13 February 2021

What is hashCode?

The hashcode of a Java Object is simply a number, it is 32-bit signed int, that allows an object to be managed by a hash-based data structure. We know that hash code is a unique id number allocated to an object by JVM. But actually speaking, Hash code is not an unique number for an object. If two objects are equals then these two objects should return the same hash code. So we have to implement hashcode() method of a class in such way that if two objects are equals, ie compared by equal() method of that class, then those two objects must return same hash code. If you are overriding hashCode you need to override equals method also.

What is the difference between Hashtable and HashMap?

Answer:
The basic differences are Hashtable is synchronized and HashMap is not synchronized. Hashtable does not allow null values, and HashMap allows null values.

What is the difference between ArrayList and LinkedList?

Answer:

Both ArrayList and LinkedList are implementation of List interface in Java. Both classes are non-synchronized. But there are certain differences as well.

Following are the important differences between ArrayList and LinkedList method.

Sr. No.
Key
ArrayList
LinkedList
1
Internal Implementation
ArrayList internally uses a dynamic array to store its elements.
LinkedList uses Doubly Linked List to store its elements.
2
Manipulation
ArrayList is slow as array manipulation is slower.
LinkedList is faster being node based as not much bit shifting required.
3
Implementation
ArrayList implements only List.
LinkedList implements List as well as Queue. It can acts as a queue as well.
4
Access
ArrayList is faster in storing and accessing data.
LinkedList is faster in manipulation of data.


Tuesday, 22 October 2019

Lamda Expression

Lamda


ArrayList<Employee> e = new ArrayList<Employee>();
   
    e.add(new Employee("Balu", 1));
    e.add(new Employee("zahir", 2));
    e.add(new Employee("Kannan", 3));
    e.add(new Employee("Mani", 4));
   
    System.out.println(e);
    //sorting order using eno
    Comparator<Employee> c=(e1, e2)->(e1.eno<e2.eno?-1:e1.eno>e2.eno?1:0);
   
    Collections.sort(e, c);
   
    e.stream().forEach(System.out::println);
    //alphabetical order using name
    Collections.sort(e, (e1,e2)->(e1.name.compareTo(e2.name)));
   
    e.stream().forEach(System.out::print);





Static

if a field is declared static, then exactly a single copy of that field is created and shared among all instances of that class

From the memory perspective, static variables go in a particular pool in JVM memory called Metaspace (before Java 8, this pool was called Permanent Generation or PermGen, which was completely removed and replaced with Metaspace).

  • Since static variables belong to a class, they can be accessed directly using class name and don’t need any object reference
  • static variables can only be declared at the class level
  • static fields can be accessed without object initialization
  • Although we can access static fields using an object reference (like ford.numberOfCars++) , we should refrain from using it as in this case it becomes difficult to figure whether it’s an instance variable or a class variable; instead, we should always refer to static variables using class name (for example, in this case, Car.numberOfCars++)





Monday, 15 October 2018

Collection Framework

There are 9 key Interfaces are available in collection framework



1. Collection -

1. If you want to represent a group of an individual object as an entity, you should go for Collection

2 In general, the collection interface is considered a root interface of any collection interface

3. Define the most common methods which are applicable for any collection objects

4. There is no concrete class that implements the collection interface directly.

2. List Interface -

1. if you want to represent a group of an individual object as an entity where duplicates allowed and insert order is preserved

2. ArrayList, Linked List, Vector and Stacks are Implementation classes

Collections --> List --> ArrayList,
                                      Linked List,
                                      Vector-->Stacks
                                                                 
3. Collections came in 1.2

4. Vector came in 1.0 version which are legacy classes

3. SET

1. if you want to represent a group of individual objects as an entity where duplicates are not allowed and insert no order is preserved

2. Hash set, LinkedHashSet

Collections (1.2v)--> Set (1.2v)--> HashSet(1.2v) --> LinkedHashset (1.4)

Difference between SET and LIST

List - Duplicates allowed, Insertion order is preserved

SET - Duplicated not allowed, Insertion order is not preserved


4. SortedSet Interface

1. if you want to represent a group of individual objects as an entity where duplicates are not allowed and all objects inserted in sorting order

Collections (I)--> Set (I)--> SortedSet (I)(1.2v)

5. NavigableSet Interface

NavigableSet is child interface of SortedSet defines several methods for navigation purpose

Collections (I)--> Set (I)--> SortedSet (I)(1.2v) --> NavigableSet (I) (1.2v) --> TreeSet (Imp class) (1.2)

6. Queue Interface

If you want to represent a group of an individual object prior to processing then go for Queue

Queue Implementation classes: (V1.5)
 Priority Queue, Blocking Queue, Linked Blocking Queue, PriorityBlockingQueue

7. Map

If you want to represent a group of an individual object as a key-value pair then go for Map interface

- Map is not child interface of collection

- Duplicate keys are not allowed but values can be duplicate

Implementation classes:

Hashmap, LinkedHashmap, WeakHshMap, IdentityHashMap, HashTable, Properties, Dictionary

Map -> Hashmap -> LinkedHashmap (1.4v)

Map -> WeakHshMap (1.4v)

Map -> IdentityHashMap (1.4v)

Map -> HashTable
                                --> Properties (1.0v)
                                ---> Dictionary (1.0v)

8.SortedMap

If you want to represent a group of an individual object as a key-value pair with some sorted order of keys then go for SortedMap interface

Map --> SortedMap

9. NavigableMap

It defines several utility methods for navigation purpose

Map --> SortedMap --> Navigable Map (1.6v) --> TreeMap(Impl)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-----------------------------------------------------------------------------------------
               |  Implements   | Order | Random | Key-Value | Duplicate | Null | Thread |
-----------------------------------------------------------------------------------------
ArrayList      |      List     |    X  |    X   |           |     X     |   X  |        |
-----------------------------------------------------------------------------------------
Vector         |      List     |    X  |    X   |           |     X     |   X  |    X   |
-----------------------------------------------------------------------------------------
LinkedList     | List, Deque   |    X  |        |           |     X     |   X  |    X   |
-----------------------------------------------------------------------------------------
HashSet        |      Set      |    X  |    X   |      X    |     X     |   X  |        |
-----------------------------------------------------------------------------------------
TreeSet        |   SortedSet   |    X  |    X   |           |           |      |        |
-----------------------------------------------------------------------------------------
Stack          | Vector, List  |    X  |        |           |     X     |   X  |    X   |
-----------------------------------------------------------------------------------------
Properties     | Hashtable,Map |       |    X   |      X    |           |      |    X   |
-----------------------------------------------------------------------------------------
HashMap        |      Map      |       |    X   |      X    |           |   X  |        |
-----------------------------------------------------------------------------------------
TreeMap        |   SortedMap   |    X  |    X   |      X    |           |      |        |
-----------------------------------------------------------------------------------------
Hashtable      |      Map      |       |    X   |      X    |           |      |    X   |
-----------------------------------------------------------------------------------------

Where to use ArrayList in java

This is obvious that if ArrayList is the part of Collection Framework then it will give some sort of operation (store, retrieve, searching, sorting, insertion, deletion, and advance manipulation) on the Objects stored inside it.
  • ArrayList provides faster iteration so where faster iteration or index-based retrieval is required and there are not many additions or deletion operation takes place then it is recommended to use ArrayList in java.
  • ArrayList is slower in addition or removal data, so where more operation of addition and deletion is required then the use of ArrayList is not recommended.
        
        System.out.println("Following is the output ArrayList with for loop");
        for(String name : listName){  // for loop to iterate arraylist
             System.out.println(name); 
        
         
        System.out.println("Following is the output ArrayList with for loop");
         
        Iterator itr = listName.iterator();//getting Iterator from arraylist to iterate elements 
        while(itr.hasNext()){
            String name = itr.next();
            System.out.println(name); 
        }

ArrayList in java collections framework is defined as below -
  • ArrayList in java is used to store the java element or object.
  • ArrayList class extends AbstractList class and implements List interface.
  • ArrayList stores and iterates data in order to which they are inserted.
  • ArrayList class uses arrays to store the element or object internally.
  • ArrayList size grows automatically when elements or objects are added to it.
  • Java ArrayList allows random access of elements and java objects.
  • ArrayList class can store duplicate elements or java objects.
  • ArrayList class is not thread-safe. if thread safety is required we need to synchronize this.