Core Java Interview Questions and Answers
Core Java Interview Questions and Answers
Revision History
3
21.2 How get() methods works internally ........................................................... 47
21.3 In case of null Key......................................................................................47
21.4 HashMap changes in Java 8 ......................................................................47
22. Overriding hashCode() and equals() method........................................................... 48
22.1 Usage of hashCode() and equals() ............................................................... 48
22.2 When do we need to override hashCode() and equals() ............................... 49
22.3 Requirements for implementing equals() and hashCode() ........................... 51
23. How HashSet works internally ..............................................................................52
23.1 How elements are added in HashSet .......................................................... 53
23.2 How Object is removed from a HashSet ......................................................53
23.3 How Object is retrieved from HashSet ........................................................ 54
24. Iterate over HashMap, Hashtable or any Map ......................................................... 54
24.1 Iterating or looping map using Java5 foreach loop .....................................54
24.2 Iterating Map in Java using KeySet Iterator ...............................................55
24.3 Looping HashMap in Java using EntrySet and Java 5 for loop ...................55
24.4 Iterating HashMap in Java using EntrySet and Java iterator .....................56
24.5 Java 8 – lambda method ............................................................................56
25. ConcurrentHashMap, Hashtable and Synchronized Map ..........................................57
25.1 Why need ConcurrentHashMap and CopyOnWriteArrayList ....................... 58
25.2 Difference between ConcurrentHashMap and Hashtable ............................ 59
25.3 The difference between ConcurrentHashMap and
Collections.synchronizedMap..................................................................................59
25.4 Difference between ConcurrentHashMap and HashMap ............................. 59
26. ConcurrentHashMap in Java ................................................................................60
26.1 Why another Map ......................................................................................61
26.2 How performance is improved ....................................................................62
26.3 Simple example using ConcurrentHashMap ...............................................62
26.4 Null is not allowed .....................................................................................63
26.5 Atomic operations ......................................................................................63
26.6 Fail-safe iterator ........................................................................................ 64
26.7 When ConcurrentHashMap is a better choice ............................................65
26.8 Points to note ............................................................................................. 65
27. Java Class Loading ............................................................................................. 65
27.1 What is ClassLoader ..................................................................................66
27.2 How ClassLoader works .............................................................................66
27.3 Delegation principles..................................................................................67
27.4 Visibility Principle ......................................................................................67
27.5 Visibility Principle ......................................................................................68
4
27.6 How to load class explicitly ........................................................................68
27.7 Where to use ClassLoader ..........................................................................69
28. When a class is loaded and initialized in JVM ......................................................... 69
28.1 When Class is loaded .................................................................................69
28.2 When a Class is initialized .........................................................................69
28.3 How Class is initialized ..............................................................................70
28.4 Examples of class initialization .................................................................70
28.5 Observation ............................................................................................... 71
29. Difference between Comparable and Comparator ...................................................72
29.1 Comparable interface .................................................................................73
29.2 Comparator interface .................................................................................73
29.3 Example code............................................................................................. 73
29.4 When do we need Comparator....................................................................75
29.5 When to use Comparator and Comparable .................................................78
30. Final Vs finally Vs finalize .....................................................................................79
30.1 final ...........................................................................................................79
30.1.1 final variable in Java ..................................................................................79
30.1.2 Final object ................................................................................................ 79
30.1.3 final method parameter ..............................................................................79
30.1.4 Final variables and thread safety ............................................................... 79
30.1.5 final with inheritance .................................................................................80
30.1.6 final method............................................................................................... 80
30.1.7 Benefit of final method ...............................................................................80
30.1.8 Final Class .................................................................................................80
30.1.9 Benefits of final class .................................................................................80
30.1.10 Points to note ............................................................................................. 80
30.2 finally.........................................................................................................81
30.2.1 Example of finally ......................................................................................81
30.2.2 Points to note ............................................................................................. 83
30.3 finalize() .....................................................................................................83
30.3.1 When is finalize() method called .................................................................83
30.3.2 General form of finalize method .................................................................84
30.3.3 How to use finalize method ........................................................................84
30.3.4 How to properly write a finalize() method....................................................84
30.3.5 Example code for finalize method ............................................................... 85
30.3.6 When we can use finalize method .............................................................. 86
30.3.7 Finalize method and exception handling ....................................................86
5
30.3.8 Points to note ............................................................................................. 86
31. fail-fast Vs fail-safe iterator ...................................................................................86
31.1 fail-fast iterator .......................................................................................... 87
31.2 Fail Safe iterator ........................................................................................ 91
31.3 Points to note ............................................................................................. 92
32. What are the changes in Collections framework in Java 8? .......................................92
33. Overview of lambda expression in Java 8 ....................................................................93
33.1 What is a lambda expression? ....................................................................93
33.2 What is a functional interface? ...................................................................94
33.3 Type of Lambda expression ........................................................................94
33.4 Points to note ............................................................................................. 97
34. Difference between iterator and ListIterator? .............................................................. 97
35. What happens if HashMap has duplicate keys? ............................................................. 97
36. Difference between ArrayList and LinkedList ................................................................ 98
36.1 Adding an element .....................................................................................98
36.2 Retrieving an element ................................................................................98
36.3 Removing an element .................................................................................99
36.4 Removing an element while iterating .......................................................... 99
37. Difference between ArrayList and Vector ...................................................................99
38. TreeMap in Java ................................................................................................ 100
38.1 How TreeMap is implemented .................................................................. 100
38.2 TreeMap doesn't allow null....................................................................... 101
38.3 TreeMap is not synchronized.................................................................... 101
38.4 TreeMap class' iterator is fail-fast............................................................. 102
38.5 Sorting elements in different order in TreeMap......................................... 102
6
1. String vs StringBuffer vs StringBuilder
1.1. String in Java
String class represents character strings, we can instantiate String by two ways.
String str = "abc"; or String str = new String ("abc");
String is immutable in java, so its easy to share it across different threads or functions.
When we create a String using double quotes, it first looks for the String with same value in the
JVM string pool, if found it returns the reference else it creates the String object and then place
it in the String pool. This way JVM saves a lot of space by using same String in different threads.
But if new operator is used, it explicitly creates a new String in the heap memory.
+ operator is overloaded for String and used to concatenate two Strings. Although internally it
uses StringBuffer to perform this action.
String overrides equals() and hashCode() methods, two Strings are equal only if they have same
characters in same order. Note that equals() method is case sensitive, so if you are not looking
for case sensitive checks, you should use equalsIgnoreCase() method.
A String represents a string in the UTF-16 format
String is a final class with all the fields as final except “private int hash”. This field contains the
hashCode() function value and created only when hashCode() method is called and then cached
in this field. Furthermore, hash is generated using final fields of String class with some
calculations, so every time hashCode() method is called, it will result in same output. For caller,
its like calculations are happening every time but internally it’s cached in hash field.
7
For String manipulations in non-multi-threaded environment, we should use StringBuilder else
use StringBuffer class.
3.1 Pass-by-value
The actual parameter (or argument expression) is fully evaluated and the resulting value is copied into a
location being used to hold the formal parameter's value during method/function execution. That
location is typically a chunk of memory on the runtime stack for the application (which is how Java
handles it), but other languages could choose parameter storage differently.
3.2 Pass-by-reference
The formal parameter merely acts as an alias for the actual parameter. Anytime the method/function
uses the formal parameter (for reading or writing), it is actually using the actual parameter.
Java is strictly pass-by-value, exactly as in C. Read the Java Language Specification (JLS). In short: Java
has pointers and is strictly pass-by-value. There's no funky rules. It's simple, clean, and clear.
The Java Spec says that everything in java is pass-by-value. There is no such thing as "pass-by-reference"
in java.
8
foo(myDog);
you're essentially passing the address of the created Dog object to the foo method. (I say essentially b/c
java pointers aren't direct addresses, but it's easiest to think of them that way)
Suppose the Dog object resides at memory address 42. This means we pass 42 to the method.
at line "AAA"
someDog is followed to the Dog it points to (the Dog object at address 42) that Dog (the one at address
42) is asked to change his name to Max
at line "BBB"
a new Dog is created. Let's say he's at address 74 we assign the parameter someDog to 74
at line "CCC"
someDog is followed to the Dog it points to (the Dog object at address 74) that Dog (the one at address
74) is asked to change his name to Rowlf then, we return
There's the key.Keeping in mind that myDog is a pointer, and not an actual Dog, the answer is NO.
myDog still has the value 42; it's still pointing to the original Dog.
9
serializable. The serialization interface has no methods or fields and serves only to identify the
semantics of being serializable.
java.rmi.Remote - The Remote interface serves to identify interfaces whose methods may be
invoked from a non-local virtual machine. Any object that is a remote object must directly or
indirectly implement this interface. Only those methods specified in a "remote interface", an
interface that extends java.rmi.Remote are available remotely.
java.lang.Cloneable - A class implements the Cloneable interface to indicate to the
Object.clone() method that it is legal for that method to make a field-for-field copy of instances
of that class. Invoking Object's clone method on an instance that does not implement the
Cloneable interface results in the exception CloneNotSupportedException being thrown.
javax.servlet.SingleThreadModel - Ensures that servlets handle only one request at a time. This
interface has no methods.
java.util.EvenListener - A tagging interface that all event listener interfaces must extend.
The "instanceof" keyword in java can be used to test if an object is of a specified type. So this keyword in
combination with Marker interface can be used to take different actions based on type of interface an
object implements.
0,1,1,2,3,5,8,13,21,34.
The Fibonacci spiral: an approximation of the golden spiral created by drawing circular arcs connecting
the opposite corners of squares in the Fibonacci tiling;this one uses squares of sizes 1, 1, 2, 3, 5, 8, 13,
21, and 34. By definition, the first two numbers in the Fibonacci sequence are 1 and 1, or 0 and 1,
depending on the chosen starting point of the sequence, and each subsequent number is the sum of the
previous two.
public class FibonacciNumbers {
/**
* Recursive solution based on Fibonacci sequence definition. F(N) = F(N-1)
+ F(N-2).
10
*
* The complexity order of this algorithm is O(2^N) where N is integer used
as parameter. In space
* terms, the complexity order of this algorithm is O(1) because we are not
using any auxiliary
* data structure to solve this problem.
*/
public int getRecursive(int n) {
validateInput(n);
if (n == 0 || n == 1) {
return 1;
} else {
return getRecursive(n - 1) + getRecursive(n - 2);
}
}
/**
* Iterative approach. The complexity order in this algorithm is
O(N) where N is the integer used
* as parameter. In space terms, the complexity order of this
algorithm is again O(1).
*/
public int getIterative(int n) {
validateInput(n);
if (n <= 1) {
return 1;
}
int previous = 1;
int current = 1;
int element = 0;
for (int i = 2; i <= n; i++) {
element = previous + current;
previous = current;
current = element;
}
return element;
}
/**
* This version of the recursive algorithm is better in performance
terms because we are caching
* every calculated element to avoid every branch of the recursion
the same values. Is faster
* because one branch is going to take the already calculated value
from other branches and when
* you are going to calculate the 11th value the only thing you have
to calculate is to take
* previous values from the array instead of iterate from nth to 1
and sum every value. I've used
* a dynamic programming technique.
*
11
* The problem with this algorithm is related with the space
complexity which is much bigger than
* the one used for the previous algorithms. In this case, we have
O(N) because we are using an
* additional data structure to store partial results.
*/
public int getRecursiveWithCaching(int n) {
validateInput(n);
if (n <= 1) {
return 1;
} else if (elements[n] != 0) {
return elements[n];
}
elements[n] = getRecursiveWithCaching(n - 1) +
getRecursiveWithCaching(n - 2);
return elements[n];
}
/**
* Iterative solution for this problem. This version is based on the
factorial definition
* described in the statement and the complexity order in time terms of
this solution is O(N)
* where N is integer passed as argument. In space terms, the complexity
order of this algorithm
12
* is O(1) because we are not using any additional data structure related
to the integer passed
* as parameter.
*/
public int getIterative(int n) {
validateInput(n);
int result = 1;
for (int i = n; i >= 2; i--) {
result *= i;
}
return result;
}
/**
* Recursive implementation of the previous algorithm. The
complexity order in time and space
* terms is the same. Take into account that this implementation is
not tail recursive.
*/
public int getRecursive(int n) {
validateInput(n);
if (n == 0) {
return 1;
} else {
return n * getRecursive(n - 1);
}
}
/**
* Tail recursive implementation of the previous algorithm. The
complexity order in time and
* space terms is the same but the resources needed by the CPU to
execute this method is lower
* because this implementation is tail recursive.
*/
public int getTailRecursive(int n) {
validateInput(n);
return getTailRecursiveInner(n, 1);
}
13
8. Write a Java program to check if a number is Prime or
not?
A number is said prime if it is not divisible by any other number except itself. 1 is not considered prime,
so your check must start with 2. Simplest solution of this to check every number until the number itself
to see if its divisible or not.
8.1 Solution 1
public class Prime {
if (n%2 == 0){
return n==2;
}
if (n%3 ==0){
return n==3;
}
if (n%5 ==0){
return n==5;
}
for (int i = 7; i*i < n; i++) {
if (n%i == 0){
return false;
}
}
return true;
}
8.2 Solution 2
14
for(int i = 8 ; n > primes.size() ; i++) {
isPrime = true;
for(int prime : primes) {
if(i % prime == 0) {
isPrime = false;
break;
}
}
if(isPrime)
primes.add(i);
}
/**
* Iterative algorithm to solve this problem. The complexity order
in time and space terms of
* this algorithm is O(N) where N is the number of chars in the
input String. In time terms is
* possible to get O(N) because String class uses a char array
internally and the complexity
* order of charAt method is O(1).
*/
public String reverseIterative(String input) {
validateInput(input);
/**
* Tail recursive solution to this problem. This algorithm has the
same complexity order in time
* and space terms than the previous approach.
*/
public String reverseRecursive(String input) {
validateInput(input);
return reverseRecursiveInner(input, input.length() - 1, new
StringBuilder());
}
16
several body parts including Hand, Leg and Heart. When human object dies, all its body part ceased to
exist meaningfully, this is one example of Composition.
In Object-oriented programming, one object is related to other to use functionality and service provided
by that object. This relationship between two objects is known as the association in object oriented
general software design and depicted by an arrow in Unified Modelling language or UML. Both
Composition and Aggregation are the form of association between two objects, but there is a subtle
difference between composition and aggregation, which is also reflected by their UML notation. We
refer association between two objects as Composition, when one class owns other class and other class
can not meaningfully exist, when it's owner destroyed, for example, Human class is a composition of
several body parts including Hand, Leg and Heart. When human object dies, all it's body part ceased to
exist meaningfully, this is one example of Composition.
Another example of Composition is Car and it's part e.g. engines, wheels etc. Individual parts of the car
can not function when a car is destroyed. While in the case of Aggregation, including object can exists
without being part of the main object e.g. a Player which is part of a Team, can exist without a team and
can become part of other teams as well.
Another example of Aggregation is Student in School class, when School closed, Student still exist and
then can join another School or so. In UML notation, a composition is denoted by a filled diamond,
while aggregation is denoted by an empty diamond, which shows their obvious difference in terms of
strength of the relationship.
The composition is stronger than Aggregation. In Short, a relationship between two objects is referred
as an association, and an association is known as composition when one object owns other while an
association is known as aggregation when one object uses another object.
10.1 Composition
Since Engine is-part-of Car, the relationship between them is Composition. Here is how they are
implemented between Java classes.
public class Car {
//final will make sure engine is initialized
private final Engine engine;
public Car(){
engine = new Engine();
}
}
class Engine {
private String type;
}
10.2 Aggregation
Since Organization has Person as employees, the relationship between them is Aggregation. Here is how
they look like in terms of Java classes
public class Organization {
17
private List employees;
}
As I said all three denotes relationship between object and only differ in their strength, you can also
view them as below, where composition represents strongest form of relationship and association being
the most general form.
18
10.4 Association vs Composition vs Aggregation
Here is the list of differences between Composition and Aggregation in point format, for quick review.
As I said the key difference between them comes from the point that in the case of Composition, One
object is OWNER of another object, while in the case of aggregation, one object is just a USER or another
object.
1. If A and B two classes are related to each other such that, B ceased to exist, when A is destroyed, then
the association between two objects is known as Composition. An example is Car and Engine. While if A
and B are associated with each other, such that B can exist without being associated with A, then this
association in known as Aggregation.
2. In the case of Composition A owns B e.g. Person is the owner of his Hand, Mind and Heart, while in
the case of Aggregation, A uses B e.g. Organization uses People as an employee.
3. In UML diagram Association is denoted by a normal arrow head, while Composition is represented by
filled diamond arrow head, and Aggregation is represented by an empty diamond arrow head, As shown
in below and attached diagram in the third paragraph.
Association A---->B
Composition A-----<filled>B
Aggregation A-----<>B
4. Aggregation is a lighter form of Composition, where a sub-part object can meaningfully exist without
main objects.
5. In Java, you can use final keyword to represent Composition. Since in Composition, Owner object
expects a part object to be available and functions, by making it final, your provide guarantee that, when
Owner will be created, this part object will exist. This is actually a Java idiom to represent a strong form
of association i.e. composition between two objects.
6. Another interesting word, which comes handy to understand difference between Composition and
Aggregation in software design is "part-of" and "has". If one object is-part-of another object e.g. Engine
is part of Car, then association or relationship between them is Composition. On the other hand, if one
object just has another object e.g. Car has the driver then it's Aggregation.
19
11. Difference between Abstract class vs Interface
1) Interface in Java can only contains declaration. You can not declare any concrete methods inside
interface. On the other hand abstract class may contain both abstract and concrete methods, which
makes abstract class an ideal place to provide common or default functionality. I suggest reading my
post 10 things to know about interface in Java to know more about interfaces, particularly in Java
programming language.
2) Java interface can extend multiple interface also Java class can implement multiple interfaces, Which
means interface can provide more Polymorphism support than abstract class . By extending abstract
class, a class can only participate in one Type hierarchy but by using interface it can be part of multiple
type hierarchies. E.g. a class can be Runnable and Displayable at same time. One example I can
remember of this is writing GUI application in J2ME, where class extends Canvas and implements
CommandListener to provide both graphic and event-handling functionality.
3) In order to implement interface in Java, until your class is abstract, you need to provide
implementation of all methods, which is very painful. On the other hand abstract class may help you in
this case by providing default implementation. Because of this reason, I prefer to have minimum
methods in interface, starting from just one, I don't like idea of marker interface, once annotation is
introduced in Java 5. If you look JDK or any framework like Spring, which I does to understand OOPS and
design patter better, you will find that most of interface contains only one or two methods e.g.
Runnable, Callable, ActionListener etc.
2) Let's see another case where an abstract class suits better than interface. Since abstract class can
include concrete methods, it’s great for maintenance point of view, particularly when your base class is
evolving and keep changing. If you need a functionality across all your implementation e.g. a common
method, than, you need to change every single implementation to include that change if you have
chosen interface to describe your base class. Abstract class comes handy in this case because you can
just define new functionality in abstract super class and every sub class will automatically gets it. In
short, abstract class are great in terms of evolving functionality. If you are using interface, you need to
exercise extra care while defining contracts because it’s not easy to change them once published.
3) Interface in Java is great for defining Types. Programming for interfaces than implementation is also
one of the useful Object oriented design principle which suggests benefit of using interface as argument
to function, return type etc.
4) One more general rule of when to use abstract class and interface is to find out whether a certain
class will form a IS-A hierarchy or CAN-DO-THIS hierarchy. If you know that you will be creating classes
e.g. Circle, Square than it's better to create an abstract class Shape which can have area() and
20
perimeter() as abstract method, rather than defining Shape as interface in Java. On the other hand if you
are going to create classes which can do things like, can fly, you can use interface Flyable instead of
abstract class.
5) Interface generally define capability e.g. Runnable can run(), Callable can call(), Displayable can
display(). So if you need to define capability, consider using interface. Since a class can have multiple
capabilities i.e. a class can be Runnable as well as Displayable at same time. As discussed in first point,
since java does not allow multiple inheritance at class level, only way to provide multiple capability is via
interfaces.
6) Let's see another example of where to use Abstract class and Interface in Java, which is related to
earlier point. Suppose you have lot of classes to model which are birds, which can fly, than creating a
base abstract class as Bird would be appropriate but if you have to model other things along with Birds,
which can fly e.g. Airplanes, Balloons or Kites than it's better to create interface Flyable to represent
flying functionality. In conclusion, if you need to provide a functionality which is used by same type of
class than use Abstract class and if functionality can be used by completely unrelated classes than use
interface.
7) Another interesting use of Abstract class and interface is defining contract using interface and
providing skeletal using abstract class. java.util.List from Java collection framework is a good example of
this pattern. List is declared as interface and extends Collection and Iterable interface and AbstractList is
an abstract class which implements List. AbstractList provides skeletal implementation of List interface.
Benefit of using this approach is that it minimize the effort to implement this interface by concrete class
e.g. ArrayList or LinkedList. If you don't use skeletal implementation e.g. abstract class and instead
decide to implement List interface than not only you need to implement all List methods but also you
might be duplicating common code. Abstract class in this case reduce effort to implement interface.
8) Interface also provide more decoupling than abstract class because interface doesn't contain any
implementation detail, while abstract class may contain default implementation which may couple them
with other class or resource.
9) Using interface also help while implementing Dependency Injection design pattern and makes testing
easy. Many mock testing framework utilize this behavior.
10). From Java 8 onwards, we can have method implementations in the interfaces. We can create
default as well as static methods in the interfaces and provide implementation for them. This has bridge
the gap between abstract classes and interfaces and now interfaces are the way to go because we can
extend it further by providing default implementations for new methods.
21
Now consider we are going to a showroom to buy a car. What do we see now? We see four wheels,
powerful engine, power steering etc. We see the car at high level components. But, there is so much
inside it which gives the completeness to the car.
Now consider a mechanic, who is going to service the car. He will see one more level deeper with more
level of information.
When we design software, we take the context. In the above example, we ask the question whether we
are designing the software for a causal on looker or a buyer or a mechanic? Levels of abstraction is
applied on the design accordingly.
As per dictionary, abstraction is the quality of dealing with ideas rather than events. For example, when
you consider the case of e-mail, complex details such as what happens as soon as you send an e-mail,
the protocol your e-mail server uses are hidden from the user. Therefore, to send an e-mail you just
need to type the content, mention the address of the receiver, and click send.
When we say abstraction in Java, we are talking about abstraction in object oriented programming
(OOP) and how it is done in Java. Concept of abstraction in OOP, starts right at the moment when a class
is getting conceived. I will not say, using Java access modifiers to restrict the properties of an object
alone is abstraction. There is lot more to it. Abstraction is applied everywhere in software and OOP.
Similarly, what are the behaviors we are going to have in the class? Abstraction is also applied here.
What is necessary to have here and what will be an overdose? Then we cut off some information from
the class. This process is applying abstraction.
22
When we ask for difference between encapsulation and abstraction, I would say, encapsulation uses
abstraction as a concept. So then, is it only encapsulation. No, abstraction is even a concept applied as
part of inheritance and polymorphism.
We got to look at abstraction at a level higher among the other OOP concepts encapsulation,
inheritance and polymorphism.
What are some common properties that can be exposed and elevated to a higher level, so that lower
level classes can inherit it. Some properties need not be kept at higher level. These decision making
process is nothing but applying abstraction to come up with different layers of hierarchy. So abstraction
is one key aspect in OOP as a concept.
Abstraction and encapsulation are complementary concepts: abstraction focuses on the observable
behavior of an object... encapsulation focuses upon the implementation that gives rise to this behavior...
encapsulation is most often achieved through information hiding, which is the process of hiding all of
the secrets of object that do not contribute to its essential characteristics.
In other words: abstraction = the object externally; encapsulation (achieved through information hiding)
= the object internally.
An abstract method in Java doesn't have the body, it's just a declaration. In order to use an abstract
method, you need to override that method in sub class.
23
12.7 So when do you use abstraction?
When you know something needs to be there but not sure how exactly it should look like. e.g. when I
am creating a class called Vehicle, I know there should be methods like start() and stop() but don't know
how that start and stop method should work, because every vehicle can have different start and stop
mechanism e.g. some can be started by kicking or some can be by pressing buttons . The Same concept
applies to interface in Java as well, which we will discuss in some other post.
So the implementation of those start() and stop() methods should be left to their concrete
implementation e.g. Scooter, MotorBike , Car etc.
In Java Interface is an another way of providing abstraction, Interfaces are by default abstract and only
contains public, static, final constant or abstract methods. It's very common interview question is that
where should we use abstract class and where should we use Java Interfaces in my view this is
important to understand to design better Java application, you can go for java interface if you only know
the name of methods your class should have e.g. for Server it should have start() and stop() method but
we don't know how exactly these start and stop method will work.
If you know some of the behavior while designing class and that would remain common across all
subclasses add that into an abstract class. An interface like Runnable interface is a good example of
abstraction in Java which is used to abstract task executed by multiple threads. Callable is another good
abstract of a task which can return value.
2) In Java, you cannot create an instance of the abstract class using the new operator, its compiler error.
Though abstract class can have a constructor.
3) Abstract is a keyword in Java, which can be used with both class and method. Abstract class can
contain both abstract and concrete method. An abstract method doesn't have the body, just
declaration.
4) A class automatically becomes abstract class when any of its methods declared as abstract.
6) In Java, a variable cannot be made abstract, its only class or methods which would be abstract.
7) If a class extends an abstract class or interface it has to provide implementation to all its abstract
method to be a concrete class. Alternatively, this class can also be abstract.
24
13. What is Encapsulation?
Encapsulation is the ability to package data, related behavior in an object bundle and control/restrict
access to them (both data and function) from other objects. It is all about packaging related stuff
together and hide them from external elements.
We can see that keywords encapsulation and data hiding are used synonymously everywhere. It should
not be misunderstood that encapsulation is all about data hiding only. When we say encapsulation,
emphasis should be on grouping or packaging or bundling related data and behavior together.
When we design a class in OOP, the first principle we should have in mind is encapsulation. Group the
related data and its behavior in a bucket. Primary benefit of encapsulation is, better maintainability.
That’s it! This is all about encapsulation. Let us leave it as simple as that. Nothing more and nothing less.
So data hiding is fairly straight forward. How about bundling data and method. This is critical. We should
understand well about the business domain and based on that design the class and group attributes and
its methods together. This process is key in encapsulation.
Following is an outline example for Java encapsulation. When we talk about an animal, we should have
all its attributes listed, similarly its behavior like how it will hunt, run, mate, etc. By bundling all these
data and behavior in a single class we are following encapsulation principles.
package com.javapapers.java;
return animalName;
}
}
Encapsulation in Java or object oriented programming language is a concept which enforces protecting
variables, functions from outside of class, in order to better manage that piece of code and having least
impact or no impact on other parts of a program due to change in protected code. Encapsulation in Java
is visible at different places and Java language itself provide many constructs to encapsulate members.
You can completely encapsulate a member be it a variable or method in Java by using private keyword
and you can even achieve a lesser degree of encapsulation in Java by using other access modifiers like
protected or the public.
Encapsulation is nothing but protecting anything which is prone to change. Rational behind
encapsulation is that if any functionality which is well encapsulated in code i.e. maintained in just one
place and not scattered around code is easy to change. this can be better explained with a simple
example of encapsulation in Java. we all know that constructor is used to creating object in Java and
constructor can accept an argument. Suppose we have a class Loan has a constructor and then in
various classes, you have created an instance of the loan by using this constructor. now requirements
change and you need to include the age of borrower as well while taking a loan.
Since this code is not well encapsulated i.e. not confined in one place you need to change everywhere
you are calling this constructor i.e. for one change you need to modify several file instead of just one file
which is more error prone and tedious, though it can be done with refactoring feature of advanced IDE
wouldn't it be better if you only need to make change at one place? Yes, that is possible if we
26
encapsulate Loan creation logic in one method say createLoan() and client code call this method and this
method internally create Loan object. in this case, you only need to modify this method instead of all
client code.
27
13.4 Design Pattern based on Encapsulation
Many design pattern in Java uses encapsulation concept, one of them is Factory pattern which is used to
create objects. Factory pattern is a better choice than new operator for creating an object of those
classes whose creation logic can vary and also for creating different implementation of the same
interface. BorderFactory class of JDK is a good example of encapsulation in Java which creates different
types of Border and encapsulate creation logic of Border. Singleton pattern in Java also encapsulate how
you create an instance by providing getInstance() method. since an object is created inside one class and
not from any other place in code you can easily change how you create an object without affect another
part of code.
1. Ad hoc Polymorphism
2. Parametric Polymorphism
Later these were further categorized as below:
28
14.1.1 Ad hoc Polymorphism
"Ad-hoc polymorphism is obtained when a function works, or appears to work, on several different
types (which may not exhibit a common structure) and may behave in unrelated ways for each type.
Parametric polymorphism is obtained when a function works uniformly on a range of types; these types
normally exhibit some common structure." – Strachey 1967
If we want to say the above paragraph in two words, they are operator overloading and function
overloading. Determining the operation of a function based on the arguments passed.
In Java we have function overloading and we do not have operator overloading. Yes we have “+”
operator implemented in a polymorphic way.
String fruits = "Apple" + "Orange";
int a = b + c;
The definition is when the type is different, the internal function adjusts itself accordingly. int and float
are different types and so even the following can be included in polymorphism operator overloading.
int i = 10 - 3;
float f = 10.5 - 3.5;
Similarly even * and / can be considered as overloaded for int and float types.
Having said all the above, these are all language implemented features. Developers cannot custom
overload an operator. So answer for the question, “does Java supports operator overloading?” is “yes
and no”.
29
Java wholeheartedly supports function overloading. We can have same function name with different
argument type list. For function overloading in Java I have already written a super-hit tutorial and I am
sure you will enjoy reading it.
In inheritance, the ability to replace an inherited method in the subclass by providing a different
implementation is overriding. Function overriding in is discussed in the same tutorial as overloading.
Polymorphism is a larger concept which consists of all these different types. So it is not right to say that
overloading or overriding alone is polymorphism. It is more than that.
Now with this definition, let us see if Java has coercion polymorphism. The answer is half yes. Java
supports widening type conversion and not narrowing conversions.
1. Narrowing Conversion:
class FToC {
public static float fToC (int fahrenheit) {
return (fahrenheit - 32)*5/9;
}
2. Widening Conversion:
class FToC {
public static float fToC (float fahrenheit) {
return (fahrenheit - 32)*5/9;
}
30
14.1.2 Universal Polymorphism
Universal polymorphism is the ability to handle types universally. There will be a common template
structure available for operations definition irrespective of the types. Universal polymorphism is
categorized into inclusion polymorphism and parametric polymorphism.
“Let T be a super type and S be its subtype (parent and child class). Then, instances (objects) of T can be
substituted with instances of S.”
Replacing the supertype’s instance with a subtype’s instance. This is called inclusion polymorphism or
subtype polymorphism. This is covariant type and the reverse of it is contravariant. We have discussed
the substitution principle and covariant types, contravariant and invariant earlier in the linked tutorial.
This is demonstrated with a code example. Java supports subtype polymorphism from Java / JDK version
1.5.
The following source code demonstrates a generics feature of Java. It gives the ability to define a class
and parameterize the type involved. The behavior of the class is based on the parameter type passed
when it is instantiated.
package com.javapapers.java;
import java.util.ArrayList;
import java.util.List;
Let us take overloading and overriding for example to understand static and dynamic binding. In the
below code, first call is dynamic binding. Whether to call the obey method of DomesticAnimal or Animal
is resolve at runtime and so it is dynamic binding. In the second call, whether the method obey() or
obey(String i) should be called is decided at compile time and so this is static binding.
package com.javapapers.java;
class Animal {
public String obey() {
return "No!";
}
32
class DomesticAnimal extends Animal {
public String obey() {
return "Yes!";
}
Yes!
Ok!
33
public String getDescription(){
return "Futures trading system";
}
}
Here we have a super class called TradingSystem and there two implementation
DirectMarketAccessSystem and CommodityTradingSystem and here we will write code which is flexible
enough to work with any future implementation of TradingSystem we can achieve this by using
Polymorphism in Java which we will see in the further example.
1. Method argument:
Always use super type in method argument that will give you leverage to pass any implementation while
invoking a method. For example:
public void showDescription(TradingSystem tradingSystem){
tradingSystem.description();
}
If you have used concrete implementation e.g. CommodityTradingSystem or DMATradingSystem then
that code will require frequent changes whenever you add new Trading system.
2. Variable names:
Always use Super type while you are storing reference returned from any Factory method in Java, This
gives you the flexibility to accommodate any new implementation from Factory. Here is an example of
polymorphism while writing Java code which you can use retrieving reference from Factory:
String systemName = Configuration.getSystemName();
TradingSystem system = TradingSystemFactory.getSystem(systemName);
34
done by dynamic binding in Java. Java supports both overloading and overriding of methods. In case of
overloading method signature changes while in case of overriding method signature remains same and
binding and invocation of method is decided on runtime based on actual object. This facility allows Java
programmer to write very flexibly and maintainable code using interfaces without worrying about
concrete implementation. One disadvantage of using Polymorphism in code is that while reading code
you don't know the actual type which annoys while you are looking to find bugs or trying to debug
program. But if you do Java debugging in IDE you will definitely be able to see the actual object and the
method call and variable associated with it.
Inheritance in Java is way to define relationship between two classes. Inheritance defines Parent and
Child relationship between two classes. Similar to real world where a Child inherit his parents Surname
and other qualities, In Java programming language, Child class inherit its Parent’s property and code. In
Java programming, terms Super class and Sub Class is used to represent Parent and Child class, while in
other object oriented language like C++, terms base and derived class is used to denote Inheritance.
Inheritance is also simplest but not optimal way to reuse code and When one class use Inheritance to
extend another class it get access to all non private code written in Super class. In Context of Inheritance
in Java, following are legal :
1) Super class reference variable can point to Sub Class Object e.g.
SuperClass parent = new SubClass();
is legal at compile time because of IS-A relationship between Super class and Sub Class. In Java Sub Class
IS-A Super class like Mango IS-A Fruit.
Similarly you can pass Sub class object in method arguments where Super class is expected, return Sub
Class instance where return type of method is Super Class etc.
On the other hand if an you want to store object of Sub class, which is stored in super class reference
variable, back on Sub class reference variable you need to use casting in Java, as shown below :
SubClass child = (SubClass) parent; //since parent variable pointing
to SubClass object
This code will throw ClassCastException if parent reference variable doesn't point to a SubClass object.
35
2. If you do not want to allow Inheritance for your class than you can make it final. final classes can not
be extended in Java and any attempt to inherit final class will result in compile time error.
3. Constructor in Java are not inherited by Sub Class. In face Constructors are chained, first statement in
constructor is always a call to another constructor, either implicitly or explicitly. If you don't call any
other constructor compiler will insert super(), which calls no argument constructor of super class in Java.
this keyword represent current instance of class and super keyword represent instance of super class in
Java.
4. Inheritance in Java represents IS-A relationship. If you see IS-A relationship between your domain
Objects and Classes than consider using Inheritance e.g. if you have a class called ProgrammingLanguage
than Java IS-A ProgrammingLanguage and should inherit from ProgrammingLanguage class.
5. Private members of Super class is not visible to Sub class even after using Inheritance in Java. Private
members include any private field or method in Java.
6. Java has a special access modifier known as protected which is meant to support Inheritance in Java.
Any protected member including protected method and field are only accessible in Child class or Sub
class outside the package on which they are declared.
7. One of the risk of Inheritance in Java is that derived class can alter behavior of base class by overriding
methods, which can compromise variants of base class e.g. if a malicious class overrides String's equals
method in Java to change the comparison logic, you may get different behavior when String reference
variable points to that class. to prevent such malicious overriding, you can make your class final to
disallow inheritance. But beware making a class final severely implements its client's ability to reuse
code. It make more sense from security perspective and that's one of the reason Why String is final in
Java.
8. Use @Override annotation while overriding super class's method in subclass. This will ensure a
compile time check on whether overriding method actually overrides super class method or not. Its
common mistake to overload a method instead of overriding it mostly when super class method accept
Object type, common examples are equals method, compareTo method and compare() method in Java.
36
15.3 How to use Inheritance
You can use Inheritance in Java by using two keywords, extends and implements. extends keyword is
used when one Class inherit from other Class or one interface extend another interface. On the other
hand implements keyword is used when a class implement an interface which is also a form of
Abstraction in Java. Interestingly, Inheritance facilitate Polymorphism in Java. By using Inheritance Sub
class gets all property of Super class, except private, and can represent Super class i.e. you can store sub
class instance in a Super class reference variable, which is a form of Polymorphism in Java. All flexibility
which is provided by interface based design is achieved using polymorphism. Common example of this
Factory design pattern in Java where return type of Factory method should be base interface, which
allows Factory method to return any implementation of base interface, which is actually created using
Inheritance in Java. In next section we will an example of Inheritance, which will show How to code for
inheritance. in Java
/**
*
* Java program to demonstrate Inheritance in Java programming
language.
* Inheritance is used to reuse code and Java programming language
allows you
* to either extend class or implements Interface. In this Program we
have a
* Super Class Server and a Sub Class Tomcat, which is a Server.
* Tomcat inherit start() and stop() method of Server Super Class.
*
* @author Javin
*/
public class Inheritance{
tomcat.stop();
}
37
}
class Server{
private long uptime;
@Override
public void start(){
super.start();
//Tomcat Server specific task
System.out.println("Tomcat Server started");
}
@Override
public void stop(){
super.stop(); //you can call super class method using super
keyword
System.out.println("Tomcat Server Stopped");
}
}
Output:
Tomcat Server started
Uptime of Server : 105898370823666
Tomcat Server Stopped
That’s all on What is Inheritance in Java, When to use Inheritance and How to use Inheritance in Java
programming language. If you are coming from C++ background than only surprise for you is that Java
does not support multiple Inheritance, other than that Java Inheritance is similar to Inheritance in any
other programming language e.g. C++. in Java
38
overloading method, the signature must be different. Last but not the least difference between them is
that call to overloaded methods are resolved using static binding while the call to overridden method is
resolved using dynamic binding in Java.
By the way, Method overloading and method overriding in Java is two important concept in Java which
allows Java programmer to declare method with same name but different behavior. Method
overloading and method overriding is based on Polymorphism in Java.
In case of method overloading, method with same name co-exists in same class but they must have
different method signature, while in case of method overriding, method with same name is declared in
derived class or sub class. Method overloading is resolved using static binding in Java at compile time
while method overriding is resolved using dynamic binding in Java at runtime.
In short, when you overload a method in Java its method signature got changed while in case of
overriding method signature remains same but a method can only be overridden in sub class. Since Java
supports Polymorphism and resolve object at run-time it is capable to call overridden method in Java.
39
16.3 Difference between Method Overloading vs overriding
1) First and most important difference between method overloading and overriding is that, In case of
method overloading in Java, signature of method changes while in case of method overriding it remain
same.
2) Second major difference between method overloading vs overriding in Java is that you can overload
method in one class but overriding can only be done on subclass.
3) You cannot override static, final and private method in Java but you can overload static, final or
private method in Java.
4) Overloaded method in Java is bonded by static binding and overridden methods are subject to
dynamic binding.
You can see that Beta class which is overriding doStuff() method from Alpha class is returning Beta type
and not Alpha type. This will remove type casting on client side.
40
17. Java Collection
41
18. Java Collection Flow
42
19. Java Collection heat Sheet
43
20. Collection Big O Cheat Sheet
Coming to the internal working of the HashMap, which is also a favourite Java Collections interview
question, there are four things we should know about before going into the internals of how does
HashMap work in Java - in Java:
44
1 HashMap works on the principal of hashing.
2 Map.Entry interface - This interface gives a map entry (key-value pair). HashMap in Java
stores both key and value object, in bucket, as an object of Entry class which implements this
nested interface Map.Entry.
3 hashCode() -HashMap provides put(key, value) for storing and get(key) method for retrieving
Values from HashMap. When put() method is used to store (Key, Value) pair, HashMap
implementation calls hashcode on Key object to calculate a hash that is used to find a bucket
where Entry object will be stored. When get() method is used to retrieve value, again key object is
used to calculate a hash which is used then to find a bucket where that particular key is stored.
4 equals() - equals() method is used to compare objects for equality. In case of HashMap key
object is used for comparison, also using equals() method Map knows how to handle hashing
collision (hashing collision means more than one key having the same hash value, thus assigned to
the same bucket. In that case objects are stored in a linked list, refer figure for more clarity.
Where hashCode method helps in finding the bucket where that key is stored, equals method helps in
finding the right key as there may be more than one key-value pair stored in a single bucket.
** Bucket term used here is actually an index of array, that array is called table in HashMap
implementation. Thus table[0] is referred as bucket0, table[1] as bucket1 and so on.
45
@Override
// A very bad implementation of hashcode
// done here for illustrative purpose only
public int hashCode(){
return 5;
}
@Override
// A very bad implementation of equals
// done here for illustrative purpose only
public boolean equals(Object obj){
return true;
}
}
Output
Notice that I am inserting 4 values in the HashMap, still in the output it says size is 1 and iterating the
map gives me the last inserted entry. Why is that?
Answer lies in, how hashCode() and equals() method are implemented for the key Class. Have a look at
the hashCode() method of the class Key which always returns "5" and the equals() method which is
always returning "true".
When a value is put into HashMap it calculates a hash using key object and for that it uses the
hashCode() method of the key object class (or its parent class). Based on the calculated hash value
HashMap implementation decides which bucket should store the particular Entry object.
In my code the hashCode() method of the key class always returns "5". This effectively means calculated
hash value, is same for all the entries inserted in the HashMap. Thus all the entries are stored in the
same bucket.
Second thing, a HashMap implementation does is to use equals() method to see if the key is equal to any
of the already inserted keys (Recall that there may be more than one entry in the same bucket). Note
that, with in a bucket key-value pair entries (Entry objects) are stored in a linked-list (Refer figure for
more clarity). In case hash is same, but equals() returns false (which essentially means more than one
key having the same hash or hash collision) Entry objects are stored, with in the same bucket, in a
linked-list.
In my code, I am always returning true for equals() method so the HashMap implementation "thinks"
that the keys are equal and overwrites the value. So, in a way using hashCode() and equals() I have
"tricked" HashMap implementation to think that all the keys (even though different) are same, thus
overwriting the values.
46
Using hashCode() method, hash value will be calculated. Using that hash it will be ascertained, in
which bucket particular entry will be stored.
equals() method is used to find if such a key already exists in that bucket, if no then a new node
is created with the map entry and stored within the same bucket. A linked-list is used to store
those nodes.
If equals() method returns true, which means that the key already exists in the bucket. In that
case, the new value will overwrite the old value for the matched key.
Pictorial representation of how Entry (key-value pair) objects will be stored in table array
Using the key again hash value will be calculated to determine the bucket where that Entry object is
stored, in case there are more than one Entry object with in the same bucket stored as a linked-list
equals() method will be used to find out the correct key. As soon as the matching key is found get()
method will return the value object stored in the Entry object.
47
But the performance may worsen in the case hashCode() used is not proper and there are lots of hash
collisions. As we know now that in case of hash collision entry objects are stored as a node in a linked-
list and equals() method is used to compare keys. That comparison to find the correct key with in a
linked-list is a linear operation so in a worst case scenario the complexity becomes O(n).
To address this issue in Java 8 hash elements use balanced trees instead of linked lists after a certain
threshold is reached. Which means HashMap starts with storing Entry objects in linked list but after the
number of items in a hash becomes larger than a certain threshold, the hash will change from using a
linked list to a balanced tree, this will improve the worst case performance from O(n) to O(log n).
Points to note -
The default implementation of equals() method in the Object class is a simple reference equality check -
public boolean equals(Object obj){
return (this == obj);
}
The default implementation of hashCode() in the Object class just returns integer value of the memory
address of the object.
hashCode() - This method is used to get a unique integer value for a given object. We can see it's use
with hash based collections like HashTable or HashMap where hashCode() is used to find the correct
bucket location where the particular (key, value) pair is stored. Refer to How HashMap internally works
48
in Java to know more about it. equals() - equals() method is used to determine the equality of two
objects.
In such cases we can't rely on the default implementation provided by the Object class and need to
provide custom implementation of hashCode() and equals() method.
Most of the time we use HashMap when it comes to hash based collections. Within HashMap as key, we
mostly use primitive wrapper class like Integer or String class. These classes are immutable and provide
their own proper implementation of hashCode() and equals(), thus these classes, on their own are, good
hash keys.
At least I never had the need to implement these methods before I started using Hibernate. Things
become tricky when we are using any custom object as key, in that case it becomes very important to
override these 2 methods to make sure that we really get the object we want.
Let's say you are using some custom class object for a key in HashMap and that class did not override
equals() and hashCode(), what will happen in that case?
In that case we would not be able to reliably retrieve the associated value using that key, unless we used
the exact same class instance as key in the get() call as we did in the put() call. Why using the same
instance it is possible? Because in the case we are not providing the implementation of equals() and
hashCode(), Object class' equals() and hashCode() method will be used and recall that in Object class
equals() method implementation is simple reference equality check thus having the same instance may
satisfy the Object class' equals() method.
Let's see an example where custom object is used but hashCode and equals are not overridden and
custom implementation is not given.
class Customer {
private int customerID;
private String firstName;
private String lastName;
}
public class HashCodeDemo {
49
public static void main(String[] args) {
Map<Customer, String> m = new HashMap<Customer, String>();
Customer cust = new Customer(1, "Roger", "Cox");
m.put(cust,"Roger Cox");
// retrieving using another instance
System.out.println(m.get(new Customer(1, "Roger", "Cox")));
// retrieving using same instance
System.out.println(m.get(cust));
}
}
Output
null
Roger Cox
It can be seen how; when the instance is changed the value is not retrieved even when the same values
for the customer object are given as key. But when we use the same instance then it is able to fetch. But
that's not very convenient and in a big application we are not expected to keep the same instance and
use it whenever we want to retrieve the value. So enter the equals() and hashCode() methods.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + customerID;
result = prime * result
+ ((firstName == null) ? 0 :
firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
50
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (customerID != other.customerID)
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
}
public class HashCodeDemo {
Roger Cox
Roger Cox
1. It is reflexive: for any non-null reference value x, x.equals(x) should return true.
2. It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and
only if y.equals(x) returns true.
3. It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and
y.equals(z) returns true, then x.equals(z) should return true.
4. It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y)
consistently return true or consistently return false, provided no information used in equals
comparisons on the objects is modified.
51
5. For any non-null reference value x, x.equals(null) should return false.
1. Whenever it is invoked on the same object more than once during an execution of a Java
application, the hashCode method must consistently return the same integer, provided no
information used in equals comparisons on the object is modified. This integer need not remain
consistent from one execution of an application to another execution of the same application.
2. If two objects are equal according to the equals(Object) method, then calling the hashCode
method on each of the two objects must produce the same integer result.
3. It is not required that if two objects are unequal according to the equals(java.lang.Object)
method, then calling the hashCode method on each of the two objects must produce distinct
integer results. However, the programmer should be aware that producing distinct integer
results for unequal objects may improve the performance of hash tables.
The first point says that the hashCode() method must consistently return the same integer. In
case a mutable object is used as key we have to make sure that its state does not change. If a
key's hashCode changes while used in a Collection get and put will give some unpredictable
results.
According to the second point if 2 objects Obj1 and Obj2 are equal according to their equals()
method then they must have the same hash code too. Though the vice-versa is not true that is if
2 objects have the same hash code then they do not have to be equal too.
According to the third point if 2 objects are not equal according to their equals() method they
still can have the same hash code. That is known as hash collision.
Also you may have guessed by now, since hash function is calculated using value that is why only unique
values are stored in the HashSet. If you try to store the same element again, the calculated hash
function would be same, thus the element will be overwritten.
Now coming back to internal working of HashSet, which is also an important Java Collections interview
question, the most important point is HashSet internally uses HashMap to store it's objects. Within the
HashSet there are many constructors one without any parameter and several more with initial capacity
or load factor but every one of these constructor creates a HashMap. If you know how HashMap works
internally in Java it is easy to understand how HashSet works internally.
52
HashSet Constructor examples
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance
has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
And the map, which is used for storing values, is defined as
private transient HashMap<E,Object> map;
In the constructor, if you have noticed, there are parameters named initial capacity and load factor. For
HashSet, default initial capacity is 16, that is an array (or bucket) of length 16 would be created and
default load factor is 0.75. Where load factor is a measure of how full the hash table is allowed to get
before its capacity is automatically increased.
Actually in HashSet, from add method, put method of HashMap is called where the value which has to
be added in the Set becomes Key and a constant object "PRESENT" is used as value.
53
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
Here note that remove(Object key) method of the HashMap returns the Value associated with the key.
Whereas the remove(Object o) method of the HashSet returns Boolean value. Also we know that for
every value added in HashSet that value becomes Key and the value is always an object called PRESENT.
Therefore the value that is returned from the remove(Object key) method of the HashMap is always
PRESENT thus the condition map.remove(o)==PRESENT.
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
54
System.out.println("-----------------------------------------------
-");
System.out.println("Iterating or looping map using java5 foreach
loop");
System.out.println("key: " + key + " value: " + loans.get(key));
}
Output:
------------------------------------------------
Iterating or looping map using java5 foreach looop
key: home loan value: citibank
------------------------------------------------
Iterating or looping map using java5 foreach looop
key: personal loan value: Wells Fargo
Output:
------------------------------------------------
Iterating Map in Java using KeySet Iterator
key: home loan value: citibank
------------------------------------------------
Iterating Map in Java using KeySet Iterator
key: personal loan value: Wells Fargo
24.3 Looping HashMap in Java using EntrySet and Java 5 for loop
In this Example of traversing Map in Java, we have used EntrySet instead of KeySet. EntrySet is a
collection of all Map Entries and contains both Key and Value.
Set<Map.Entry<String, String>> entrySet = loans.entrySet();
for (Entry entry : entrySet) {
System.out.println("-----------------------------------------------
-");
System.out.println("looping HashMap in Java using EntrySet and
java5 for loop");
System.out.println("key: " + entry.getKey() + " value: " +
entry.getValue());
}
55
Output:
------------------------------------------------
looping HashMap in Java using EntrySet and java5 for loop
key: home loan value: citibank
------------------------------------------------
looping HashMap in Java using EntrySet and java5 for loop
key: personal loan value: Wells Fargo
Output:
------------------------------------------------
Iterating HashMap in Java using EntrySet and Java iterator
key: home loan value: citibank
------------------------------------------------
Iterating HashMap in Java using EntrySet and Java iterator
key: personal loan value: Wells Fargo
56
crunchifyCompanyList.add("Facebook");
crunchifyCompanyList.add("Twitter");
CrunchifyStandardForEachMethod4List(crunchifyCompanyList);
// Method4,5: Java8 Method to iterate through Java List
CrunchifyJava8ForEachMethod4List(crunchifyCompanyList);
}
private static void CrunchifyStandardForEachMethod4Map(
Map<String, String> crunchifyCompanyMap) {
for (Map.Entry<String, String> crunchifyEntry :
crunchifyCompanyMap.entrySet()) {
log("crunchifyCompany: " + crunchifyEntry.getKey()
+ ", address: "
+ crunchifyEntry.getValue());
}
}
private static void CrunchifyJava8ForEachMethod4Map(Map<String,
String> crunchifyCompanyMap) {
crunchifyCompanyMap.forEach((k, v) ->
log("crunchifyCompany: " + k + ", address: " + v));
}
private static void
CrunchifyStandardForEachMethod4List(List<String> crunchifyList) {
for (String item : crunchifyList) {
log(item);
}
}
}
// Simple log utility
private static void log(String string) {
System.out.println(string);
}
}
57
Use the second option if you need to ensure data consistency, and each thread needs to have an up-to-
date view of the map. Use the first if performance is critical, and each thread only inserts data to the
map, with reads happening less frequently.
Though all three collection classes are thread-safe and can be used in multi-threaded, concurrent Java
application, there is a significant difference between them, which arise from the fact that how they
achieve their thread-safety. Hashtable is a legacy class from JDK 1.1 itself, which uses synchronized
methods to achieve thread-safety. All methods of Hashtable are synchronized which makes them quite
slow due to contention if a number of thread increases. Synchronized Map is also not very different than
Hashtable and provides similar performance in concurrent Java programs. The only difference between
Hashtable and Synchronized Map is that later is not a legacy and you can wrap any Map to create it's
synchronized version by using Collections.synchronizedMap() method.
On the other hand, ConcurrentHashMap is specially designed for concurrent use i.e. more than one
thread. By default it simultaneously allows 16 threads to read and write from Map without any external
synchronization. It is also very scalable because of stripped locking technique used in the internal
implementation of ConcurrentHashMap class. Unlike Hashtable and Synchronized Map, it never locks
whole Map, instead, it divides the map into segments and locking is done on those. Though it performs
better if a number of reader threads are greater than the number of writer threads.
To be frank, Collections classes are the heart of Java API though I feel using them judiciously is an art. It's
my personal experience where I have improved the performance of Java application by using ArrayList
where legacy codes were unnecessarily using Vector etc. Prior Java 5, One of the major drawback of Java
Collection framework was a lack of scalability.
In multi-threaded Java application synchronized collection classes like Hashtable and Vector quickly
becomes the bottleneck; to address scalability JDK 1.5 introduces some good concurrent collections
which are highly efficient for high volume, low latency system electronic trading systems In general
those are the backbone for Concurrent fast access to stored data.
In this tutorial, we will look on ConcurrentHashMap, Hashtable, HashMap and synchronized Map and
see the difference between ConcurrentHashMap and Hashtable and synchronized Map in Java. We have
already discussed some key difference between HashMap and Hashtable in Java in this blog and those
will also help you to answer this question during interviews.
58
25.2 Difference between ConcurrentHashMap and Hashtable
So what is the difference between Hashtable and ConcurrentHashMap, both can be used in the
multithreaded environment but once the size of Hashtable becomes considerable large performance
degrade because for iteration it has to be locked for a longer duration.
Since ConcurrentHashMap introduced the concept of segmentation, how large it becomes only certain
part of it get locked to provide thread safety so many other readers can still access map without waiting
for iteration to complete.
In Summary, ConcurrentHashMap only locked certain portion of Map while Hashtable locks full map
while doing iteration. This will be clearer by looking at this diagram which explains the internal working
of ConcurrentHashMap in Java.
ConcurrentHashMap does not allow null keys or null values while synchronized HashMap allows one null
key.
59
3. In ConcurrentHashMap synchronization is done a little differently. Rather than locking every
method on a common lock, ConcurrentHashMap uses separate lock for separate buckets thus
locking only a portion of the Map.
4. By default there are 16 buckets and also separate locks for separate buckets. So the default
concurrency level is 16. That means theoretically any given time 16 threads can access
ConcurrentHashMap if they all are going to separate buckets.
5. In ConcurrentHashMap performance is further improved by providing read access concurrently
without any blocking. Retrieval operations (including get) generally do not block, so may overlap
with update operations (including put and remove).
6. HashMap allows one null as key but ConcurrentHashMap doesn't allow null as key.
7. Performace wise HashMap is better as there is no synchronization.
8. In case HashMap has to be used in a multi-threaded environment and there is a need to use
Collections.SynchronizedMap() method then ConcurrentHashMap() is a better choice as
ConcurrentHashMap still gives a chance to more than one thread to access map thus improving
performance.
9. Iterator provided by ConcurrentHashMap is fail-safe which means it will not throw
ConcurrentModificationException if the underlying structure is changed during iteration.
10. Iterator provided by HashMap is fail-fast as it throws a ConcurrentModificationException if the
underlying collection is structurally modified at any time after the iterator is created.
60
26.1 Why another Map
First thing that comes to mind is why another map when we already have HashMap or HashTable (if
thread safe data structure is required). The answer is better performance though still providing a thread
safe alternative. So it can be said that ConcurrentHashMap is a hash map whose operations are
threadsafe.
61
26.2 How performance is improved
As I said ConcurrentHashMap is also a hash based map like HashMap, how it differs is the locking
strategy used by ConcurrentHashMap. Unlike HashTable (or synchronized HashMap) it doesn't
synchronize every method on a common lock. ConcurrentHashMap uses separate lock for separate
buckets thus locking only a portion of the Map. Just for information ConcurrentHashMap uses
ReentrantLock for locking
If you have idea about the internal implementation of the HashMap you must be knowing that by
default there are 16 buckets. Same concept is used in ConcurrentHashMap and by default there are 16
buckets and also separate locks for separate buckets. So the default concurrency level is 16.
ConcurrentHashMap() Creates a new, empty map with a default initial capacity (16), load factor (0.75)
and concurrencyLevel (16).There are several other constructors, one of them is
ConcurrentHashMap(int initialCapacity, float loadFactor, int
concurrencyLevel)
Creates a new, empty map with the specified initial capacity, load factor and concurrency level. So you
can see that you can provide your own initial capacity (default is 16), own load factor and also
concurrency level (Which by default is 16).
Since there are 16 buckets having separate locks of their own which effectively means at any given time
16 threads can operate on the map concurrently provided all these threads are operating on separate
buckets.
So you see how ConcurrentHashMap provides better performance by locking only the portion of the
map rather than blocking the whole map resulting in greater shared access.
That is not all, performance is further improved by providing read access concurrently without any
blocking. Retrieval operations (including get) generally do not block, so may overlap with update
operations (including put and remove). Retrievals reflect the results of the most recently completed
update operations which may mean that retrieval operations may not fetch the current/in-progress
value (Which is one drawback). Memory visibility for the read operations is ensured by volatile reads.
You can see in the ConcurrentHashMap code that the val and next fields of Node are volatile.
Also for aggregate operations such as putAll and clear which works on the whole map, concurrent
retrievals may reflect insertion or removal of only some entries (another drawback of separate locking).
Because read operations are not blocking but some of the writes (which are on the same bucket) may
still be blocking.
62
// Storing elements
cityTemperatureMap.put("Delhi", "24");
cityTemperatureMap.put("Mumbai", "32");
//cityTemperatureMap.put(null, "26");
cityTemperatureMap.put("Chennai", "35");
cityTemperatureMap.put("Bangalore", "22" );
Suppose you have a word Map that counts the frequency of every word where key is the word and
count is the value, in a multi-threaded environment, even if ConcurrentHashMap is used, there may be a
problem as described in the code snippet.
public class CHMAtomicDemo {
63
}
To avoid these kind of problems you can use atomic method, one of the atomic method is compute
which can be used here.
wordMap.compute(word, (k,v)-> v == null ? 1 : v + 1);
If you see the general structure of the Compute method
compute(K key, BiFunction<? super K,? super V,? extendsV>
remappingFunction) Here BiFunction functional interface is used which can be implemented as a lambda
expression.
There are several other atomic operations like computeIfAbsent, computeIfPresent, merge, putIfAbsent.
Example code
public class CHMDemo {
// Storing elements
cityTemperatureMap.put("Delhi", "24");
cityTemperatureMap.put("Mumbai", "32");
cityTemperatureMap.put("Chennai", "35");
cityTemperatureMap.put("Bangalore", "22" );
Iterator<String> iterator =
cityTemperatureMap.keySet().iterator();
while (iterator.hasNext()){
System.out.println(cityTemperatureMap.get(iterator.next()));
// adding new value, it won't throw error
cityTemperatureMap.put("Kolkata", "34");
}
}
64
}
Output
24
35
34
32
22
According to the JavaDocs - The view's iterator is a "weakly consistent" iterator that will never throw
ConcurrentModificationException, and guarantees to traverse elements as they existed upon
construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to
construction.
65
27.1 What is ClassLoader
ClassLoader in Java is a class which is used to load class files in Java. Java code is compiled into class file
by javac compiler and JVM executes Java program, by executing byte codes written in class file.
ClassLoader is responsible for loading class files from file system, network or any other source. There are
three default class loader used in Java, Bootstrap , Extension and System or Application class loader.
Every class loader has a predefined location, from where they loads class files. Bootstrap ClassLoader is
responsible for loading standard JDK class files from rt.jar and it is parent of all class loaders in Java.
Bootstrap class loader don't have any parents, if you call String.class.getClassLoader() it will return null
and any code based on that may throw NullPointerException in Java. Bootstrap class loader is also
known as Primordial ClassLoader in Java.
Extension ClassLoader delegates class loading request to its parent, Bootstrap and if unsuccessful, loads
class form jre/lib/ext directory or any other directory pointed by java.ext.dirs system property.
Extension ClassLoader in JVM is implemented by sun.misc.Launcher$ExtClassLoader.
Third default class loader used by JVM to load Java classes is called System or Application class loader
and it is responsible for loading application specific classes from CLASSPATH environment variable, -
classpath or -cp command line option, Class-Path attribute of Manifest file inside JAR. Application class
loader is a child of Extension ClassLoader and its implemented by sun.misc.Launcher$AppClassLoader
class. Also, except Bootstrap class loader, which is implemented in native language mostly in C, all Java
class loaders are implemented using java.lang.ClassLoader.
In short here is the location from which Bootstrap, Extension and Application ClassLoader load Class
files.
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Java program to demonstrate How ClassLoader works in Java,
* in particular about visibility principle of ClassLoader.
*
* @author Javin Paul
*/
67
public static void main(String args[]) {
try {
//printing ClassLoader of this class
System.out.println("ClassLoaderTest.getClass().getClassLoader() : "
+
ClassLoaderTest.class.getClassLoader());
Logger.getLogger(ClassLoaderTest.class.getName()).log(Level.SEVERE,
null, ex);
}
}
Output:
ClassLoaderTest.getClass().getClassLoader() :
sun.misc.Launcher$AppClassLoader@601bb1
16/08/2012 2:43:48 AM test.ClassLoaderTest main
SEVERE: null
java.lang.ClassNotFoundException: test.ClassLoaderTest
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at
sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at test.ClassLoaderTest.main(ClassLoaderTest.java:29)
68
program to Connect Oracle database. As shown in above example you can pass name of ClassLoader
which should be used to load that particular class along with binary name of class. Class is loaded by
calling loadClass() method of java.lang.ClassLoader class which calls findClass() method to locate
bytecodes for corresponding class. In this example Extension ClassLoader uses java.net.URLClassLoader
which search for class files and resources in JAR and directories. any search path which is ended using
"/" is considered directory. If findClass() does not found the class than it throws
java.lang.ClassNotFoundException and if it finds it calls defineClass() to convert bytecodes into a .class
instance which is returned to the caller.
1) An Instance of class is created using either new() keyword or using reflection using class.forName(),
which may throw ClassNotFoundException in Java.
69
5) if Class is a top level class and an assert statement lexically nested within class is executed.
Reflection can also cause initialization of class. Some methods of java.lang.reflect package may cause
class to be initialized. JLS Strictly says that a class should not be initialized by any reason other than
above.
1) Classes are initialized from top to bottom so field declared on top initialized before field declared in
bottom
3) If Class initialization is triggered due to access of static field, only Class which has declared static field
is initialized and it doesn't trigger initialization of super class or sub class even if static field is referenced
by Type of Sub Class, Sub Interface or by implementation class of interface.
5) static fields are initialized during static initialization of class while non static fields are initialized when
instance of class is created. It means static fields are initialized before non static fields in Java.
6)non static fields are initialized by constructors in Java. sub class constructor implicitly call super class
constructor before doing any initialization, which guarantees that non static or instance variables of
super class is initialized before sub class.
70
}
}
/**
* Super class to demonstrate that Super class is loaded and
initialized before Subclass.
*/
class Parent {
static { System.out.println("static block of Super class is
initialized"); }
{System.out.println("non static blocks in super class is
initialized");}
}
/**
* Java class which is not used in this program, consequently not
loaded by JVM
*/
class NotUsed {
static { System.out.println("NotUsed Class is initialized "); }
}
/**
* Sub class of Parent, demonstrate when exactly sub class loading and
initialization occurs.
*/
class Child extends Parent {
static { System.out.println("static block of Sub class is
initialized in Java "); }
{System.out.println("non static blocks in sub class is
initialized");}
}
Output:
static block of Super class is initialized
static block of Sub class is initialized in Java
non static blocks in super class is initialized
non static blocks in sub class is initialized
false
28.5 Observation
1) Super class is initialized before sub class in Java.
2) Static variables or blocks are initialized before non static blocks or fields.
3) Not used class is not initialized at all because its not been used, none of the cases mentioned on JLS or
above which triggers initialization of class is not happened here.
71
*/
class Parent {
//compile time constant, accessing this will not trigger class
initialization
//protected static final String familyName = "Lawson";
Output:
static block of Super class is initialized
Lawson
Observation
1. Here class initialization occurs because static field is accessed which is not a compile time constant.
had you declare "familyName" compile time constant using final keyword in Java (as shown in
commented section) class initialization of super class would not have occurred.
2) Only super class is initialized even though static field is referenced using sub type.
There is another example of class initialization related to interface on JLS which explains clearly that
initialization of sub interfaces does not trigger initialization of super interface. I highly recommend
reading JLS 14.4 for understating class loading and initialization in more detail.
72
So in this post I'll try to explain the difference between comparable and comparator interfaces and why
both of them are required. Before going into the differences between these two, let's have a brief
introduction of both.
General form of Comparator interface - Note the annotation @FunctionalInterface, it's available from
Java 8 and Comparator being a functional interface can be implemented using lambda expression. Also
note that apart from compare method which is the single abstract method there are several other
default and static methods too with in the Comparator interface.
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Let's say we have an Employee class. Objects of this Employee class are stored in an array list and we
want to sort it first on first name and then on last name. So this order is the natural order for the
Employee class, employees are first sorted on first name and then last name.
Employee class
public class Employee implements Comparable<Employee> {
private String lastName;
private String firstName;
private String empId;
private int age;
73
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
System.out.println("Sorted List");
for(Employee emp : empList){
System.out.println("" + emp);
}
}
// Stub method
private static Employee getData(String empId, String lastName,
String firstName, int age){
Employee employee = new Employee();
employee.setEmpId(empId);
employee.setLastName(lastName);
employee.setFirstName(firstName);
employee.setAge(age);
return employee;
}
}
Output
Original List
Pyaremohan Mishra 35 E001
John Smith 45 E002
Ram Sharma 23 E003
Pyaremohan Mishra 60 E004
Eva Caroll 32 E005
Ram Tiwari 23 E003
Sorted List
Eva Caroll 32 E005
John Smith 45 E002
Pyaremohan Mishra 35 E001
Pyaremohan Mishra 60 E004
Ram Sharma 23 E003
Ram Tiwari 23 E003
Sorting logic
75
public class SortObjectList {
public static void main(String[] args) {
List<Employee> empList = new ArrayList<Employee>();
// Storing elements in the arraylist
empList.add(getData("E001", "Mishra", "Pyaremohan", 35));
empList.add(getData("E002", "Smith", "John", 45));
empList.add(getData("E003", "Sharma", "Ram", 23));
empList.add(getData("E004", "Mishra", "Pyaremohan", 60));
empList.add(getData("E005", "Caroll", "Eva", 32));
empList.add(getData("E003", "Tiwari", "Ram", 23));
System.out.println("Original List");
for(Employee emp : empList){
System.out.println("" + emp);
}
// Sorting the list
Collections.sort(empList, new MyComparator());
System.out.println("Sorted List");
for(Employee emp : empList){
System.out.println("" + emp);
}
}
// Stub method
private static Employee getData(String empId, String lastName,
String firstName, int age){
Employee employee = new Employee();
employee.setEmpId(empId);
employee.setLastName(lastName);
employee.setFirstName(firstName);
employee.setAge(age);
return employee;
}
}else{
return firstCmp;
}
76
}
}
Output
Original List
Pyaremohan Mishra 35 E001
John Smith 45 E002
Ram Sharma 23 E003
Pyaremohan Mishra 60 E004
Eva Caroll 32 E005
Ram Tiwari 23 E003
Sorted List
Eva Caroll 32 E005
John Smith 45 E002
Pyaremohan Mishra 60 E004
Pyaremohan Mishra 35 E001
Ram Sharma 23 E003
Ram Tiwari 23 E003
Here it can be seen that the name which is same is sorted by age in descending order.
Note here that a Comparator class MyComparator is implementing the Comparator interface and
providing implementation for the compare() method. Also note that in Collections.sort method now we
need to provide the Comparator class.
Collections.sort(empList, new MyComparator());
Comparator class can also be implemented as an Anonymous class or as a Lambda expression.
Comparable Comparator
Comparable interface is
Comparator interface is in java.util package.
in java.lang package.
The class which has to be sorted should Some other class can implement the Comparator interface
implement the comparable interface not the actual class whose objects are to be sorted. That
(sorting logic is in the class which has to way there may be many comparators and depending on
77
Comparable Comparator
be sorted), and that implementation the ordering needed specific comparator can be used. As
becomes the natural ordering of the example for Employee class if different orderings are
class. needed based on first name, last name, age etc. then we
can have different comparators with the implementations
for those orderings.
2) Some time you write code to sort object of a class for which you are not the original author, or you
don't have access to code. In these cases you can not implement Comparable and Comparator is only
way to sort those objects.
3) Beware with the fact that How those object will behave if stored in SorteSet or SortedMap like
TreeSet and TreeMap. If an object doesn't implement Comparable than while putting them into
SortedMap, always provided corresponding Comparator which can provide sorting logic.
4) Order of comparison is very important while implementing Comparable or Comparator interface. for
example if you are sorting object based upon name than you can compare first name or last name on
any order, so decide it judiciously. I have shared more detailed tips on compareTo on my post how to
implement CompareTo in Java.
78
5) Comparator has a distinct advantage of being self descriptive for example if you are writing
Comparator to compare two Employees based upon there salary than name that comparator as
SalaryComparator, on the other hand compareTo().
30.1 final
final keyword is used to restrict in some way. It can be used with variables, methods and classes. When
a variable is declared as final, its value can not be changed once it is initialized. Except in case of blank
final variable, which must be initialized in the constructor. If you make a method final in Java, that
method can’t be overridden in a sub class.If a class is declared as final then it can not be sub classed.
final keyword in java has its usage in preventing the user from modifying a field, method or class.
1. final field - A variable declared as final prevents the content of that variable being modified.
2. final method - A method declared as final prevents the user from overriding that method.
3. final class - A class declared as final can not be extended thus prevents inheritance.
Please note that the final variable that has not been assigned a value while declaring a variable is called
blank final variable, in that case it forces the constructor to initialize it.
79
Also if any field is final it is ensured by the JVM that other threads can't access the partially constructed
object, thus making sure that final fields always have correct values when the object is available to other
threads.
Where as in case of final methods since compiler knows these methods can not be overridden, call to
these methods can be resolved at compile time. This is known as early binding. Because of this early
binding compiler can inline the methods declared as final thus avoiding the overhead of method call.
If creator of the class is sure that the class has all the required functionality and should be used as it is
with out extending it then it should be declared as final.
Declaring a class as final implicitly means that all the methods of the class are final too as the class can't
be extended.
It is illegal to declare a class as both final and abstract. Since abstract class by design relies on subclass to
provide complete implementation.
Restricting extensibility may also be required in some cases essentially when using third party tools.
80
final variables are essentially read only and it is a common convention to write the final
variables in all caps. As exp. Private final int MAXIMUM_VALUE = 10
final variables that are not initialized during declaration are called blank final variable in that
case it forces the constructor to initialize it. Failure to do so will result in compile time error.
final variables can be initialized only once, assigning any value there after will result in compile
time error.
final variables are read-only thus thread safe.
In case of Final object reference can't be changed.
final methods can't be overridden
final classes can't be extended.
final methods are bound during compile time (early binding), which means compiler may inline
those methods resulting in performance optimization.
30.2 finally
finally is part of exception handling mechanism in Java. finally block is used with try-catch block. Along
with a try block we can have both catch and finally blocks or any one of them. So we can have any of
these combinations try-catch-finally, try-catch, try-finally. finally block is always executed whether any
exception is thrown or not and raised exception is handled in catch block or not. Since finally block
always executes thus it is primarily used to close the opened resources like database connection, file
handles etc.
From Java 7 onwards try with resources provide another way to automatically manage resources.
When an exception occurs in the code, the flow of the execution may change or even end abruptly. That
may cause problem if some resources were opened in the method.
As exp if a file was opened in a method and it was not closed in the end as some exception occurred
then the resources may remain open consuming memory. finally provides that exception-handling
mechanism to clean up.
Code with in the finally block will be executed after a try/catch block has completed. The finally block
will be executed whether or not an exception is thrown.
If the code with in try block executes without throwing any exception, the finally block is executed
immediately after the completion of try block. If an exception is thrown with in the try block, the finally
block is executed immediately after executing the catch block which handled the thrown exception.
81
try{
System.out.println("In try block");
return 1;
}finally{
System.out.println("In finally block");
return 2;
}
}
}
Output
In try block
In finally block
Value of i 2
It can be seen though try block has a return value still finally is executed. Ultimately return value is what
finally retruns.
Even if the exception is thrown still return value will be what finally returns. Let's see the same example
again, this time an exception will be thrown.
public class FinallyDemo {
}
Output
In try block
Exception caught in catch block of displayValue
In finally block
Value of i 3
Please note that it is not a good idea to return any thing from finally as it will suppress the exception.
finally must be used for cleaning up.
82
30.2.2 Points to note
Every try block must be followed by at least one catch or a finally clause. So we can have any of
these combinations try-catch, try-finally or try-catch-finally blocks.
When method is about to return from its try-catch block after normal execution flow or because
of an uncaught exception, finally block is executed just before the method returns.
If there are multiple catch blocks and none of them can handle the exception thrown, even then
the finally bock is executed.
Though there can be multiple catch blocks associated with a single try statement but there can
only be single finally block associated with a try block. In case of nested try blocks there can be
associated finally blocks with respective try blocks.
Finally block is used to close the allocated resources (like file handles, database connections)
before returning from the method.
It's not a good idea to return any value from finally as it may cause any exceptions that are not
caught in the method to be lost.
If the JVM exits (through System.exit() or JVM crash) while the try or catch code is being
executed, then the finally block may not execute. In case of multithreading if the thread
executing the try or catch code is interrupted or killed, the finally block may not execute even
though the application as a whole continues.
30.3 finalize()
finalize() method is a protected method of java.lang.Object class. Since it is in Object class thus it is
inherited by every class. This method is called by garbage collector thread before removing an object
from the memory. This method can be overridden by a class to provide any cleanup operation and gives
object final chance to cleanup before getting garbage collected.
protected void finalize() throws Throwable
{
//resource clean up operations
}
Please note that it is not a good idea to rely on finalize() method for closing resources as there is no
guarantee when finalize() method will be called by Garbage collector.
There may be a situation when an object will need to perform some action just before it is getting
garbage collected. For example if an object is holding some non-java resources like file handle then it is
better to make sure that these resources are closed before an object is destroyed because simply
reclaiming the memory used by an object would not guarantee that the resources it held would be
reclaimed.
For that purpose Java provides a mechanism called finalization through finalize() method. In finalize
method we can provide the actions to release the resources before the object is destroyed.
83
does not specify how soon a finalizer will be invoked that's one reason why we should not rely solely on
finalize() method to release resources.
According to Joshua Bloch in his book Effective Java, Item 7: Avoid Finalizers
"The promptness with which finalizers are executed is primarily a function of the garbage collection
algorithm, which varies widely from JVM implementation to JVM implementation. The behavior of a
program that depends on the promptness of finalizer execution may likewise vary. It is entirely possible
that such a program will run perfectly on the JVM on which you test it and then fail miserably on the
JVM favored by your most important customer."
Just as a reminder the protected access modifier provides the access as - Variables, methods and
constructors which are declared protected in a superclass can be accessed only by the subclasses in
other package or any class within the package of the protected members' class.
Since all the classes have Object class as the super class either directly or indirectly so this method
would be accessible to each and every class anyway so it makes sense to keep the access as protected.
84
30.3.5 Example code for finalize method
Here is a simple example where I have created an object then set that object reference as null. Also
called System.gc() to run garbage collector. Note you may not get the output in some of the runs as
System.gc() is also more of a suggestion to the virtual machine to reclaim memory from unused objects
it may not run as soon as System.gc() is called and the program may terminate not at all calling the
finalize method.
public class FinalizeDemo {
int i;
FinalizeDemo(int num){
this.i = num;
}
public static void main(String[] args) {
// creating object
FinalizeDemo finalizeDemo = new FinalizeDemo(10);
Temp temp = new Temp();
// setting object reference as null so it is
// eligible for garabge collection
finalizeDemo = null;
temp.doCalcualtion();
// setting object reference as null so it is
// eligible for garabge collection
temp = null;
// Calling System.gc() to run garbage collector
System.gc();
}
@Override
protected void finalize() throws Throwable {
try{
System.out.println("finalize method called for
FinalizeDemo");
}finally{
super.finalize();
}
}
class Temp{
public void doCalcualtion(){
int i = 5;
System.out.println("value of i is " + i);
}
@Override
protected void finalize() throws Throwable {
try{
System.out.println("finalize method called for Temp");
}finally{
super.finalize();
}
}
85
}
Output
value of i is 5
finalize method called for Temp
finalize method called for FinalizeDemo
Though I have used System.gc here to some how make sure that finalize() method is indeed called but
don't rely on it. To quote Joshua Bloch again "Don't be seduced by the methods System.gc and
System.runFinalization. They may increase the odds of finalizers getting executed, but they don't
guarantee it. The only methods that claim to guarantee finalization are System.runFinalizersOnExit and
its evil twin, Runtime.runFinalizersOnExit. These methods are fatally flawed and have been deprecated."
So first let us see the key differences between the fail-fast and fail-safe iterator and then we'll see some
programs to explain those features.
3. fail-fast iterator provides remove, set, and add operations. Note that not all the iterators support
all these methods. As exp. ListIterator supports add() method but the general iterator doesn't.
With fail-safe iterator element-changing operations on iterators themselves (remove, set, and add) are
not supported. These methods throw UnsupportedOperationException.
Now let us see some detailed explanation and supporting programs to see these features of both fail-
fast and fail-safe iterators.
fail-fast iterator fails if the underlying collection is structurally modified at any time after the iterator is
created, thus the iterator will throw a ConcurrentModificationException if the underlying collection is
structurally modified in any way except through the iterator's own remove or add (if applicable as in list-
iterator) methods.
Note that structural modification is any operation that adds or deletes one or more elements; merely
setting the value of an element (in case of list) or changing the value associated with an existing key (in
case of map) is not a structural modification.
Also note that according to Oracle Docs fail-fast behavior of an iterator cannot be guaranteed as it is,
generally speaking, impossible to make any hard guarantees in the presence of unsynchronized
concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort
basis. Therefore, it would be wrong to write a program that depended on this exception for its
correctness: the fail-fast behavior of iterators should be used only to detect bugs.
Example code of fail-fast iterator with an attempt to add new value to a map while the map is being
iterated
public class FailFastModification {
public static void main(String[] args) {
// creating map
Map <String,String> cityMap = new HashMap<String,String>();
cityMap.put("1","New York City" );
cityMap.put("2", "New Delhi");
cityMap.put("3", "Newark");
cityMap.put("4", "Newport");
87
// getting iterator
Iterator <String> itr = cityMap.keySet().iterator();
while (itr.hasNext()){
System.out.println(cityMap.get(itr.next()));
// trying to add new value to a map while iterating it
cityMap.put("5", "New City");
}
}
}
OUTPUT
Let’s see a multi-threaded example, where concurrency is simulated using sleep method.
public class FailFastTest {
public static void main(String[] args) {
final Map<String,String> cityMap = new HashMap<String,String>();
cityMap.put("1","New York City" );
cityMap.put("2", "New Delhi");
cityMap.put("3", "Newark");
cityMap.put("4", "Newport");
//This thread will print the map values
// Thread1 starts
Thread thread1 = new Thread(){
public void run(){
try{
Iterator i = cityMap.keySet().iterator();
while (i.hasNext()){
System.out.println(i.next());
// Using sleep to simulate concurrency
Thread.sleep(1000);
}
}catch(ConcurrentModificationException e){
System.out.println("thread1 : Concurrent modification detected on
this map");
}catch(InterruptedException e){
}
}
};
thread1.start();
89
// Thread1 ends
// This thread will try to remove value from the collection,
// while the collection is iterated by another thread.
// thread2 starts
Thread thread2 = new Thread(){
public void run(){
try{
// Using sleep to simulate concurrency
Thread.sleep(2000);
// removing value from the map
cityMap.remove("2");
System.out.println("city with key 2 removed successfully");
}catch(ConcurrentModificationException e){
System.out.println("thread2 : Concurrent modification detected
on this map");
} catch(InterruptedException e){}
}
};
thread2.start();
// thread2 end
} // main end
} // class end
Output
1
2
city with key 2 removed successfully
thread1 : Concurrent modification detected on this map
It can be seen that in thread 1 which is iterating the map, Concurrent
modification exception is thrown.
}
}
};
thread1.start();
Since iteration is done over a copy of the collection so interference is impossible and the iterator is
guaranteed not to throw ConcurrentModificationException.
Drawback of using a copy of the collection rather than original collection is that the iterator will not
reflect additions, removals, or changes to the collection since the iterator was created. Element-
changing operations on iterators themselves (remove, set, and add) are not supported. These methods
throw UnsupportedOperationException.
91
public class FailSafeTest {
public static void main(String[] args) {
92
33. Overview of lambda expression in Java 8
Lambda expressions (also known as closures) are one of the most important feature added in Java 8.
Lambda expressions provide a clear and elegant way to represent a single abstract method interface
(Functional interface) using an expression.
Though the true power of lambda expression comes into fore when used with stream API where lambda
expressions can be used to provide an easy yet efficient way to perform data manipulation operations
like sort, filter, map, reduce etc. But that is a topic for another post! Here I'll just stick to fundamentals
of Lambda expressions, functional interface and how lambda expressions can provide implementation of
the abstract method defined by the functional interface.
It is very important to have a good understanding of two terms to know lambda expression - lambda
expression itself and functional interface.
A new syntax and operator has been introduced in Java for Lambda expressions.
Here you can see a new arrow operator or lambda operator which divides the lambda expression into
two parts. Left side specifies parameters required by the lambda expression. Parameters are optional, if
no parameters are needed an empty parenthesis can be given. Right side known as lambda body
specifies the logic of the lambda expression.
This lambda expression takes no parameter, that's why empty parenthesis and returns the constant
value 7.
If we have to write the equivalent Java method then it will be something like this -
int getValue(){
return 7;
}
93
(String s) -> { System.out.println(s); };
Please note that from Java 8 it is possible for an interface to have default method and static method
thus the stress on "only one abstract method".
Also a new annotation @FunctionalInterface has been added in Java 8, all the functional interfaces can
be annotated with this annotation to ensure that they have only single abstract method.
Lambda supports "target typing" which infers the object type from the context in which it is used. To
infer that object type from the context -
The parameter type of the abstract method and the parameter type of the lambda expression
must be compatible. For Example, if the abstract method in the functional interface specifies
one int parameter, then the lambda should also have one int parameter explicitly defined or
implicitly inferred as int by the context.
Its return type must be compatible with the method's type.
Lambda expression can throw only those exceptions which are acceptable to the method.
Variable declarations
Assignments
Return statements
Array initializers
Method or constructor arguments
Lambda expression bodies
94
public class LambdaExpressionDemo {
public static void main(String[] args) {
// reference of the interface
IMyInterface objRef;
// Lambda expression
objRef = () -> 7;
System.out.println("Value is " + objRef.getValue());
// Another lambda expression using the same interface reference
objRef = () -> 7 * 5;
System.out.println("Value is " + objRef.getValue());
// This line will give compiler error as target type
// can't be inferred
objref = () -> "11";
}
}
Output
Value is 7
Value is 35
Here we have an interface IMyInterface with one method getValue() whose return type is int. Since
there is only one abstract method in the interface so IMyInterface is a functional interface.
In this program it can be seen how lambda expression () -> 7 is compatible with the abstract method.
Return type is int and there is no method parameter.
If you uncomment the line () -> "11"; it will give compiler error The target type of this expression must
be a functional interface as in this case return type is string which is not compatible with the return type
of the abstract method, lambda expression is implementing.
Also notice that the same functional interface reference is used to execute 2 lambda expressions
Since both of the lambda expressions are compatible with the target type so both of them can be
assigned to the same reference (Does it remind you of run time polymorphism?). That's why Lambda
Expression is a Poly Expression.
95
4 is even true
3 is even false
Here we need to note certain points -
n -> (n % 2) == 0;
In this lambda expression type is not specified explicitly as int, type is inferred from the context in which
the lambda expression is executed, though type can be given explicitly too.
Also parenthesis around the parameter is omitted, in case of single parameter it is not necessary to
enclose the parameter with parenthesis. Again it won't be invalid to do that, so (n) -> (n % 2) == 0; or (int
n) -> (n % 2) == 0; are also valid.
One important point here is we can't have lambda expression where type for only one of the parameter
is explicitly declared.
(int x, y) -> x + y;
Till now all the examples we have seen are single expression lambda, we also have a second type of
lambda expressions known as "block lambda" where the right side of the lambda expression is a block of
code.
Let's see an example, here with in the lambda expression we have a block of code for counting the
words in a string without using any String function.
@FunctionalInterface
interface IMyInterface {
int doCount(String str);
}
public class LambdaExpressionDemo {
public static void main(String[] args) {
// Lambda expression
IMyInterface objRef = (str) -> {
int c = 0;
char ch[]= new char[str.length()];
for(int i = 0; i < str.length(); i++){
ch[i] = str.charAt(i);
if(((i > 0) && (ch[i] != ' ') && (ch[i-1] == ' ')) ||
((ch[0] != ' ') && (i == 0)))
c++;
}
return c;
};
96
System.out.println("Words in the string " + objRef.doCount("Lambda
Expression in Java"));
}
}
Output
97
cityMap.put("5", "New Delhi");
cityMap.put("5", "Kolkata");
LinkedList is implemented using a doubly linked list concept where as ArrayList internally uses an array
of Objects which can be resized dynamically. In most of the cases we do use ArrayList and it works very
well but there are some use cases where use of the linked list may be a better choice. So let's see some
of the difference between ArrayList and LinkedList, it will help you in making an informed choice when
to use ArrayList and when a LinkedList.
ArrayList class provides a constructor ArrayList(int initialCapacity) even if the default constructor
ArrayList() is used an empty list is constructed with an initial capacity of ten. Where as LinkedList just
provides one constructor LinkedList() which constructs an empty list. Note that in LinkedList there is no
provision of initial capacity or default capacity.
What it means is that if elements are added at the last every time and capacity is not breached then
ArrayList will work faster because it already has an initial capacity and just need to add that element at
the index in the underlying array. Where as in LinkedList a new node has to be created and references
for Next and Prev are to be adjusted to accommodate the new Node.
The above mentioned case for add is something we do most of the time while using arraylist or use
get(int index) which also is faster in arraylist and that's why we normally use ArrayList.
Let's go through some of the operations to see which implementation of list shines where –
Even in the case of adding at the last ArrayList may give O(n) performance in the worst case. That will
happen if you add more elements than the capacity of the underlying array, as in that case a new array
(1.5 times the last size) is created, and the old array is copied to the new one.
So for LinkedList add(e Element) is always O(1) where as for ArrayList add(e Element) operation runs in
amortized constant time, that is, adding n elements requires O(n) time.
So for LinkedList get(int index) is O(n) where as for ArrayList get(int index) is O(1).
98
36.3 Removing an element
If you are removing using the remove(int index) method then for LinkedList class it will be O(n) as list
has to be traversed to get to that index and then the element removed. Though the LinkedList provides
methods like removeFirst() and removeLast() to remove the first or last element and in that case it will
be O(1).
In case of ArrayList getting to that index is fast but removing will mean shuffling the remaining elements
to fill the gap created by the removed element with in the underlying array. It ranges from O(1) for
removing the last element to O(n). Thus it can be said remove(int index) operation is O(n - index) for the
arraylist.
One more difference is that LinkedList implementation provides a descendingIterator() which comes
from implementing the Deque interface. descendingIterator() returns an iterator over the elements in
this deque in reverse sequence.
So you can see Vector in many ways is just like ArrayList apart from some differences and this post is
about those difference between the ArrayList and Vector.
1.ArrayList is not synchronized whereas Vector is Synchronized. Which means that the methods in the
Vector class are Synchronized methods making Vector thread-safe and ready to use as-is in a multi-
threaded environment.
2. A Vector, by default, doubles the size of its array when it needs to expand the array, while the
ArrayList increases its array size by 50 percent.
3. As mentioned though Vector is retrofitted to implement the List interface it still has legacy methods
which are not there in ArrayList. As Exp. addElement(), removeElement(),capacity() which are there in
Vector class but not in ArrayList.
99
4. Performance wise Vector is comparatively slower than the ArrayList because it is synchronized. That
means only one thread can access method of Vector at the time and there is also overhead of acquiring
lock on the object.
5. For traversing an ArrayList as well as Vector, Iterator or ListIterator can be used. That
Iterator/ListIterator is fail-fast and throws ConcurrentModificationException if any other Thread
modifies the map structurally by adding or removing any element except Iterator's own remove()
method.
For Vector enumeration can also be used for traversing which is not fail-fast.
How it differs from other implementations of the Map interface like HashMap and LinkedHashMap is
that objects in TreeMap are stored in sorted order. The elements are ordered using their natural
ordering or a comparator can be provided at map creation time to provide custom ordering (We'll see
an example a little later).
Bangalore 22
Chennai 36
100
Delhi 24
Kolkata 28
Mumbai 32
It can be seen that the TreeMap sorts the elements using their natural ordering which is ascending for
String.
Also note that though Chennai is added twice but it is stored only once as trying to store the same key
twice will result in overwriting of the old value with the new value (as the calculated hash will be the
same for the keys). Thus the last one is displayed while iterating the values.
101
38.4 TreeMap class' iterator is fail-fast
The iterators returned by this class' iterator method are fail-fast, if the map is structurally modified at
any time after the iterator is created, in any way except through the iterator's own remove method, the
iterator will throw a ConcurrentModificationException.
cityTemperatureMap.put("Delhi", "24");
cityTemperatureMap.put("Mumbai", "32");
cityTemperatureMap.put("Chennai", "35");
cityTemperatureMap.put("Bangalore", "22" );
cityTemperatureMap.put("Kolkata", "28");
//Comparator class
class TreeComparator implements Comparator<String>{
@Override
public int compare(String str1, String str2) {
return str2.compareTo(str1);
}
}
Output
Mumbai 32
Kolkata 28
Delhi 24
Chennai 35
Bangalore 22
Here note that a comparator is provided which reverses the sorting order. That comparator is provided
at the map creation time in a constructor.
102