Android Interview Questions Part 2

Kishan Maurya
8 min readMar 30, 2020

In my personal opinion, a good way for preparing any kind of interview is that after the interview gets over, note down all the questions that were asked in the interview and try to find the solution for the questions that you were not able to answer at the interview time. So I am going to share a few of the questions.

You can also read a few questions from my previous article.

  1. How to execute 5 API calls parallel and once all completed do the next task?
  2. Flatmap vs compose?
  3. What will happen if you don’t override toEquals() method?
  4. What will happen if you Overriding only hashCode() method
  5. HashTable vs ConcurrentHashMap?
  6. LinkedHashMap and it's working?
  7. How to create a copy of the object?
  8. What is Deep copy and shallow copy?
  9. What is a sparse array and how it is different from HashMap?
  10. What is a handler thread?

Recommended: Please solve it first, before moving on to the solution.

There can multiple more accurate answers to the question. Based on my assumptions and learning, I am writing my answers.

How to execute 5 API calls parallel and once all completed do the next task?

CountDownLatch is used to make sure that a task waits for other threads before it starts.
CountDownLatch in Java is a kind of synchronizer which allows one Thread to wait for one or more Threads before starts processing.
When countdownlach reached 0 then it means all thread inside that has completed their task.

In Kotlin using async and Launch
Create 5 Async coroutines and creation of all these 5 async inside another launch or async coroutine.

 var job = launch { 
val work1 = async { myparallelTask(1) }
val work2 = async { myparallelTask(2) }
val work3 = async { myparallelTask(3) }
val work4 = async { myparallelTask(4) }
val work25 = async { myparallelTask(5) }
val result = work1.await() + work2.await() + work3.await() + work4.await() + work5.await()

withContext(UI) { result.toString() }
}//the variable result is only available when both work1 , work2, work3 ,work4 ,work5 are completed

Flatmap vs compose?

compose() is a higher level abstraction: it operates on the entire stream, not individually emitted items.compose() executes immediately when you create the Observable stream.flatMap() executes when its onNext() is called, each time it is called. 
FlatMap() transforms each item, whereas compose() transforms the whole stream.
flatMap() is necessarily less efficient because it has to create a new Observable every time onNext() is called.
compose() operates on the stream as it is

What will happen if you don’t override toEquals() method when dealing with hashmap?

The contract between equals() and hashCode() is:
1) If two objects are equal, then they must have the same hash code.
2) If two objects have the same hash code, they may or may not be equal.

//Creating two Objects with  same stateGeek g1 = new Geek("demo", 1);
Geek g2 = new Geek("demo", 1);
Map<Geek, String> map = new HashMap<Geek, String>();
map.put(g1, "CSE");
map.put(g2, "IT");

Overriding only the equals(Object) method?

If we only override equals(Object) method, when we call map.put(g1, “CSE”); it will hash to some bucket location and when we call map.put(g2, “IT”); it will hash to some other bucket location because of different hashcode value as hashCode() method has not been overridden.

Overriding only hashCode() method?

Map map = new HashMap();
map.put(“xyz”, “CSE”);
map.put(“xyz”, “IT”);

When we call map.put(“xyz”, “CSE”); it will generate hashcode value and stores it to the bucket location that is specified with this address (hashcode value). And when we call map.put(“xyz”, “IT”); it generates same hashcode value as previous entry since key objects are same and hashCode() method has been overridden.

So it should replace first with second as per rule. But it didn’t. The reason is when it iterates through that bucket and seeks to find k such that k.equals(“xyz”) i.e. if searching key already exists. But it fails to find because equals(Object ) method has not been overridden. It is a violation of the rule of hashing.

HashTable vs ConcurrentHashMap?

Hashtable uses single lock for whole data. At a time only 1 thread can read/write data in hash tableHashtable performance is quite slow.ConcurrentHashMap uses multiple locks on segment level instead of object level i.e. whole Map.ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to modify it while another is iterating over it and does not allow null values.ConcurrentHashMap returns Iterator, which fails-safe (i.e. iterator will make a copy of the internal data structure) on concurrent modification.

LinkedHashMap and it’s working?

LinkedHashMap is that it maintains the insertion order of key-value pairs. We will maintain double LinkedList for doing so.

Entry<K, V> before, after — we keep track of newly added entry in LinkedHashMap, which helps us in maintaining insertion order.

Next will be used to put the entry in same bucket location

Entry contains

