Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
Core Java 1 of 28
Core Java Table of Content
--------------------------------------------------
General 4
What will happen if you call return statement or System.exit on try or catch block ? will finally block
execute? 4
Can you override private or static method in Java ? 4
What does the following Java program print? 4
What do the expression 1.0 / 0.0 will return? will it throw Exception? any compile time error? 5
Strings 6
What is a StringBuilder and what are its use cases? What is the difference between appending a string
to a StringBuilder and concatenating two strings with a + operator? How does StringBuilder differ
from StringBuffer? 6
How are strings represented in memory? 6
Suppose we have a circular reference (two objects that reference each other). Could such pair of
objects become eligible for garbage collection and why? 6
Multi Threading 8
Volatile 8
The Java volatile Visibility Guarantee 8
Example 8
Can we make array volatile in Java? 9
What are the practical uses of volatile modifier? 9
What is false sharing in the context of multi-threading? 9
False Sharing 10
Caching on Modern CPUs in less than 100 words 11
False Sharing 11
Countermeasures to False Sharing 12
False Sharing vs. @Contended: A Microbenchmark 13
What is the difference between preemptive scheduling and time slicing? 15
Number the bits, used to represent Unicode, ASCII, UTF-16, and UTF-8 characters? 15
Single Producer & Single Consumer 15
Core Java 2 of 28
Data.java 15
Producer.java 16
Consumer.java 17
Application.java 18
Collections 20
Fail Fast Vs Fail Safe Iterator 20
What is Concurrent Modification ? 20
Fail fast Iterator 20
How Fail Fast Iterator come to know that the internal structure is modified ? 20
Fail Safe Iterator 20
HashMap vs ConcurrentHashMap 21
Thread -Safe 21
Synchronization Method 22
Null Key 22
Performance 22
Arrange the following in the ascending order (performance) 22
LinkedList vs ArrayList 22
When to use LinkedList and ArrayList 23
What is CopyOnWriteArrayList ? How it is different from ArrayList in Java? 24
BlockingQueue 24
How TreeMap Works!! 24
How TreeMap works in java ? 24
Why and when we use TreeMap ? 25
What is the runtime performance of the get() method in TreeMap and HashMap ,where n
represents the number of elements ? 25
One liner 25
What is "natural ordering" in TreeMap ? 25
Why do we need TreeMap when we have sortedMap ? 25
Preferred Data Structure: HashMap or TreeMap ? 25
What happens if the TreeMap is concurrently modified while iterating the elements ? 26
Which copy technique (deep or shallow ) is used by the TreeMap clone() method ? 26
Why java's treemap does not allow an initial size ? 26
Core Java 3 of 28
IdentityHashMap 26
WeakHashMap 26
RedBlackTree (RBT) Data Structure 27
Java Memory Model / GC 28
JRE vs JVM 28
Core Java 4 of 28
Core Java --------------------------------------------------
General
What will happen if you call return statement or System.exit on try or
catch block ? will finally block execute?
This is a very popular tricky Java question and it's tricky because many programmer think that finally
block always executed. This question challenge that concept by putting return statement in try or catch
block or calling System.exit from try or catch block. Answer of this tricky question in Java is that finally
block will execute even if you put return statement in try block or catch block but finally block won't run
if you call System.exit form try or catch.
____________________________________________________________________________
Can you override private or static method in Java ?
Another popular Java tricky question, As I said method overriding is a good topic to ask trick questions in
Java. Anyway, you can not override private or static method in Java, if you create similar method with
same return type and same method arguments that's called method hiding.
____________________________________________________________________________
What does the following Java program print?
public class Test {
public static void main(String[] args) {
System.out.println(Math.min(Double.MIN_VALUE, 0.0d));
}
}
This question is tricky because unlike the Integer, where MIN_VALUE is negative, both the MAX_VALUE
and MIN_VALUE of the Double class are positive numbers. The Double.MIN_VALUE is 2^(-1074), a
Core Java 5 of 28
double constant whose magnitude is the least among all double values. So unlike the obvious answer,
this program will print 0.0 because Double.MIN_VALUE is greater than 0.
____________________________________________________________________________
What do the expression 1.0 / 0.0 will return? will it throw Exception?
any compile time error?
This is another tricky question from Double class. Though Java developer knows about the double
primitive type and Double class, while doing floating point arithmetic they don't pay enough attention to
Double.INFINITY, NaN, and -0.0 and other rules that govern the arithmetic calculations involving them.
The simple answer to this question is that it will not throw Arithmetic Excpeption and return
Double.INFINITY.
Summary:
If divided by zero, the Arithmetic Exception, whereas divided by 0.0 (double/float) then Infinity is the
result.
____________________________________________________________________________
Core Java 6 of 28
Strings
What is a StringBuilder and what are its use cases? What is the
difference between appending a string to a StringBuilder and
concatenating two strings with a + operator? How does StringBuilder
differ from StringBuffer?
StringBuilder allows manipulating character sequences by appending, deleting and inserting characters
and strings. This is a mutable data structure, as opposed to the String class which is immutable.
When concatenating two String instances, a new object is created, and strings are copied. This could
bring a huge garbage collector overhead if we need to create or modify a string in a loop. StringBuilder
allows handling string manipulations much more efficiently.
StringBuffer is different from StringBuilder in that it is thread-safe. If you need to manipulate a string in
a single thread, use StringBuilder instead.
____________________________________________________________________________
How are strings represented in memory?
A String instance in Java is an object with two fields: a char[] value field and an int hash field. The value
field is an array of chars representing the string itself, and the hash field contains the hashCode of a
string which is initialized with zero, calculated during the first hashCode() call and cached ever since. As
a curious edge case, if a hashCode of a string has a zero value, it has to be recalculated each time the
hashCode() is called.
Important thing is that a String instance is immutable: you can’t get or modify the underlying char[]
array. Another feature of strings is that the static constant strings are loaded and cached in a string pool.
If you have multiple identical String objects in your source code, they are all represented by a single
instance at runtime.
____________________________________________________________________________
Suppose we have a circular reference (two objects that reference each
other). Could such pair of objects become eligible for garbage collection
and why?
Yes, a pair of objects with a circular reference can become eligible for garbage collection. This is because
of how Java’s garbage collector handles circular references. It considers objects live not when they have
Core Java 7 of 28
any reference to them, but when they are reachable by navigating the object graph starting from some
garbage collection root (a local variable of a live thread or a static field). If a pair of objects with a
circular reference is not reachable from any root, it is considered eligible for garbage collection.
____________________________________________________________________________
Core Java 8 of 28
Multi Threading
Volatile
The Java volatile keyword is used to mark a Java variable as "being stored in main memory". More
precisely that means, that every read of a volatile variable will be read from the computer's main
memory, and not from the CPU cache, and that every write to a volatile variable will be written to main
memory, and not just to the CPU cache.
Actually, since Java 5 the volatile keyword guarantees more than just that volatile variables are written
to and read from main memory. I will explain that in the following sections.
The Java volatile Visibility Guarantee
The Java volatile keyword guarantees visibility of changes to variables across threads. This may sound
a bit abstract, so let me elaborate.
In a multithreaded application where the threads operate on non-volatile variables, each thread may
copy variables from main memory into a CPU cache while working on them, for performance reasons.
If your computer contains more than one CPU, each thread may run on a different CPU. That means,
that each thread may copy the variables into the CPU cache of different CPUs.
When a thread writes to a volatile variable, then not just the volatile variable itself is written to main
memory. Also all other variables changed by the thread before writing to the volatile variable are also
flushed to main memory. When a thread reads a volatile variable it will also read all other variables
from main memory which were flushed to main memory together with the volatile variable.
Example
public class SharedObject { public int counter = 0; }
Imagine too, that only Thread 1 increments the counter variable, but both Thread 1 and Thread 2 may
read the counter variable from time to time.
If the counter variable is not declared volatile there is no guarantee about when the value of the counter
variable is written from the CPU cache back to main memory. This means, that the counter variable
value in the CPU cache may not be the same as in main memory.
Core Java 9 of 28
____________________________________________________________________________
Can we make array volatile in Java?
This is one of the tricky Java multi-threading questions you will see in senior Java developer Interview.
Yes, you can make an array volatile in Java but only the reference which is pointing to an array, not the
whole array. What I mean, if one thread changes the reference variable to points to another array, that
will provide a volatile guarantee, but if multiple threads are changing individual array elements they
won't be having happens before guarantee provided by the volatile modifier.
____________________________________________________________________________
What are the practical uses of volatile modifier?
One of the practical use of the volatile variable is to make reading double and long atomic. Both double
and long are 64-bit wide and they are read in two parts, first 32-bit first time and next 32-bit second
time, which is non-atomic but volatile double and long read is atomic in Java. Another use of the volatile
variable is to provide a memory barrier, just like it is used in Disrupter framework. Basically, Java
Memory model inserts a write barrier after you write to a volatile variable and a read barrier before you
read it. Which means, if you write to volatile field then it's guaranteed that any thread accessing that
variable will see the value you wrote and anything you did before doing that right into the thread is
guaranteed to have happened and any updated data values will also be visible to all threads, because
the memory barrier flushed all other writes to the cache.
____________________________________________________________________________
What is false sharing in the context of multi-threading?
false sharing is one of the well-known performance issues on multi-core systems, where each process
has its local cache. false sharing occurs when threads on different processor modify variables that reside
on same cache line as shown in the following image:
Core Java 10 of 28
False sharing is very hard to detect because the thread may be accessing completely different global
variables that happen to be relatively close together in memory. Like many concurrency issues, the
primary way to avoid false sharing is careful code review and aligning your data structure with the size
of a cache line.
____________________________________________________________________________
False Sharing
Normally, Java programmers are not too concerned about the hardware on which their beautiful
software runs as long as provides loads of memory. Most of the time this is a good thing as software
should solve a business problem rather than satisfying a machine. The JVM does a decent job hiding the
underlying platform but as we know, abstractions are leaky. Sometimes we have to peek under hood,
especially when we're concerned about performance. One such topic is false sharing, were a very
performance-critical component might not perform as well as we'd expect.
Consider this class:
Core Java 11 of 28
public final class X { public volatile int f1; public volatile int f2; }
On Oracle JDK 1.8, instances of this class are laid out in memory as shown below:
Note: I have determined the layout on OpenJDK 1.8.0-b132 (64-Bit) using JOL, see also my
accompanying project on false sharing on Github.
We have declared all fields as volatile indicating that these fields may be used by different threads and
we want to ensure writes are visible to all of them. As a result, the runtime will emit code to ensure that
writes to a field are visible across CPU cores. But how does this work?
Caching on Modern CPUs in less than 100 words
CPUs don't care about classes or objects; they are concerned with reads and writes on memory cells.
To efficiently operate on data, it is fetched from main memory into a CPU cache at the granularity of a
cache line. A cache line is a block of memory in the CPU cache, say 64 bytes. If data in a cache line is
modified, each core sends messages across the memory bus according to a well-defined cache
coherence protocol (the most common one being the MESI protocol) so all cores can reconcile.
False Sharing
In this example I assume a hypothetical CPU with one cache layer (L1 cache) where each cache
belongs to one core. What happens if one thread, running on Core0 is constantly writing to X.f1
(depicted in red below) and another thread on Core1 is constantly reading from f2 (depicted in green
below)?
Core Java 12 of 28
Core0 knows that it does not own the cache line "n" exclusively, so it has to broadcast an "Invalidate"
message across the bus after changing the cache line to notify other cores that their caches are stale.
Core1 is listening on the bus and invalidates the corresponding cache line. Consequently, this
produces a lot of unnecessary bus traffic although both cores operate on different fields. This
phenomenon is known as false sharing.
Countermeasures to False Sharing
This is a rather unsatisfying state of affairs: Although each thread operates on different fields, we
produce a lot of unnecessary bus traffic which is ultimately caused by the memory layout of our Java
objects. If we were able to influence the memory layout we can avoid false sharing. It turns out there
are a few ways around this problem. A word of warning though: The following techniques depend on
the JVM implementation or the underlying hardware so take my words with a grain of salt. The
techniques are taken from the JMH example class JMHSample_22_FalseSharing and a presentation
on @Contended which inspired me to write this blog post. I'll just describe three of them shortly here
as the example class of JMH documents these and more techniques already very clearly:
Field padding within class: The idea is to stuff enough fields between f1 and f2 so that they end up on
different cache lines. Depending on the JVM implementation this may not work as a JVM
implementation can lay out fields in memory as it sees fit.
Field padding across class hierarchy: A JVM implementation might be cleverly rearranging fields
though so field padding will not work. However, if f1 and the padding fields are placed in a dedicated
class, and f2 is placed in a subclass of it, currently no JVM implementation will rearrange the padding
fields across the class hierarchy. This is quite quirky and fortunately, there is a better solution in Java
8.
@Contended: @Contended has been introduced to Java 8 with JEP-142. With this annotation, fields
can be declared as contended. The current OpenJDK implementation will then pad the field
appropriately, inserting a 128 byte padding after each annotated field. 128 bytes is twice the typical
Core Java 13 of 28
cache line size and were chosen to account for cache prefetching algorithms, specifically algorithms
which fetch two adjacent cache lines. Consideration of @Contended by the JVM must be explicitly
enabled -XX:-RestrictContended. As it is likely that cache line size or cache prefetching algorithms will
change over time, the JVM flag -XX:ContendedPaddingWidth (previously known as -
XX:FieldPaddingWidth) allows to control the padding size. If this all sounds a bit scary to you, you are
not alone. In the introductory post on the OpenJDK mailing list the annotation was controversially
discussed. It is likely that you'll almost never encounter the annotation in an application but parts of
the JDK such as ForkJoinPool already take advantage of it.
To properly pad f1, annotate it with @Contended:
import sun.misc.Contended;
public final class X {
@Contended
public volatile int f1;
public volatile int f2;
}
Which will result in the object layout below:
False Sharing vs. @Contended: A Microbenchmark
To demonstrate the effects of false sharing, I have written a small JMH microbenchmark which is
available on Github. Below is the result of this benchmark comparing false sharing and the
@Contended approach using three reader threads and one writer thread. It has been run on an Intel
Core i7-2635QM with 4 physical cores.
Core Java 14 of 28
While write throughput is roughly equivalent (mean throughput 373 ops/µs for false sharing and 371
ops/µs for the solution with @Contended), the mean read throughput is around three times higher with
@Contended (2338 ops/µs) than with false sharing (813 ops/µs). This clearly demonstrates the influence
of false sharing in this scenario.
However, don't worry: @Contended is definitely not meant to be sprinkled across the entire codebase.
In fact, it should be used very, very sparingly and people wanting to use @Contended probably already
use one of the previously-mentioned field padding approaches. In JDK 8, @Contended is just used in 5
classes (Thread, Striped64, ConcurrentHashMap, Exchanger and ForkJoinPool). There are limited
circumstances where false sharing is really a problem and bottlenecks should be identified before-hand.
But that may be the topic of another article some day...
____________________________________________________________________________
Core Java 15 of 28
What is the difference between preemptive scheduling and time
slicing?
Differences between preemptive and time scheduling are:
- In Preemptive scheduling the highest priority task executes until it enters the waiting or dead stated or
a higher priority task comes into existence.
- Time slicing, a task executes for a predefined time period and then the pool of ready tasks. The
scheduler then determines which task should execute next, based on priority and other factor.
____________________________________________________________________________
Number the bits, used to represent Unicode, ASCII, UTF-16, and UTF-8
characters?
- Unicode requires 16 bits
- ASCII require 7 bits. but it is usually represented as 8 bits.
- UTF-8 represents characters using 8, 16, and 18 bit patterns.
- UTF-16 uses 16-bit and larger bit patterns.
____________________________________________________________________________
Single Producer & Single Consumer
Data.java
package org.karanki.play.coding.single_producer_consumer;
public class Data {
volatile private String data;
private volatile boolean completed;
public String getData() {
if(data == null) {
throw new UnsupportedOperationException("Empty Data found");
}
String retunedData = data;
data = null;
Core Java 16 of 28
return retunedData;
}
public void setData(String data) {
this.data = data;
}
public void setCompleted() {
completed = true;
}
public boolean isCompleted() {
return completed;
}
}
Producer.java
package org.karanki.play.coding.single_producer_consumer;
import java.util.UUID;
public class Producer implements Runnable {
volatile private Data data;
public Producer(Data data) {
this.data = data;
}
@Override
public void run() {
synchronized (data) {
for(int i = 1; i <= 10; i++) {
String uuid = UUID.randomUUID().toString();
System.out.println("Producing :: " + uuid);
data.setData(uuid);
Core Java 17 of 28
data.notify();
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
data.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Producer Done!!!");
data.setCompleted();
data.notify();
}
}
}
Consumer.java
package org.karanki.play.coding.single_producer_consumer;
public class Consumer implements Runnable {
volatile private Data data;
public Consumer(Data data) {
this.data = data;
}
@Override
public void run() {
Core Java 18 of 28
synchronized (data) {
while(!data.isCompleted()) {
System.out.println("Consuming :: " + data.getData());
data.notify();
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
data.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumer Done!!!");
}
}
};
Application.java
package org.karanki.play.coding.single_producer_consumer;
public class Application {
public static void main(String[] args) {
Data data = new Data();
Core Java 19 of 28
Thread producer = new Thread(new Producer(data));
Thread consumer = new Thread(new Consumer(data));
producer.start();
consumer.start();
}
};
____________________________________________________________________________
Core Java 20 of 28
Collections
Fail Fast Vs Fail Safe Iterator
What is Concurrent Modification ?
When one or more thread is iterating over the collection, in between, one thread changes the
structure of the collection (either adding the element to the collection or by deleting the element in
the collection or by updating the value at particular position in the collection) is known as Concurrent
Modification
Fail fast Iterator
Fail fast iterator while iterating through the collection , instantly throws Concurrent Modification
Exception if there is structural modification of the collection . Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic
behavior at an undetermined time in the future.
Fail-fast iterator can throw ConcurrentModificationException in two scenarios :
Single Threaded Environment
After the creation of the iterator , structure is modified at any time by any method other than
iterator's own remove method.
Multiple Threaded Environment
If one thread is modifying the structure of the collection while other thread is iterating over it .
How Fail Fast Iterator come to know that the internal structure is modified ?
Iterator read internal data structure (object array) directly . The internal data structure(i.e object
array) should not be modified while iterating through the collection. To ensure this it maintains an
internal flag "mods" .Iterator checks the "mods" flag whenever it gets the next value (using hasNext()
method and next() method). Value of mods flag changes whenever there is an structural modification.
Thus indicating iterator to throw ConcurrentModificationException.
Fail Safe Iterator
Fail Safe Iterator makes copy of the internal data structure (object array) and iterates over the copied
data structure.Any structural modification done to the iterator affects the copied data structure. So ,
original data structure remains structurally unchanged .Hence , no ConcurrentModificationException
throws by the fail safe iterator.
Core Java 21 of 28
Two issues associated with Fail Safe Iterator are :
1. Overhead of maintaining the copied data structure i.e memory.
2. Fail safe iterator does not guarantee that the data being read is the data currently in the original
data structure.
According to Oracle docs , fail safe iterator is ordinarily too costly, but may be more efficient than
alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or
don’t want to synchronize traversals, yet need to preclude interference among concurrent threads.
The "snapshot" style iterator method uses a reference to the state of the array at the point that the
iterator was created. This array never changes during the lifetime of the iterator, so interference is
impossible and the iterator is guaranteed not to throw ConcurrentModificationException.The iterator
will not reflect additions, removals, or changes to the list since the iterator was created. Element-
changing operations on iterators themselves (remove(), set(), and add()) are not supported. These
methods throw UnsupportedOperationException.
____________________________________________________________________________
HashMap vs ConcurrentHashMap
Thread -Safe
ConcurrentHashMap is thread-safe that is the code can be accessed by single thread at a time .
While HashMap is not thread-safe.
Core Java 22 of 28
Synchronization Method
HashMap can be synchronized by using synchronizedMap(HashMap) method . By using this
method we get a HashMap object which is equivalent to the HashTable object . So every modification
is performed on Map is locked on Map object.
ConcurrentHashMap synchronizes or locks on the certain portion of the Map . To optimize
the performance of ConcurrentHashMap , Map is divided into different partitions depending upon
the Concurrency level . So that we do not need to synchronize the whole Map Object.
Null Key
ConcurrentHashMap does not allow NULL values . So the key can not be null in ConcurrentHashMap
.While In HashMap there can only be one null key.
Performance
In multiple threaded environment HashMap is usually faster than ConcurrentHashMap . As
only single thread can access the certain portion of the Map and thus reducing the performance .
While in HashMap any number of threads can access the code at the same time.
____________________________________________________________________________
Arrange the following in the ascending order (performance)
HashMap , Hashtable , ConcurrentHashMap and Collections.SynchronizedMap
Hashtable < Collections.SynchronizedMap < ConcurrentHashMap < HashMap
____________________________________________________________________________
LinkedList vs ArrayList
LinkedList and ArrayList both implement List Interface but how they work internally is where the
differences lies. Main difference between ArrayList and LinkedList is that ArrayList is implemented using
re sizable array while LinkedList is implemented using doubly LinkedList. ArrayList is more popular
among Java programmer than LinkedList as there are few scenarios on which LinkedList is a suitable
collection than ArrayList. In this article we will see some differences between LinkedList and ArrayList
and try to find out when and where to use LinkedList over ArrayList.
Core Java 23 of 28
All the differences between LinkedList and ArrayList has there root on difference between Array and
LinkedList data-structure. If you are familiar with Array and LinkedList data structure you will most likely
derive following differences between them:
1) Since Array is an index based data-structure searching or getting element from Array with index is
pretty fast. Array provides O(1) performance for get(index) method but remove is costly in ArrayList as
you need to rearrange all elements. On the Other hand LinkedList doesn't provide Random or index
based access and you need to iterate over linked list to retrieve any element which is of order O(n).
2) Insertions are easy and fast in LinkedList as compared to ArrayList because there is no risk of resizing
array
and copying content to new array if array gets full which makes adding into ArrayList of O(n) in worst
case, while adding is O(1) operation in LinkedList in Java. ArrayList also needs to update its index if you
insert something anywhere except at the end of array.
3) Removal is like insertions better in LinkedList than ArrayList.
4) LinkedList has more memory overhead than ArrayList because in ArrayList each index only holds
actual object (data) but in case of LinkedList each node holds both data and address of next and
previous node.
When to use LinkedList and ArrayList
● LinkedList is not as popular as ArrayList but still there are situation where a LinkedList is better
choice than ArrayList in Java. Use LinkedList in Java if:
●
● Your application can live without Random access. Because if you need nth element in LinkedList
you need to first traverse up to nth element O(n) and than you get data from that node.
● Your application is more insertion and deletion driver and you insert or remove more than
retrieval. Since insertion or removal doesn't involve resizing its much faster than ArrayList.
● ArrayList has constant time search operation O(1) .Hence, ArrayList is preferred when there are
more get() or search operation .
● Insertion , Deletion operations take constant time O(1) for LinkedList. Hence, LinkedList is
preferred when there are more insertions or deletions involved in the application.
That’s all on difference between ArrayList and LinkedList in Java. Use ArrayList in Java for all there
situation where you need a non-synchronized index based access. ArrayList is fast and easy to use, just
try to minimize array resizing by constructing arraylist with proper initial size.
____________________________________________________________________________
Core Java 24 of 28
What is CopyOnWriteArrayList ? How it is different from ArrayList in
Java?
CopyOnWriteArrayList is a thread safe variant of ArrayList in which all mutative operations like add , set
are implemented by creating a fresh copy of the underlying array.
It guaranteed not to throw ConcurrentModificationException.
It permits all elements including null. It is introduced in jdk 1.5
____________________________________________________________________________
BlockingQueue
BlockingQueue implements the java.util.Queue interface . BlockingQueue supports operations that wait
for the queue to become non-empty when retrieving an element , and wait for space to become
available in the queue when storing an element .
It does not accept null elements.
Blocking queues are primarily designed for the producer-consumer problems.
BlockingQueue implementations are thread-safe and can also be used in inter-thread communications.
This concurrent Collection class was added in jdk 1.5
____________________________________________________________________________
How TreeMap Works!!
Treemap class is like HashMap which stores key- value pairs . The major difference is that Treemap sorts
the key in ascending order.
Treemap is sorted according to the natural ordering of its keys, or by a Comparator provided at map
creation time, depending on which constructor is used.
This implementation provides guaranteed log(n) time cost for the containsKey, get, put and remove
operations. Algorithms are adaptations of those in Cormen, Leiserson, and Rivest's Introduction to
Algorithms.
How TreeMap works in java ?
TreeMap is a Red-Black tree based NavigableMap implementation.In other words , it sorts the
TreeMap object keys using Red-Black tree algorithm.
Core Java 25 of 28
Why and when we use TreeMap ?
We need TreeMap to get the sorted list of keys in ascending order.
What is the runtime performance of the get() method in TreeMap and
HashMap ,where n represents the number of elements ?
TreeMap implementation provides guaranteed log(n) time cost for the containsKey,get,put and
remove operations.
One liner
TreeMap : log(n) HashMap : Constant time performance assuming elements disperses properly.
What is "natural ordering" in TreeMap ?
"Natural" ordering is the ordering implied by the implementation of the Comparable interface by the
objects used as keys in the TreeMap. Essentially, RBTree must be able to tell which key is smaller than
the other key, and there are two ways to supply that logic to the RBTree implementation:
1.Implement Comparable interface in the class(es) used as keys to TreeMap, or
2.Supply an implementation of the Comparator that would do comparing outside the key class itself.
Natural ordering is the order provided by the Comparable interface .If somebody puts the key that do
not implement natural order then it will throw ClassCastException.
Why do we need TreeMap when we have sortedMap ?
SortedMap is a interface and TreeMap is the class implementing it .As we know one can not create
objects of the interface . Interface tells us which methods a sortedMap implementation should
provide .TreeMap is such an implementation.
Preferred Data Structure: HashMap or TreeMap ?
HashMap is faster while TreeMap is sorted .Thus we choose them according to their advantage.
If you do not want to sort the elements but just to insert and retrieve the elements then use HashMap
.
But if you want to maintain the order of the elements then TreeMap should be preferred because the
result is alphabetically sorted .While iterating HashMap there is no ordering of the elements ,on the
other hand , TreeMap iterates in the natural key order.
Core Java 26 of 28
What happens if the TreeMap is concurrently modified while iterating the
elements ?
The iterator fails fast and quickly if structurally modified at any time after the iterator is created (in
any way except through the iterator's own remove method ). We already discussed the difference
between Fail-fast and Fail safe iterators .
Which copy technique (deep or shallow ) is used by the TreeMap clone() method
?
According to docjar , clone() method returns the shallow copy of the TreeMap instance . In shallow
copy object B points to object A location in memory . In other words , both object A and B are sharing
the same elements .The keys and values themselves are not cloned .
Why java's treemap does not allow an initial size ?
HashMap reallocates its internals as the new one gets inserted while TreeMap does not reallocate
nodes on adding new ones. Thus , the size of the TreeMap dynamically increases if needed , without
shuffling the internals. So it is meaningless to set the initial size of the TreeMap.
____________________________________________________________________________
IdentityHashMap
IdentityHashMap is a class present in java.util package. It implements the Map interface with a hash
table , using reference equality instead of object equality when comparing keys and values.In other
words , in IdentityHashMap two keys k1 and k2 are considered equal if only if (k1==k2).
IdentityHashMap is not synchronized.
Iterators returned by the iterator() method are fail-fast , hence , will throw
ConcurrentModificationException.
____________________________________________________________________________
WeakHashMap
WeakHashMap is a class present in java.util package similar to IdentityHashMap. It is a Hashtable based
implementation of Map interface with weak keys. An entry in WeakHashMap will automatically be
removed when its key is no longer in ordinary use. More precisely the presence of a mapping for a given
key will not prevent the key from being discarded by the garbage collector.
It permits null keys and null values.
Like most collection classes this class is not synchronized. A synchronized WeakHashMap may be
constructed using the Collections.synchronizedMap() method.
Core Java 27 of 28
Iterators returned by the iterator() method are fail-fast , hence , will throw
ConcurrentModificationException.
____________________________________________________________________________
RedBlackTree (RBT) Data Structure
Red Black algorithm is a complex algorithm . We should read the pseudocode of Red Black algorithm in
order to understand the internal implementation .
● A red-black tree is a type of self-balancing binary search tree.
● Red-black trees are used to implement associative arrays.
● Red-black trees make use of tree rotations.
● Insertion, deletion, and searching take O(log n) time in a red-black tree.
Red Black tree has the following properties :
1. As the name of the algorithm suggests ,color of every node in the tree is either red or black.
2. Root node must be Black in color.
3. Red node can not have a red color neighbor node.
4. All paths from root node to the null should consist the same number of black nodes
____________________________________________________________________________
Core Java 28 of 28
Java Memory Model / GC
JRE vs JVM
Java Runtime Environment contains JVM, class libraries, and other supporting files.
It does not contain any development tools such as compiler, debugger, etc.
Actually JVM runs the program, and it uses the class libraries, and other supporting files provided in JRE.
JRE = JVM + Java Packages Classes (like util, math, lang, awt, swing etc) + runtime libraries.
If you want to run any Java program, you need to have JRE installed in the system.
JRE is the box and JVM is the content of the box.
In simple words JRE = JVM + rt.jar
where rt.jar contains lang, util, awt, swing, math etc. libraries or compiled .class files used to run our
program.
____________________________________________________________________________