1. How does HashMap work internally in Java?
Answer:
HashMap in Java uses an array of nodes (buckets) to store key-value pairs. Each bucket is a linked list or a red-black tree if the list grows too long (threshold is 8). The key's hashCode is used to determine the bucket index. If multiple keys map to the same bucket (collision), they are stored in a linked list or tree at that index. When retrieving a value, the hashCode and equals method are used to find the exact key-value pair.
Example:
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
System.out.println(map.get("one")); // Output: 1
2. What are the differences between ArrayList and LinkedList?
Answer:
- Underlying Data Structure:
ArrayListuses a dynamic array, whileLinkedListuses a doubly linked list. - Access Time:
ArrayListprovides constant-time access for get and set operations (O(1)), whileLinkedListprovides linear-time access (O(n)). - Insertion/Deletion:
LinkedListis better for frequent insertions and deletions (O(1)for add/remove) in the middle of the list, whereasArrayListrequires shifting elements (O(n)). - Memory Overhead:
LinkedListuses more memory due to storing references to the previous and next elements.
Example:
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
3. Explain the difference between HashSet and TreeSet.
Answer:
- Ordering:
HashSetdoes not maintain any order of elements, whileTreeSetmaintains elements in a sorted (natural ordering or specified comparator) order. - Performance:
HashSetoffers constant time (O(1)) performance for basic operations like add, remove, and contains.TreeSetoffers log-time (O(log n)) performance. - Implementation:
HashSetis backed by aHashMap, whileTreeSetis backed by aTreeMap.
Example:
Set<String> hashSet = new HashSet<>();
Set<String> treeSet = new TreeSet<>();
hashSet.add("b");
hashSet.add("a");
treeSet.add("b");
treeSet.add("a");
System.out.println(hashSet); // Output might be [a, b] or [b, a]
System.out.println(treeSet); // Output: [a, b]
4. How does ConcurrentHashMap achieve thread safety?
Answer:
ConcurrentHashMap achieves thread safety through a combination of lock striping and concurrent techniques. It divides the map into segments (by default 16), each with its own lock. This reduces contention by allowing multiple threads to operate on different segments concurrently. For finer-grained locking, it uses a non-blocking algorithm with volatile variables and CAS (Compare-And-Swap) operations.
Example:
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("one", 1);
concurrentMap.put("two", 2);
System.out.println(concurrentMap.get("one")); // Output: 1
5. What are weak references and how are they used in WeakHashMap?
Answer:
Weak references allow objects to be collected by the garbage collector if they are not strongly reachable. WeakHashMap uses weak references for its keys, meaning that if a key is no longer referenced elsewhere, it can be garbage collected, and the corresponding entry will be removed from the map.
Example:
Map<String, String> weakHashMap = new WeakHashMap<>();
String key = new String("key");
String value = "value";
weakHashMap.put(key, value);
System.out.println(weakHashMap); // Output: {key=value}
key = null; // Making key eligible for garbage collection
System.gc(); // Suggesting JVM to run GC
System.out.println(weakHashMap); // Output might be {} after GC
6. What is the difference between synchronizedList and CopyOnWriteArrayList?
Answer:
synchronizedList: Returns a synchronized (thread-safe) list backed by the specified list. All operations on the returned list are synchronized. Performance can degrade due to the cost of synchronization.List<String> list = Collections.synchronizedList(new ArrayList<>());CopyOnWriteArrayList: Creates a new copy of the list for each write operation (add, set, etc.). It is best suited for scenarios where read operations are more frequent than write operations, as read operations do not require locking.List<String> list = new CopyOnWriteArrayList<>();
7. How does PriorityQueue work in Java?
Answer:
PriorityQueue is a queue data structure that orders elements according to their natural ordering or by a comparator provided at queue construction time. It uses a binary heap to store elements. The head of the queue is the least element with respect to the specified ordering.
Example:
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.add(10);
pq.add(20);
pq.add(15);
System.out.println(pq.peek()); // Output: 10
System.out.println(pq.poll()); // Output: 10
System.out.println(pq.poll()); // Output: 15
8. What are the differences between Iterator and ListIterator?
Answer:
Iterator: Can iterate over a collection in one direction (forward) and can remove elements during iteration.ListIterator: ExtendsIteratorand adds functionalities such as bidirectional traversal (forward and backward), and ability to modify elements during iteration.
Example:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
System.out.println(listIterator.next()); // Forward iteration
}
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previous()); // Backward iteration
}
9. How does EnumSet work in Java?
Answer:
EnumSet is a specialized Set implementation for use with enum types. It is highly efficient because it internally uses bit vectors, making it extremely fast for operations like add, remove, and contains. EnumSet is ordered by the natural order of the enum values.
Example:
enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
System.out.println(weekend); // Output: [SATURDAY, SUNDAY]
10. What is the difference between Comparable and Comparator?
Answer:
Comparable: Used to define the natural ordering of objects. The class itself must implement theComparableinterface and override thecompareTomethod.class Person implements Comparable<Person> { String name; int age; @Override public int compareTo(Person other) { return this.age - other.age; } }Comparator: Used to define an external comparison logic. It can be used to compare objects in a custom order. Implemented in a separate class or as an anonymous class.class NameComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } }
queue interface: deque, double ended queue
Map:
hashmap: non-synchronized, 1 null
hahs table: synchonized, non null
sorted map: tree map, acending
fail fast: concurrent modification exception
fail safe: no exception: they work on clone of colelction , later on they merge it on.
blocking queue: producer consumer use case
no overflow, no underflow
synchronized , concurrent
both thread safe, faster and efficient hashmap
hash map : no other thread can read segments
lock stripping: seg 1 is lock other thread worker as seg 2, 3,4
collection hierarchy
list: order, duplicate, index based
queue: fifo
set: sorted, no duplicate
hashset: hashtable, unique, one null, order
linked hashset: orderd
sorted set: comparatble interface asceneding
treeset: self binary serach tree[red black tree]
map: key-value, unique, duplicate value
