Cracking Core Java Interviews Sample PDF
Cracking Core Java Interviews Sample PDF
Cracking
Java Interviews
( Java 8 )
My skills my Job!!
Preface
This work is my sincere effort to consolidate solutions to some basic set of problems faced by my fellow mates
in their day to day work. This work can be used by candidates preparing to brush up their skills for Job change.
This Book Is
• Collection of excerpts discussing the common problems faced by an experienced Java Developer in his
day to day work. The intent is not to provide with the concrete solution to a given problem, but to show the
approach to get the problem solved. And there could definitely be more efficient ways to solve the given
problem compared to what is mentioned in this book. The approach shown here is limited to the knowledge
of the author.
• Collection of Questions in Core Java 8, Object Oriented Design, Concurrency, Algorithms & Data
Structures, Spring, Hibernate, REST and few puzzles.
I hope this book adds value to your skills. Be a knowledge seeker for lifetime and keep enjoying new learnings!
Munish Chandel
[email protected]
http://linkedIn.com/munish.chandel
August 2014
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 4
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 5
Contents
Cracking Java Interviews 2
Preface 3
Q 1. What are good software practices for developing Scalable, Testable and Maintainable Software ? 15
Q 2. What are good books for reference on Java Programming ?
15
Q 3. What is Growth Road Map for a Java Developer? 16
Q 4. Why should I choose Java for Software Development? What are Pros and Cons of Java 8 ? 17
Q 5. What is difference between 32 bit and 64 bit versions of Java? 17
Q 6. What are four basic principles of OOP? 18
Q 7. What are the key paradigms for Developing the Clean Object Oriented Code? 18
Q 8. What is Role of Requirement Understanding in software development process? 18
Q 9. What is Logarithm? Why is it relevant in Software Development? 20
Q 10. What do you understand by Big O notation, why is it important in software development ? 21
Q 11. How would you determine the Time Complexity of a given algorithm, are there any general guidelines? 22
Q 12. What is a sorting algorithm ? List down sorting algorithms by their time & memory complexity in Big O
notation ? When do we call a sorting algorithm 'Stable'? 23
Q 13. Why Prime Numbers are given much importance in writing certain algorithms like hashcode()? 29
Q 14. What is left shift <<, right shift >> and Unsigned right shift >>> operator in Java? How are these useful?29
Q 15. What is 2's complement notation system for Binary Numbers? 31
Q 16. How Heap space is divided in Java. How does Garbage Collector cleans up the unused Objects ? Why
shouldn't we use System.gc() command in production code? 32
Q 17. What is difference between Stack and Heap area of JVM Memory? What is stored inside a stack and what
goes into heap? 36
Q 18. What is a Binary Tree? Where and why is this used in Java Programs? 37
Q 19. Discuss implementation and uses of TreeSet Collection? 37
Q 20. How does Session handling works in Servlet environment? 38
Q 21. Explain Servlet Life Cycle in a Servlet Container ? 39
Q 22. How can one handle relative context path while coding the web applications? For example, your web
application may be deployed at a different context path in Tomcat, how will you make sure static/dynamic
resources works well at custom context path ? 40
Q 23. How will you write a Recursive Program? 41
Q 24. How many elements a complete binary tree could hold for a depth of 10? 41
Q 25. Explain working of a hashing data structure, for example HashMap in Java. 42
Q 26. Discuss internal's of a concurrent hashmap provided by Java Collections Framework. 43
Q 27. Why do we need Reader Classes when we already have Streams Classes? What are the benefit of using a
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 6
Q 135. We have an Application and we want that only Single Instance should run for that Application. If
Application is already running then second instance should never be started. How would you handle this in Java?
126
Concurrency in Java 127
Q 136. What is Concurrency? How will you implement Concurrency in your Java Programs? 127
Q 137. There are two Threads A and B operating on a shared resource R, A needs to inform B that some
important changes has happened in R. What technique would you use in Java to achieve this? 128
Q 138. What are different states of a Thread? What does those states tells us? 129
Q 139. Question: What do you understand by Java Memory Model? What is double-checked locking? What is
different about final variables in new JMM? 130
Q 140. Is i++ thread-safe (increment operation on primitive types)? 134
Q 141. What happens when wait() & notify() method are called? 134
Q 142. Discuss ThreadPoolExecutor ? What different Task Queuing Strategies are possible ? How will you
gracefully handle rejection for Tasks ? 134
Q 143. How will you write a custom ThreadPoolExecutor that can be paused and resumed on demand ? You can
extend the existing ThreadPoolExecutor to add this new behavior. 136
Q 144. How will you write your own custom thread pool executor from scratch ? 137
Q 145. Discuss about volatile keyword and Java Memory Model? 139
Q 146. What is a CAS? How does it help writing non-blocking scalable applications? Tell something about
Atomic Package provided by Java 1.6 140
Q 147. There is a object state which is represented by two variables. How would you write a high throughput
non-blocking algorithm to update the state from multiple threads? 141
Q 148. How would you implement AtomicFloat /AtomicDouble using CAS? 142
Q 149. How LongAdder and LongAccumulator are different from AtomicLong & AtomicInteger ? 144
Q 150. Can we implement check & update method (similar to compare and swap) using volatile alone? 144
Q 151. How will you track the largest value monitored by different threads in an non-blocking fashion (using
Atomic Operations) ? 144
Q 152. What is difference between Fork/Join framework and ExecutorService ? 145
Q 153. How does ForkJoinPool helps in writing concurrent applications ? Please provide few examples for
RecursiveTask and RecursiveAction. 145
Q 154. How will you calculate Fibonacci Sequence on a multi-core processor ? 148
Q 155. How will you increment each element of an Integer array, utilizing all the cores of processor ? 149
Q 156. You are writing a multi-threaded software piece for NSE for maintaining the volume of Trades made by
its individual brokers (icici direct, reliance ). It's highly concurrent scenario and we can not use lock based thread
safety due to high demand of throughput. How would handle such scenario? 150
Q 157. Calculate the time spread for 10 threads - Suppose T1 started earliest and T5 finished last, then the
difference between T5 and T1 will give time spread. 151
Q 158. What are fail-fast Iterator? what is fail safe? 153
Q 159. There is a stream of words which contains Anagrams. How would you print anagrams in a single bucket
from that stream? 154
Q 160. Describe CopyOnWriteArrayList? Where is it used in Java Applications? 155
Q 161. There are M number of Threads who work on N number of shared synchronized resources. How would
you make sure that deadlock does not happen? 155
Q 162. Are there concurrent version for TreeMap and TreeSet in Java Collections Framework? 155
Q 163. Is it safe to iterate over an ArrayList and remove its elements at the same time ? When do we get
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 10
Q 169. Given a collection of 1 million integers ranging from 1 to 9, how would you sort them in Big O(n) time?
163
Q 170. Given 1 million trades objects, you need to write a method that searches if the specified trade is
contained in the collection or not. Which collection would you choose for storing these 1 million trades and
why?164
Q 171. I have an Integer array where every number appears even number of time except one. Find that number.
164
Q 172. how would you check if a number is even or odd using bit wise operator in Java? 165
Q 173. How would you check if the given number is power of 2? 165
Q 174. What is a PriorityQueue? How is it implemented in Java? What are its uses? 166
Q 175. What is difference between Collections.sort() and Arrays.sort()? Which one is better in terms of time
efficiency?167
Q 176. There are 1 billion cell-phone numbers each having 10 digits, all of them stored randomly in a file. How
would you check if there exists any duplicate? Only 10 MB RAM is available to the system. 167
Q 177. What is a Binary Search Tree? Does Java provide implementation for BST? How do you do in-order,
pre-order and post-order Traversal of its elements? 168
Q 178. What is technique to sort data that is too large to bring into memory ? 169
Q 179. Check if a binary tree is a Binary Search Tree or not? 169
Q 180. How would you convert a sorted integer array to height balanced Binary Search Tree?
Input: Array {1, 2, 3}
Output: A Balanced BST
2
/ \
1 3 170
Q 181. How would you calculate depth of a binary tree? 171
Q 182. Calculate factorial using recursive method. 171
Q 183. How will you swap two numbers using XOR operation? 171
Q 184. You have a mixed pile of N nuts and N bolts and need to quickly find the corresponding pairs of nuts
and bolts. Each nut matches exactly one bolt, and each bolt matches exactly one nut. By fitting a nut and bolt
together, you can see which is bigger. But it is not possible to directly compare two nuts or two bolts. Given an
efficient method for solving the problem. 172
Q 185. Your are give a file with 1 million numbers in it. How would you find the 20 biggest numbers out of this
file?172
Q 186. Reverse the bits of a number and check if the number is palindrome or not? 172
Q 187. How would you mirror a Binary Tree? 173
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 11
Q 188. How to calculate exponentiation of a number using squaring for performance reason? 173
Q 189. How will you implement a Queue from scratch in Java? 175
Q 190. How will you Implement a Stack using the Queue? 176
Q 191. How would you implement a simple Math.random() method for a given range say (1-16)? 177
Q 192. How an elevator decides priority of a given request. Suppose you are in an elevator at 5th floor and one
person presses 7th floor and then 2nd presses 8th floor. which data structure will be helpful to prioritize the
requests? 177
Q 193. How would you multiply a number with 7 using bitwise hacks? 178
Q 194. What is the best way to search an element from a sorted Integer Array? What would be it's time
complexity?178
Q 195. How would you reverse a Singly linked List? 179
Q 196. How would you count word occurrence in a very large file ? How to keep track of top 10 occurring
words?180
Q 197. What is difference between synchronized HashMap and a hashtable? 184
Q 198. What is difference between Iterator and LisIterator? 184
Q 199. What do you understand by Token Bucket Algorithm. What is its use ? 185
Q 200. How will you implement fibonacci series using Iterative & Recursive approach in Java 8 ? 187
Q 201. How will you write a multi-threaded HttpDownloader program using Java 8 ? 190
Q 202. How will you find first non-repeatable character from a String using Java 8 ? 191
Q 203. How will you find Word Frequency in sorted order for a collection of words ? 191
Q 204. How will you calculate MD5 hash of a given String in Java ? 193
Q 205. There is a set of integer values representing the time consumed by a job execution in seconds, how will
you find average execution time ignoring the extreme run times (0 seconds or a value much above the average
execution time) ? 193
Q 206. There are millions of telephone numbers in a country, each state of the country has specific phone
number range assigned to it. How will you determine which state a number belongs to ? 193
Q 207. There is a number series in which subsequent number is either +1 or -1 of previous number. How will
you determine if the range of supplied numbers are contained in this series in minimum time ? 195
Object Oriented Design 196
Q 208. What are the key principles when designing a software for performance efficiency ? 196
Q 209. How would you describe Producer Consumer problem in Java ? What is its significance ? 196
Q 210. How would you implement a Caching for HttpDownloader Task using Decorator Design Pattern ? 200
Q 211. Write Object Oriented design for library management system. 201
Q 212. Design ATM machine. 203
Q 213. Design a web crawler that will crawl for links(urls). 204
Q 214. Design Phone Book for a mobile using TRIE (also known as prefix tree). 208
Q 215. How would you resolve task's inter dependency, just as in maven/ant.
Let's consider the following task dependencies.
Here first row states that task 3 is dependent on task 1 and task 5, and so on. If the two consecutive tasks have no
dependency, then they can be run in any order.
The result should look like - [1, 5, 3, 2 ,4] or [1, 5, 3, 4, 2] 210
Q 216. How would you sort 900 MB of data using 100 MB of RAM ?
What is external sort ? 214
Q 217. How would you design minimum number of platforms so that the buses can be accommodated as per
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 12
their schedule ?
Bus Schedule for a given Platform 217
Q 218. There is a pricing service which connects to Reuters & Bloomberg and fetches the latest price for the
given Instrument Tics. There could be multiple price events for the same Stock and we need to consider the latest
one. Design a service to show prices for the Top 10 stocks of the Day ? 219
Q 219. Design a parking lot where cars and motorcycles can be parked. What data structure to use for finding
free parking spot in Parking Lot program? Assume there are million of parking slots. 222
Q 220. There is three file contains flight data, write a standalone program to search flight detail from all files
depend on criteria ? Write JUnit to demonstrate the working. 223
Q 221. Implement the classes to model two pieces of furniture (Desk and Chair) that can be constructed of
one of two kinds of materials (Steel and Oak). The classes representing every piece of furniture must have a
method getIgnitionPoint() that returns the integer temperature at which its material will combust. The design
must be extensible to allow other pieces of furniture and other materials to be added later. Do not use multiple
inheritance to implement the classes. 229
Q 222. How would you simulate a digital Clock in Object Oriented Programming Language? 231
Q 223. How would you design an elevator system for multi story building? Provide with request scheduling
algorithm & Class diagram for the design. 234
Q 224. Given two log files, each with a billion username (each username appended to the log file), find the
username existing in both documents in the most efficient manner? 234
Q 225. Design DVD renting system, database table, class and interface. 235
Puzzles & Misc 236
Question: What causes a typical developer to switch his/her job so frequent, Is that bad, why that is
not the case in West ?
A thought to switch Job comes to one's mind when one finds blockage in growth opportunities in their current
organization. I could list few reasons for the same -
1. Salary disparity and scope for higher salaries in next Job is the major reason for job switch. Most service
based companies tries to maximize their profit offering lower salaries to its employees (that's beneficial for
freshers who do not have any experience), but as people acquire more skills they switch for bigger roles in
new Job. Demand and supply typically governs the salaries in India.
2. The quality of work is another reason for switch. Work quality directly relates to stress (more manual work
more stress)
3. Shift Timings and location preference also causes people to switch their jobs
To some extent this switch is fair because we can't expect someone to work for a company few thousand
dollars a year for his lifetime (As he acquires skills in parallel to take up more responsibilities). As the Industry
will mature, job shift will reduce. The IT companies in west are mature, salaries are already saturated, people
don't take much work stress, So western employees do not find many reasons for their Job switch.
Question: What is typical psychology of average Indian Developer ? What kind of chaos pollute his
mind ?
Most Indian opt for IT, not by choice but for money, because of large unemployment in India. Moreover earning
Chapter - Introduction Cracking Java Interviews (Java 8, Hibernate & Spring) 14
money in IT industry is easy and effortless compared to other parallel opportunities. Many people wants to
take IT as the jumping ground for their higher studies (MBA, MS, etc). An average fresher is polluted with the
thoughts about his career growth, and is unsure about his key interests in IT field, trying various alternates in
first few years.
Question: What is the Problem with Most Indian Developers in terms of Skills ?
Majority of IT crowd does not have good hold over their primary skills (Technical, Presentation) which are
required for the work. The underlying cause for the low skills are poor quality of education and the type of work
which is fed to Indian Companies. The majority of work does not require high quality of skills on developer's
part. Many people learn by their own, build their skills and fight for better quality work. One should have a very
good hold over his primary skill set and look for work which is matching those skills.
Question: Would it help if I memorize all the questions for cracking interviews?
No, it will not. But memorizing the most common Patterns of software development will definitely help
crack not only the interview but also make your day to day work life easy. A single pattern resolves n number
of problems emerging from that pattern, and we should always look forward finding the patterns instead of
solution to a particular problem.
Question: Why do interviewers ask rocket science questions in interviews even if the new role does
not require any such skills ?
Hiring in IT industry is not regulated by any means, it is solely up to the interviewer to choose the topic for
discussion in the interview. In today's intellectual world, people like intellectual war, and interview is a good
place for that. I do not find any harm by such interview process unless interviewer hides the real picture of work
that one needs to perform after joining the new role. For sure there is one plus point to such interview process
that it will definitely tend to raise our skill set.
Question: Why people take so many offers at the time of Job change, doesn't it add to chaos ?
The main reason for doing so, is the disparity between work and salary across the companies. People feel
insecure at financial level and try their best to grab the most paying Job opportunity, and that's fair from
employee perspective. On the other hand, companies tend to maximize their profit by limiting the salary offer
as per individual's previous company's salary. So it is a game, where both the employer and the employee are
fighting to maximize their own profit. Ultimately, the Demand and Supply equation balances the fight between
employer and the employee. Saturation of salaries and work quality in coming years might hamper this.
Chapter 1
Core Concepts, Spring & Hibernate
Q 1. What are good software practices for developing Scalable, Testable and Main-
tainable Software ?
1. Understand the requirement and the business, asks questions to resolve ambiguities.
2. Follow good software development practices like Agile with Test Driven Development. Agile development
is all about incorporating changes in the software without much pain. TDD helps achieving agility in your
software. A very good test coverage (End to End and Unit Tests) keeps a developer away from last minute
stress at production deployment time.
3. Automate all non-productive mundane tasks related to deployment, e.g. Salt Stack or AIDS for Dev Ops
4. Take a software change request only if it is really required. If there is no value addition to the customer then
don't do it.
5. Keep refactoring your code base time to time, don't leave any duplicate code inside code base. Follow DRY
(don't repeat yourself) strictly. Every object must have a single authoritative representation in the system.
Software development is like the art of gardening where refactoring takes it to a next level.
6. Add an automated test case for every new bug found. Appropriate test assertions are equally important
otherwise it will just reflect on the code coverage without much help.
7. Document interfaces and reasons instead of implementation.
8. Use Profiling Tools to identify bottlenecks of your application. One can use jvisualVM tool bundled in JDK
to know the JVM profile of an application, though there are some commercially available easy to use tools
available in market, e.g. JProfiler
9. Use pair programming when bringing someone new up to speed and when tackling particularly tricky
problems which are hard to KT otherwise. This also leads to smooth landing for the new employees.
10. Use tools to find the duplicates and then refactor to reuse the existing code with better design. IntelliJ is
one of the good tools that will take care of boilerplate stuff (but soon you will become it's luxury addict)
11. Work in small steps with frequent feedback and correction to avoid the last minute surprises (Agile).
12. Continuous Integration environment is must for rapid bug free, coordinated development. Tools like
TeamCity, Hudson, Jenkins, etc are can be leveraged for Continuous Integration.
13. Software development without Art, Fun and Creativity is boring and will bring depression, so be aware of
this warning sign. Don't leave learning, be a student for lifetime!!!
Q 4. Why should I choose Java for Software Development? What are Pros and Cons
of Java 8 ?
Java Pros
1. Java is free, download it and start creating your own applications
2. Plenty of third party libraries, frameworks & IDE for faster development (spring, hibernate, intelliJ, etc)
3. Platform independent, write once run on most modern platform (Unix, Windows, Mac, 32/64 bit Hardware)
4. Supports Object Oriented Programming, easy to model real life scenarios into object model
5. In built support for multi-threading & concurrency, Its easy to write scalable applications in Java that
can utilize multi-core processors, clusters of machine, distributed RAM, etc. There is in built support for
Threads, ForkJoinTask (Work Stealing Algorithm), non-blocking algorithm using CAS, Stream API, Parallel
Streams, CompletableFuture, Parallel Array Operations, Atomic Values, LongAccumulator, etc.
6. Very good support for Internationalization
7. Memory management is automatic by use of garbage collector (G1, Concurrent Mark Sweep, parallel
scavenge garbage collector, etc)
8. Pure Java Byte code running on 32 bit JVM works perfectly fine on 64 bit platform
9. Functional interfaces & lambda expressions introduced in Java 8 makes code writing an easy affair.
Specifically, dealing with Collections is fun in Java 8. For example, if you want to sort a collection of people
with last name, first name and e-mail (ignoring the case for e-mail), then the following code will do it all
Stream<Person> people = Stream.of(new Person(), ...);
people.sorted(Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.thenComparing(Person::getEmail, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER)))
.forEach(System.out::println);
Java Cons
1. Is not a good fit for desktop applications because of heavy memory footprint and huge VM startup time
compared to ay C/C++ written application
2. Normal Java is not good for real time systems because of "stop the world garbage collector pauses".
Please also note that 64 bit JVM requires more memory compared to 32 JVM for the same application
because now each reference starts consuming 64 bit instead of 32 bit i.e. management cost in 64 bit version is
higher than the 32 bit version. However, newer JVMs offer object pointer compression1 techniques which can
significantly reduce the space required by 64 bit JVM.
1 http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 18
Encapsulation
Encapsulation is the mechanism of hiding of data implementation by restricting access to public methods.
Abstraction
Abstract means a concept or an Idea which is not associated with any particular instance. Using abstract class/
interface we express the intent of the class rather than the actual implementation. In a way, one class should
not know the inner details of another in order to use it, just knowing the interfaces should be good enough.
Inheritance
Inheritances expresses "is a" relationship between two objects. Using Inheritance, In derived classes we can
reuse the code of existing super classes.
Polymorphism
It means one name many forms. It is further of two types - static and dynamic. Static polymorphism is achieved
using method overloading and dynamic polymorphism using method overriding.
Q 7. What are the key paradigms for Developing the Clean Object Oriented Code?
1. Program to an Interface (or the Super Type) not the implementation.
2. Interacting Classes should be loosely coupled among themselves.
3. Code should implement tight encapsulation. Use of public and static variables should be avoided
whereever possible, they introduce coupling and make testing of classes tough. Avoid the Singleton Design
pattern whereever possible.
4. Always reuse the code using Inheritance, Composition and Utility Methods. Strictly follow the Do not
Repeat Yourself (DRY) principle.
5. Has-A relationship is better than Is-A relationship because it offer more flexibility, see Decorator Design
Pattern for more details.
6. In case of multi-threaded applications, use immutable objects to represent the state.
7. Make proper use of Design Patterns wherever possible.
8. Use up to date software dependencies & make best use of latest technology available to us.
Developer : What that data looks like and how much is the volume, where is it stored ?
Business Analyst : Data consists of integers, volume could go as high as 4 GB residing in a file. User will
upload the file into the server and should get a sorted file in return.
Developer : What is the range of Numbers that need to be sorted, will there be duplicates ?
Business Analyst : That data will consist of small numbers, all between range of 0 < number < 1 million, but
yes there will be lots of duplicates
Developer : What are the hardware specs for hosting this service ?
Business Analyst : It will be 4 GB RAM, 8-core cpu, 160GB Disk machine, with a cluster of four such
machines
Developer : What are the Time and Space requirements for this service ?
Business Analyst : It should run in minimal time possible and there could be multiple such requests running in
parallel.
So we can see how the requirement evolves after raising the relevant questions. Before asking these
questions developer could have implemented any sorting algorithm for this requirement without keeping in
mind the parallel processing, space requirements, etc.
The Dev team went ahead and provided the asked functionality without introspecting the real business cause
behind this requirement, later on came the real picture -
User actually wanted to manipulate the system data using some macro's in excel sheet and then wanted to
upload the same to the server, if proper questions had been asked the design would be different.
Whatever manipulation user wanted to perform, could have easily be done inside the server using Java
methods itself, so there was no real need for this change request raised by the user.
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 20
In pre modern era, when calculators were not there, logarithm tables were used for division and multiplication
of large astronomical numbers.
Notes
• Logarithm was used in India in ancient times around 2 BC to express astronomical units. It is known as
Laghuganak (लघुगणक) in Hindi.
• Logarithmic spirals are common in nature. Examples include the shell of a nautilus or the arrangement of
seeds on a sunflower.
• The Richter scale measures earthquake intensity on a base 10 logarithmic scale.
• In astronomy, the apparent magnitude measures the brightness of stars logarithmically, since the eye also
responds logarithmically to brightness.
• In Divide and Conquer algorithms (Binary Search, Data Partitioning, etc), the problem set is halved in each
iteration which results in logarithmic Big O (log n) Time Complexity.
1 http://simple.wikipedia.org/wiki/Logarithm
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 21
Q 10. What do you understand by Big O notation, why is it important in software de-
velopment ?
Big O Notation1 is a mechanism used to measure the relative efficiencies of Algorithms in terms of Space and
Time. It makes us understand how execution time & memory requirements of an algorithm grow as a function
of increasing input size. In this notation, O stands for the Order of magnitude.
Constant O(1) - a program whose running time's order of growth is constant, executes a fixed number of
operations to finish the job, thus its running time does not depend on N.
Linear O(N) - a program that spends a constant amount of time processing each piece of input data and thus
running time is proportional to the N.
Logarithmic O(log n) - a program where on every subsequent iteration, the problem size is cut by half, for
example - Binary Search.
Importance of Big O
We should always keep time efficiencies in mind while designing an algorithm for a data structures, otherwise
there could be severe performance penalties for using wrong algorithm for a given scenario.
PriorityQueue
O(1) for peek, element and size
O(log n) for offer, poll, remove() and add
O(n) for remove(Object) & contains(Object)
HashMap & ConcurrentHashMap (with no collisions)
O(1) for get operation
1 http://en.wikipedia.org/wiki/Big_O_notation
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 22
LinkedList
O(1) for removal and O(1) for add & poll method
O(n) for toString() method
Q 11. How would you determine the Time Complexity of a given algorithm, are there
any general guidelines?
There are few rules which can help us in the calculation of overall running time of a given piece of code.
In case of if-else condition, we should include the time complexity of condition and if or else part, whichever is
larger.
2. Iterations and Loops - for, while and do-while (Multiply the Complexity)
Total time complexity can be calculated by multiplying the Time Complexity of individual statement with the
number of iterations. for example, in the below code
Q 12. What is a sorting algorithm ? List down sorting algorithms by their time &
memory complexity in Big O notation ? When do we call a sorting algorithm 'Stable'?
Sorting is an algorithmic technique to put all the collection elements in certain order1 i.e. numerical order,
lexicographical order (dictionary order), etc. Sorting is very helpful for solving real world problems for example,
data analysis requires searching which depends upon sorted input data.
Now there are two solution possible for the first two elements
1 http://en.wikipedia.org/wiki/Sorting_algorithm
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 24
OUTPUT1 --> [(1,2) (1,3) (2,3) (3,1)] --> stable sort because order is maintained
OUTPUT2 --> [(1,3) (1,2) (2,3) (3,1)] --> unstable sort because order changed from the original
Examples of Stable Sort algorithms are : Binary Tree Sort, Bubble Sort, Merge Sort, Insertion Sort, etc
Unstable Sorting Algorithms : Heap Sort, Selection Sort, Quick Sort
5. Adaptive Sort
An algorithm is called adaptive if it takes advantage of existing order in its input thereby reducing the overall
sorting time. Adaptive versions exists for heap and merge sort. For example, Java 8's iterative merge sort
method is adaptive to an extent that it requires approximately n comparisons if the input is nearly sorted.
Algorithms Summary
Below table assumes total n items to be sorted, with keys of size k, digit size d and range of numbers r
Algorithm Average Time Worst Time Space Stable Comparison Suitable for
Complexity Complexity Complexity Based ? Memory
Quicksort O (n log n) n2 log n No Yes Internal
Binary Tree Sort O (n log n) n log n n Yes Yes Internal
Merge Sort O (n log n) n log n n Yes Yes External
Selection Sort O (n2) n2 1 (In Place) No Yes Internal
Bubble Sort O (n2) n2 1 (In Place) Yes Yes Internal
Heap Sort O (n log n) n log n 1 (In Place) No Yes Internal
Insertion Sort O (n2) n2 1 (In Place) Yes Yes Internal
Radix Sort O n.(k/d) n.(k/d) n+2d No No External
Counting Sort O (n+r) n+r n+r Yes No Internal
Question: Do you know what Sorting algorithm JDK uses for Java's Collections.sort(List<E>) method?
Java 8's Collections.sort(List<E>) uses Iterative merge sort algorithm, it requires fewer than n log(n)
comparisons when the input array is partially sorted (adaptive) and this algorithm is guaranteed to be stable in
nature.
5. Multiple Sort Criteria - Sort employees by first name and then by last name and print output to console
public void multiple_sort(List<Employee> employees) {
Comparator<Employee> byFirstName = (e1, e2) -> e1.getFirstName().compareTo(e2.getFirstName());
Comparator<Employee> byLastName = (e1, e2) -> e1.getLastName().compareTo(e2.getLastName());
employees.stream()
.sorted(byFirstName.thenComparing(byLastName))
.forEach(e -> System.out.println(e));
}
Sorted Output 1 1 2 2 4 5 6
Java 8 example for Counting Sort
import java.util.Random;
public class CountingSort {
public static void main(String[] args) {
Random random = new Random(System.currentTimeMillis());
int min = 0;
int max = 1000;
int[] input = random.ints(min, max).parallel().limit(100000000).toArray();
CountingSort countingSort = new CountingSort();
countingSort.sort(input, min, max);
}
//Compute the total number of items occurring before the current item in sorted output (histogram)
for (int i = 1; i < counting.length; i++) {
counting[i] += counting[i - 1];
}
//Fill the output array with correct number of zeros, ones, twos and so on.
int[] output = new int[input.length];
for (int i : input) {
output[counting[i - min] - 1] = i;
--counting[i - min];
}
return output;
}
Layman usage in real life - A shopkeeper wants to sort the receipts at the year end from a box, he will simply
take a calendar and start putting receipts against the dates.
int current = 0;
for (int i = 0; i < counts.length; i++) {
Arrays.fill(a, current, current + counts[i], i + low); // fills counts[i] elements of value i + low in current
current += counts[i]; // leap forward by counts[i] steps
}
}
Note: we know that, given an array of integers, its maximum and minimum values can be always found; but if
we imagine the worst case for an array of 32 bit integers, we see that in order to hold the counts, we need an
array of 232 elements, i.e., we need, to hold a count value up to 232-1, more or less 4 Gbytes. So the counting
sort is more practical when the range is (very) limited and minimum and maximum values are known a priori.
(Anyway sparse arrays may limit the impact of the memory usage)
Bucket Sort Algorithm (Integer Sort with Time Complexity O (n) + distributed algorithm)
It is a distribution sort algorithm that works by partitioning (divide and conquer) an array into a number of
buckets, with each bucket sorted individually on the same machine or another using a different sorting
algorithm or by applying the same algorithm recursively.
If the number of buckets can't be made equal to the max value in the input data, then we can use the below
modified algorithm to sort the input data
public static int[] bucketSort(int[] array, int bucketCount) {
if (bucketCount <= 0) throw new IllegalArgumentException("Invalid bucket count");
if (array.length <= 1) return array; //trivially sorted
int pointer = 0;
for (int i = 0; i < buckets.length; i++) {
Collections.sort(buckets[i]); //mergeSort
for (int j = 0; j < buckets[i].size(); j++) { //merge the buckets
array[pointer] = buckets[i].get(j);
pointer++;
}
}
return array;
}
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 29
Q 13. Why Prime Numbers are given much importance in writing certain algorithms
like hashcode()?
Prime numbers are very useful for generating hashcode, RSA algorithms, random number generators.
String class's hashcode method multiplies its hash value by prime number 31 :
int hash =0;
for (char ch : str.toCharArray()) {
hash = 31 * hash + ch;
}
A number is either prime number or a composite number (can be factorized into prime numbers). Prime
numbers are always unique and can not be divided by any other number except 1. The product of prime
number with any other number has the best chances of being unique (though not as unique as Prime number
itself) due to the fact that prime number is used to compose it. This property makes them very suitable for use
in hashing function so as to obtain fair distribution in its hashcode output and thus achieving low collisions.
Multiplying by the prime number will not tend to shift information away from the low end, as it would multiplying
by a power of 2, thus achieving a fair randomness.
Q 14. What is left shift <<, right shift >> and Unsigned right shift >>> operator in
Java? How are these useful?
All Integer in Java are of signed type (negative numbers are represented in 2's complementary notation),
hence Java provides both signed and unsigned bit shift operators to support signed and unsigned shift of bits.
00000101 << by 3
00101000
It shifts the underlying bits of an integer to left by the given distance filling the right most bits with zero always.
X = a << b means the same as X = a*2^b
a is given Number and b is the shift amount.
Here is an example of 8 bit representation of number 5. and when we left shift it's bit by 3 then the right most 3
bits are filled by zero.
And the number becomes
5*23 = 40.
The same thing happens for negative numbers which are represented in 2's complementary notation. for
example -5 becomes -40 as follow
11111011 becomes 11011000
00101000 >> by 3
00000101
Shifts the bits to left by specified amount maintaining the sign of underlying integer i.e.
It fills the left most bits with 0 if the number is positive otherwise with bit 1.
X = a >> b means same as arithmetic operation X = a / (2b)
Unsigned right shift Operator >>> (does not respect sign of Number, does not preserve the 1st bit)
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 30
Unsigned right shift operator >>> is effectively same as >> except that it is unsigned, it fills the left most
Notes
• Eight-bit type byte is promoted to int in shift-expressions. To mitigate such effects we can use bit masking
to get the result as byte for example, (b & 0xFF) >>> 2. Casting can also help achieving the same.
• Uses of bitwise operators: bitwise operators are used for few very efficient mathematical calculations
in Big O(1). Bloom Filter, fast mathematical calculations, hashing functions of HashMap are some of
applications.
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 31
The two's-complement system has the advantage that the fundamental arithmetic operations of addition,
subtraction, and multiplication are identical to those for unsigned binary numbers (as long as the inputs are
represented in the same number of bits and any overflow beyond those bits is discarded from the result).
This property makes the system both simpler to implement and capable of easily handling higher precision
arithmetic. Also, zero has only a single representation, obviating the subtleties associated with negative zero,
which exists in ones'-complement systems.
Positive numbers are represented as the ordinary binary representation in 2's complementary notation.
The most significant bit (leftmost bit) is always 0 for positive number, otherwise number is negative.
To get 2's complement of a negative numbers, the bits are inverted (using bitwise NOT operator) and then
value of 1 is added to get the final result.
That is +5.
1 http://en.wikipedia.org/wiki/Two's_complement
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 32
Q 16. How Heap space is divided in Java. How does Garbage Collector cleans up the
unused Objects ? Why shouldn't we use System.gc() command in production code?
Memory taken up by the JVM is divided into Stack, Heap and Non Heap memory areas. Stacks are taken up
by individual threads for running the method code while heap is used to hold all class instances and arrays
created using new operation. Non-heap memory includes a method area shared among all threads and is
logically part of the heap but, depending upon the implementation, a Java VM may not invoke GC on this part.
The Young generation - This further consists of one Eden Space and two survivor spaces. The VM initially
assigns all objects to Eden space, and most objects die there. When VM performs a minor GC, it moves any
remaining objects from the Eden space to one of the survivor spaces.
Tenured/Old Generation - VM moves objects that live long enough in the survivor spaces to the "tenured"
space in the old generation. When the tenured generation fills up, there is a full GC that is often much slower
because it involves all live objects.
Metaspace - The metaspace holds all the reflective data of the virtual machine itself, such as class metadata,
classloader related data. Garbage collection of the dead classes and classloaders is triggered once the class
metadata usage reaches the “MaxMetaspaceSize”.
to collect the space from Young Generation First (very low performance overhead), but when we force our JVM
to invoke System.gc(), JVM will do a Full GC which might pause your application for certain amount of time,
isn't that a bad approach then ? Let GC decide its timing.
Memory Spaces
Eden Space (heap): The pool from which memory is initially allocated for most objects.
Survivor Space (heap): The pool containing objects that have survived the garbage collection of the Eden
space.
Tenured/Old Generation (heap): The pool containing objects that have existed for some time in the survivor
space.
Metaspace (non-heap): The pool containing all the reflective data of the virtual machine itself, such as
meta-data of classes, objects (e.g pointers into the heap where objects are allocated) and method objects,
classloader related data.
Code Cache (non-heap): The HotSpot Java VM also includes a code cache, containing memory that is used
for compilation and storage of native code.
-XX:+DisableExplicitGC
Disable Sysytem.gc() which cause the Full GC to run and thus causing the JVM pauses.
-verbose:gc
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
This will print every GC details
-XX:NewRatio
The ratio between the young space and the old is set by this parameter. For example, -XX:NewRatio=2,
would make old generation 2 times bigger than the young generation (ratio between the young and tenured
generation is 1:2), or we can say that the young generation is 1/3rd the size of total heap size(young + old)
-XX:SurvivorRatio
This command line parameter sets the ratio between each survivor space and eden. For example,
-XX:SurvivorRatio=6 will make each survivor space one eighth of the young generation. (there are two survivor
space and 6 eden spaces in this case, hence 1/8)
-XX:NewSize=n
Sets the initial size of young generation, it should typically be 1/4th of total heap size. The bigger the young
generation, the less frequent the minor collection happens. (though for a bounded heap size, it may cause
more frequent major collections)
-XX:MaxMetaspaceSize=128m
2 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#generation_sizing.young_gen.survivors
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 34
Sets the maximum metaspace size (non-heap) to 128 MB which stores Classes, methods and other metadata.
We should carefully design the object pool because they fool the garbage collector by keeping the live
reference to the unused objects, thus causing application to demand more memory.
Default Values as of JDK 1.6 on server VM
Notes
Question: We have a application which creates millions of temporary large StringBuilder Objects from
multiple threads. But none of such object is really required after extracting useful information from
them. Somehow we started facing frequent gc pauses. What could be the problem, and how would you
approach it?
Solution
Performance tuning GC may solve this problem to some extent. Let's first understand memory requirements
of this application. This application create lots of short lived objects - thus we would require a large young
generation for lowering the frequency of minor garbage collection. If our young generation is small, then the
short lived objects will be promoted to Tenured Generation and thus causing frequent major collection. This can
be addressed by setting appropriate value for -XX:NewSize parameter at the JVM startup.
We also need to adjust the survivor ratio so that the eden space is large compared to survivor space, large
value of Survivor ratio should help solve this problem.
We can also try increasing the Heap size if we have sufficient memory installed on our computer.
Question : What are the available tools to give the visual view of the different memory spaces in a
3 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#generation_sizing.young_gen.survivors
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 35
running JVM ?
There are lot of free tools available for troubleshooting memory related problem in a JVM. JConsole and
JVisualVM are two of them that come shipped with every JDK. Below is the screenshot of JVisualVM (with
Visual GC plugin) showing the visual representation of the different memory segments for a running JVM.
You can always profile an application and see the memory trends and customize the memory allocations
accordingly. That can significantly reduce GC overhead and thus improve the application performance.
How do you interpret GC log message , like the one shown below ?
8109.128: [GC [PSYoungGen: 109881K->14201K(139914K)] 691015K->595352K(1119040K), 0.0454530
secs]
• 107Mb used before GC, 14Mb used after GC, max young generation size 137Mb
• 675Mb heap used before GC, 581Mb heap used after GC, 1Gb max heap size
• minor GC occurred 8109.128 seconds since the start of the JVM and took 0.04 seconds
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 36
Q 17. What is difference between Stack and Heap area of JVM Memory? What is
stored inside a stack and what goes into heap?
The biggest difference between Heap and Stack section of memory is the lifecycle of the objects that reside in
these two memory locations
Memory of Stack Section is bound to a method context and is destroyed once a thread returns from the
function i.e. the Stack objects exists within the scope of the function they are created in.
On the other hand Heap objects exists outside the method scope and are available till GC recollects the
memory.
Java stores all objects in Heap weather they are created from within a method or class. Escape analysis can
be enabled in compiler to hint JVM to create method local objects in stack if the objects does not escape the
method context. All class level variables and references are also stored in heap so that they can be accessed
from anywhere. Metadata of classes, methods, etc also reside in Heap's PermGen space.
The Stack section of memory contains methods, local variables and reference variables and all os these are
cleared when a thread returns from the method call.
Question: An ArrayList is created inside a method, will it be allocated in Stack section or Heap section
of JVM Memory?
public void foo(){
ArrayList<String> myList = new ArrayList<>();
}
Answer : All Java Objects are created in Heap memory section, so the ArrayList will be created on the heap.
But the local reference (myList) will be created in the Stack section of memory. Once the method call is finished
and if myList variable is not escaped from this method then GC will collect the ArrayList object from heap.
As of JDK 1.6_14, escape analysis1 can be enabled by setting the appropriate JVM flag (java
-XX:+DoEscapeAnalysis) which hints the compiler to convert heap allocations to stack allocations if the method
local objects do not escape the method scope.
In the following code, if we enable the escape analysis, then the Object Foo may be created on Stack, resulting
in significant performance gain due to lesser GC activity.
1 http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 37
Q 18. What is a Binary Tree? Where and why is this used in Java Programs?
Binary Tree is a tree data structure made up of nodes. Each node has utmost two children.
Why to prefer Binary Tree over any other linear data structure ?
Binary trees are a very good candidate (not the best) for storing data when faster search/retrieval is required
based on certain criteria. It does so by storing its elements in sorted order offering low time complexity for
retrieval operations compared to any other linear data structure. Any un-sorted collection can be inserted into
Binary Search Tree in O (n log n) time complexity. Though the insertion time is increased per element from
O(1) in Random Access array to O(log n) in Binary Search Tree, but we get a major advantage when we want
to search/retrieve a particular element from the tree data structure.
Worst-case Search time complexity is logarithmic in a balanced Binary Search Tree i.e. Binary tree cuts
down the problem size by half upon every subsequent iteration.
Red-black-tree is a height balanced binary tree where root is colored black and every other element is colored
either black or red with the following two rules,
1. If an element is colored red, none of its children can be colored red.
2. The number of black elements is the same in all paths from the root to the element with one child or with no
children.
It is useful for maintaining the order of elements in the collection based on the given comparator. It also provide
efficient mechanism to find the neighboring elements which are either big or small compared to given number,
because those numbers are stored physically closer in the data structure.
TreeSet is a navigable set implementation based on TreeMap. All the elements are ordered using their Natural
ordering or by comparator provided at TreeSet construction time.
NavigableSet provides us with methods like first(), last(), floor(), ceiling(), headSet(), tailSet() which can be
used to search the neighboring elements based on element's ordering.
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 38
TreeMap is Red-Black Binary Search Tree which guarantees logarithmic time for insertion, removal and
searching of an element. All the elements in this collection are stored in sorted order and the tree is height
balanced using Red black algorithm. If two elements are nearby in order, then TreeSet places them closely in
the data structure.
Uses
It is a best collection if we need to search the nearby elements of a given item based on their ordering.
Notes
• Note that this implementation is not synchronized. If multiple threads access a tree set concurrently, and at
least one of the threads modifies the set, it must be synchronized externally. This is typically accomplished
by synchronizing on some object that naturally encapsulates the set.
• If no such object exists, the set should be "wrapped" using the Collections.synchronizedSortedSet method.
This is best done at creation time, to prevent accidental unsynchronized access to the set:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
• If we are looking for high throughput in a multi-threaded application then we can prefer
ConcurrentSkipListSet which is scalable concurrent implementation of NavigableSet.
• Iterator returned by this class are fail-fast.
• TreeSet does not allow duplicates, it just replaces the old entry with the new one if both are equal (using
compareTo method)
• TreeSet does not preserve the insertion order of its elements.
• TreeSet provides guaranteed Big O (log n) time complexity for add(), remove() and contains() method.
There are multiple ways to handle session by a server framework. Most often, server uses one of the following
three mechanisms to handle session on server side -
Servlets use cookies as the default mechanism for session tracking, but in case cookies are disabled on the
client, Server can use URL re-writing for achieving the same. When server calls request.getSession(true), then
server generates and sends JSESSIONID back to the client for all future session references. JSESSIONID will
then be stored by the client and sent back to the server using any of the above mentioned mechanisms.
To ensure that your Servlets support servers that use URL rewriting to track sessions, you must pass all the
URL's used in your servlet through the HttpServletResponse.encodeURL() method, as shown below
Q 22. How can one handle relative context path while coding the web applications?
For example, your web application may be deployed at a different context path in
Tomcat, how will you make sure static/dynamic resources works well at custom
context path ?
static/images/a.gif
../static/images/a.gif
JSP EL
One can use pageContext variable available in session scope. Request contains contextPath variable which
points to the actual context path assigned to web application at the time of deployment.
${pageContext.request.contextPath}
In Freemarker
In your view resolver you can add the following property (mvc-dispatcher.xml)
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
<property name="requestContextAttribute" value="rc"/>
</bean>
Then in your freemarker template you can get the request context patch like
${rc.getContextPath()}
or, simply as
${rc.contextPath}
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 41
Q 24. How many elements a complete binary tree could hold for a depth of 10?
A binary tree is said to be complete if it is fully populated, so that each node has two child except the child
nodes.
From the figure shown, we can conclude that maximum
Nodes at level 0 = 1
Nodes at level 1 = 2
Nodes at level 2 = 4
Nodes at level n = 2n
Total Number of nodes in a tree with depth 10 will be = 210 -1 = 1023 nodes
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 42
Q 25. Explain working of a hashing data structure, for example HashMap in Java.
HashMap is a hashing data structure which utilizes object's hashcode to place that object inside map. It
provides best case time complexity of O(1) for insertion and retrieval of an object. So it is a best suited data
structure where we want to store a key-value pair which later on can retrieved in minimum time.
HashMap is not a thread safe ADT, so we should provide necessary synchronization if used in multi-threaded
environment.
HashMap is basically an array of buckets where each bucket uses linked list to hold elements.
Initial Capacity
The default initial capacity of a hashmap is 16 (the number of buckets) and it is always expressed in power of
two (2,4,8,16, etc) reaching maximum of 1 << 30 (230)
bucket index = hashcode % (number of buckets) index =0 index=1 index = ... index=N
In Java 1.8, A ConcurrentHashMap is a hashmap supporting full concurrency of retrieval via volatile reads of
segments and tables without locking, and adjustable expected concurrency for updates. All the operations
in this class are thread-safe, although the retrieval operations does not depend on locking mechanism
(non-blocking). And there is not any support for locking the entire table, in a way that prevents all access.
The allowed concurrency among update operations is guided by the optional concurrencyLevel constructor
argument (default is 16), which is used as a hint for internal sizing.
ConcurrentHashMap is similar in implementation to that of HashMap, with resizable array of hash buckets,
each consisting of List of HashEntry elements. Instead of a single collection lock, ConcurrentHashMap uses a
fixed pool of locks that form a partition over the collection of buckets.
HashEntry class takes advantage of final and volatile variables to reflect the changes to other threads without
acquiring the expensive lock for read operations.
The table inside ConcurrentHashMap is divided among Segments (which extends Reentrant Lock), each
of which itself is a concurrently readable hash table. Each segment requires uses single lock to consistently
update its elements flushing all the changes to main memory.
put() method holds the bucket lock for the duration of its execution and doesn't necessarily block other threads
from calling get() operations on the map. It firstly searches the appropriate hash chain for the given key and if
found, then it simply updates the volatile value field. Otherwise it creates a new HashEntry object and inserts it
at the head of the list.
Iterator returned by the ConcurrentHashMap is fail-safe but weakly consistent. keySet().iterator() returns
the iterator for the set of hash keys backed by the original map. The 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.
Re-sizing happens dynamically inside the map whenever required in order to maintain an upper bound on hash
collision. Increase in number of buckets leads to rehashing the existing values. This is achieved by recursively
acquiring lock over each bucket and then rehashing the elements from each bucket to new larger hash table.
Question: Can two threads read simultaneously from the same segment in ConcurrentHashMap ?
Answer: Segments maintain table of entry list that are always kept in consistent state, thus many threads
can read from the same Segment in parallel via volatile read access. Even the updates operations (put and
remove) may overlap with the retrieval operation without any blocking happening.
All these methods make concurrent programming a lot simpler than before, for example
• The below statement will conditionally create a new LongAdder() objects if none existed against the given
word and then increment the counter by One.
map.putIfAbsent(word, new LongAdder());
map.get(word).increment();
• The blow statement will print the entire key-value pair from the Hashmap (threshold is parallelism threshold
number beyond which multiple threads will execute the given operation)
map.forEach(threshold, (k, v) -> System.out.println(k + "->" + v));
• The below code snippet will increment the counter by one initializing to one if it is null
map.compute(word, (k, v) -> v == null ? 1: v+1);
• The below code snippet will search for the first match where value is greater than 100, returning null if
nothing found
String result = map.search(threshold, (k, v) -> v > 100 ? k : null) ;
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 45
• The below code snippet will count entries that have value > 100
Long count = map.reduceValues(threshold, v -> v > 100 ? 1L : null, Long::sum);
Q 27. Why do we need Reader Classes when we already have Streams Classes? What
are the benefit of using a Reader over a stream, in what scenario one should be pre-
ferred.
InputStream and OutputStream operates at byte level (also called byte streams) while Reader and Writer
classes operates at the character level (char streams). Reader class is essentially a wrapper over InputStream
where it delegates the I/O related work to the byte stream and performs the translation of byte to character
using the given character encoding and character set. So Reader class provides a easy mechanism to the
developer to deal with the Character stream with an option to deal with different CharacterSets.
It is possible to convert byte stream to a character stream using InputStreamReader and OutputStreamWriter.
Convert Unicode Characters (from String object) to non-Unicode bytes using below code
Q 28. Discuss Visitor, Template, Decorator, Strategy, Observer and Facade Design
Patterns?
Similarly
Calculating taxes in different regions on sets of invoices would require many different variations of calculation
logic. Implementing a visitor allows the logic to be de-coupled from the invoices and line items. This allows
the hierarchy of items to be visited by calculation code that can then apply the proper rates for the region.
Changing regions is as simple as substituting a different visitor.
continued on 47
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 47
@Override
public void visit(Employee emp) {
System.out.println(emp.getName());
}
}
@Override
public void accept(EmployeeVisitor visitor){
for (Employee employee : employees) {
visitor.visit(employee);
}
}
}
continued on 48
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 48
Context Strategy
<<Interface>>
ConcreteStrategyA ConcreteStrategyB
<<Implementation>> <<Implementation>>
Another good example of facade design pattern could be : exposing a set of functionalities using web services
(SOA architecture). Client does not need to worry about the complex dependencies of the underlying system
after building such API.
Q 29. What is a strong, soft, weak and Phantom reference in Java? Where are these
used?
Skills Set - in depth understanding for GC, automatic memory allocation and de-allocation, LRU Cache, etc
SoftReference, WeakReference & PhantomReference are are reference-object classes, which supports limited
degree of interaction with the GC. A programmer may use these classes to maintain a reference to some other
object (referent) in such a way that the object may still be reclaimed by GC.
Reference Queues
Reference queue is used to track the objects claimed by GC. We can use the reference objects to check
whether the objects referred by these are still active or are claimed by GC.
SoftReference
If the strongest reference to an object is a soft reference then GC will not reclaim the object until the JVM is
falling short of memory, though it must be reclaimed before throwing an Out Of Memory Error. So the object will
stay longer than a weakly referenced object. It is mostly used for writing memory sensitive caches.
WeakReference
Is similar to soft reference with the only difference that it will be GC'ed in the next GC cycle if the strongest
reference to the object is a weak reference. When a weak reference has been created with an associated
reference queue and the referent becomes a candidate for GC, the reference object (not the referent) is
enqueued on the reference queue after the reference is cleared. The application can then retrieve the
reference from the reference queue and learn that the referent has been collected so it can perform associated
cleanup activities, such as expunging the entries for objects that have fallen out of a weak collection.
WeakHashMap
It is a HashMap that store its keys (not values) using WeakReferences. An entry in this continued on 49
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 49
map is automatically removed when there is no other non-weak references to keys. This collection can be used
to store associative objects like transient object & its metadata, as soon as the object is claimed by the GC,
the associated metadata will also be removed by the map. Other application could be in a servlet environment
where as soon as the session expire's, clear all the session data/attributes.
PhantomReference
PhantomReference are garbage collected when the strongest reference to an object is a phantom. When an
object is phantomly reachable, the object is already finalized but not yet reclaimed, so the GC enqueues it in
a reference queue for post finalization processing. A Phantom Reference is not automatically cleared when it
is enqueued., so we must remember to call its clear() method or to allow phantom reference object itself to be
garbage collected. get() method always return null so as not to allow resurrect the referent object.
Phantom references are safe way to know an object has been removed from memory and could be thought of
as a substitute for finalize() method.
Automatically-cleared references
Soft and weak references are automatically cleared by the collector before being added to the queues with
which they are registered, if any. Therefore soft and weak references need not be registered with a queue
in order to be useful, while phantom references do. An object that is reachable via phantom references will
remain so until all such references are cleared or themselves become unreachable.
Reachability levels from strongest to weakest : strong, soft, weak, phantom. Java 6 docs states that -
• An object is strongly reachable if it can be reached by some thread without traversing any reference
objects. A newly-created object is strongly reachable by the thread that created it.
• An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
• An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing
a weak reference. When the weak references to a weakly-reachable object are cleared, the object
becomes eligible for finalization.
• An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized,
and some phantom reference refers to it.
• Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of
the above ways.
Notes
WeakHashMap is not a solution for implementing cache, SoftReference's could be better utilized for
implementing cache.
Applications of a WeakHashMap
WeakHashMap stores its keys using WeakReference, and can be used to map transient objects with their
metadata. Let's suppose we have a socket application which creates sockets on client's request and socket
lives there for sometime. Now if we want to associate some metadata with this socket such as identity of
the user, then WeakHashMap is a ideal container for storing such associative information. Since we are not
managing the lifecycle of the socket in this case, WeakHashMap will automatically remove all the metadata as
soon as the socket dies.
Applications of SoftReference
Soft references can be used to build memory sensitive cache which automatically collects items as soon as the
cache is under high memory load, which otherwise has to be achieved by the programmer.
Chapter - Concepts Cracking Java Interviews (Java 8, Hibernate & Spring) 50
Dirty Read
Occurs when uncommitted results of one transaction are made visible to another transaction.
Unrepeatable Reads
Occurs when the subsequent reads of same data by a transaction results in seeing different values.
Phantom Reads
One transaction performs a query returning multiple rows, and later executing the same query again sees
some additional rows that were not present the first time.
We also call above three as Isolation Hazards, and the Transaction Isolation levels are related to these three
problems.
Isolation Level Dirty read Unrepeatable read Phantom read
Read Uncommitted Yes Yes Yes
Read Committed No Yes Yes
Repeatable Read No No Yes
Serializable No No No
For most of databases, the default Transaction Isolation Level is Read Committed.
(Read Committed does not see any inconsistent state of other transaction, with a fair amount of concurrency)
READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by
other transactions. This constraint is very relaxed in what matters to transactional concurrency but it may lead
to some issues like dirty reads.
READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other
transactions. But the repeated read within the same transaction may get different results.
REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple
times the result of all those reading operations must always be the same. This eliminates both the dirty read
and the non-repeatable read issues.
SERIALIZABLE isolation level is the most restrictive of all isolation levels. Transactions are executed with
locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.
This leads to a scenario where none of the issues mentioned above may occur, but in the other way we don't
allow transaction concurrency and consequently introduce a performance penalty.
Please be noted that the above four isolation levels are in decreasing order of their concurrency. So for
scalability reasons, Serializable is rarely a good choice of design, as it offers only a single thread to work at a
given time.
Click Here To Buy