I’ve recently attended some pre-interview Java tests here in Sydney and have been challenged with some of the following Java interview questions. I will be honest, they were not easy (especially since I’ve worked on PHP a lot more in the last couple of years, feel free to view my online resume). But doing these tests have been a good way of reviewing some fundamental Java concepts and here I’ll be compiling a list of some questions that I can remember – hopefully they will come in useful to you – feel free to suggest any more to the comments section below!
What Is The Difference Between A HashMap And A HashTable?
Both collections can store key-value pairs, but there are some key differences:
- A HashMap is not synchronized, while a HashTable is synchronized. A HashTable is therefore thread-safe which means that only one thread can modify a HashTable at any point in time. The thread will need to obtain a lock on the object first, which prevents other threads from accessing it. Note that Java also has a ConcurrentHashMap which provides higher scalability as an alternative to HashTable.
- HashMap allows null values for it’s keys and values. HashTable doesn’t.
- The Iterator in HashMap is fail-fast while HashTable uses an Enumerator which is not fail-fast and will throw an Exception.
- If used in a single-threaded environment, HashMap outperforms HashTable.
- HashMap does not guarantee that the order of the map will remain constant during runtime.
While we’re on the topic of hashy things like maps and tables, another common interview/test question to consider is regarding hashCode().
Notes on hashCode()
To make any newly-created class work correctly with hash-based collections (e.g. HashMap, HashSet), all hashCode implementations must stick to a simple contract. This contract stipulates that:
- Objects that are equal must have the same hash code within a running process
- Unequal objects do not necessarily have different hash codes
- Objects with the same hash code are not necessarily equal
For further reading, see this interesting article on hash codes.
Threading deadlock occurs in the following scenario: Thread A holds lock L and tries to acquire lock M, but at the same time thread B holds lock M and tries to acquire lock L – both threads will wait forever. This is a simple case of deadlock (deadly embrace) where multiple threats wait forever due to a cyclic locking dependency. Whereas databases are designed to deal with this situation, the JVM doesn’t deal with it easily and the usual result is that the application will stall or significantly lose performance (depending on what those threads were doing). Let’s look at how this occurs with the following illustration: In the figure above, deadlock has occurred because the two threads attempted to acquire the locks in a different order. If they asked for the locks in the same order, there would be no cyclic locking dependency and therefore no deadlock. This brings us to an important cautionary concept:
A program will be free of lock-ordering deadlocks if all threads acquire the locks they need in a fixed global order.
For further reading on how to programmatically achieve this (not exactly trivial), see here.