{
K key,
V value,
Entry<K,V> next (i.e. next entry on that location of bucket),
Entry<K,V> before and
Entry<K,V> after
}

How to create a copy of the object?

Object cloning refers to the creation of an exact copy of an object. It creates a new instance of the class of the current object and initializes all its fields with exactly the contents of the corresponding fields of this object.

Assignment operator :
If we use the assignment operator then it will create a copy of the reference variable and not the object.

class Test{
int x, y;
Test(){
x = 10;
y = 20;
}
}
Test ob1 = new Test();
// Creating a new reference variable ob2 pointing to same address as ob1
Test ob2 = ob1;
// Any change made in ob2 will be reflected in ob1
ob2.x = 100;

clone() method :

Every class that implements clone() should call super.clone() to obtain the cloned object reference.

The class must also implement java.lang.Cloneable interface whose object clone we want to create otherwise it will throw CloneNotSupportedException when clone method is called on that class’s object.

class Test{int x, y;}// Contains a reference of Test and implements clone with shallow copy.class Test2 implements Cloneable{
int a;
int b;
Test c = new Test();
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Main{public static void main(String args[]) throws CloneNotSupportedException{Test2 t1 = new Test2();
t1.a = 10;
t1.b = 20;
t1.c.x = 30;
t1.c.y = 40;
// Creating a copy of object t1 and passing it to t2
Test2 t2 = (Test2)t1.clone();
// Change in primitive type of t2 will not be reflected in t1 fieldt2.a = 100;// Change in object type field will be reflected in both t2 and t1(shallow copy)
t2.c.x = 300;
OutPut : t1.a 10
t1.b 20
t1.c.x. 300 // here change in c state reflects in both t1 & t2.
t1.c.y. 40
t2.a 100
t2.b 20
t2.c.x 300
t2.c.y 40

What is Deep copy and shallow copy?

Shallow Copy

Shallow copy is method of copying an object and is followed by default in cloning.In this method the fields of an old object X are copied to the new object Y.While copying the object type field the reference is copied to Y i.e object Y will point to same location as pointed out by X. If the field value is a primitive type it copies the value of the primitive type.public Object clone() throws CloneNotSupportedException  {return super.clone();}

Deep Copy :

If any object has other class ( A ) ref then while cloning we have create new object of Class A.public Object clone() throws CloneNotSupportedException{// Assign the shallow copy to new reference variable t
Test2 t = (Test2)super.clone();
// Create a new object for the field c and assign it to shallow copy obtained to make it a deep copy
t.c = new Test();
return t;
}

Guess the output of the program

class Stu{
Stu(String name){
this.name = name;
}
public String name;
}
public class Main {
public static void main(String[] args) throws Exception {
List<Stu> a = new ArrayList<Stu>();
a.add(new Stu("HI"));
a.add(new Stu("HEllo"));
a.add(new Stu("Welcome"));
List<Stu> b = a;
List<Stu> c = new ArrayList(a);
a.add(new Stu("Medium"));
a.get(2).name = "MAC";
System.out.println(b.size()); //4
System.out.println(c.size()); //3
System.out.println(b.get(2).name); //MAC
System.out.println(c.get(2).name); // MAC
}
}

What is a sparse array and how it is different from HashMap?

ArrayMap contains two small arrays instead of one in a HashMap.
The first array (Hash-Array) contains the specified hash keys in sorted order.
The second array (Key-Value Array) stores the keys and values of the objects according to the first array.

When we fetch an item, a binary-search is done on the Hash-Array to find a matching hash the index and then directly return the key-value pair from the second array (Key-Value Array). If the key in the second array (Key-Value Array), doesn’t match then a linearly walk is done over the second array (Key-Value Array) to resolve the collision.


SparseArray key is always primitive types. Sparse arrays can be used to replace hash maps when the key is a primitive type.

SparseArray is designed to remove the auto-boxing problem (ArrayMap does not avoid the auto-boxing problem). This approach affects memory consumption.

SparseArray over HashMap is:More memory efficient by using primitives
No auto-boxing
Allocation-free
Drawbacks:
For large collections, it is slower
It only available for Android

What is handler thread?

HandlerThread sets up the Looper internally. Handy class for starting a new thread that has a looper.

It is important to explicitly call quit() on the HandlerThread in order to destroy it.

Photo by Sebastian Herrmann on Unsplash

Thanks for reading. Soon I will post more articles on Android and core Java.
Till then happy learning and keep reading!

You could check out my other interesting topics here.

--

--