Tuesday, July 15, 2008

SCJP 6 HashMap, Hashtable & hashCode examples equals comparisons sorting put get

Always focus your SCJP learning based upon the exam objectives: SCJP Exam Objectives

Section 6: Distinguish between correct and incorrect overrides of corresponding hashCode and equals methods, and explain the difference between == and the equals method.

What is the difference between a java.util.HashMap and a java.util.Hashtable?

a) HashMap permits null keys
b) Hashtable permits null keys
c) HashMap is unsynchronized
d) Hasttable is unsynchronized

Options a) and c) are correct.

You could consider the HashMap the lazier of the two collection classes being identified here. The HashMap allows both null objects and null keys. Furthermore, access to the elements in the HashMap are not synchronized, as they are in the HashTable.


#################################################

For a HashMap, a small load factor would:

a) cause a HashMap to increase in size more often
b) cause a HashMap to increase in size less often
c) cause a HashMap to manage larger object graphs more efficiently
d) cause a HashMap to manage larger object graphs less efficiently

Option a) is correct.

With a small load factor, a HashMap would have smaller increment sizes, and as a result, would increase in size more often as elements are added to it.

#####################################################

The number of buckets a HashMap contains when it is created is known as:

a) initial load factor
b) load factor
c) initial capacity factor
d) initial capacity

Option d) is correct.

The initial capacity is the term that is used to describe how large a HashMap will be, in terms of empty buckets, when it is initially created.

"An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the capacity is roughly doubled by calling the rehash method. "


##########################################################

Given the following code, what would be the result of running the HashTest class?

public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put("one", new Entity(1));
hashtable.put("two", new Entity(2));
hashtable.put("three", new Entity(3));

System.out.println(hashtable.size());
}
}


/**** Entity Class ****/


class Entity{

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return id;
}

}


a) 0 is printed to the console
b) 1 is printed to the console
c) 2 is printed to the console
d) 3 is printed to the console
e) compile time error
f) runtime error

Option d) is correct.

Three unique entities are placed into the HashMap, each with a unique key value. As a result, when we ask how many objects are stored in the HashMap, we get the number three in return.

###########################################################


Given the following code, what would be the result of running the HashTest class?

public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(2), new Entity(2));
hashtable.put(new Entity(3), new Entity(3));


System.out.println(hashtable.size());


}

}


/**** Entity Class ****/


class Entity{

public final int CODE = 007;

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return CODE;
}

public boolean equals() {
return true;
}

}

a) 0 is printed to the console
b) 1 is printed to the console
c) 2 is printed to the console
d) 3 is printed to the console
e) compile time error
f) runtime error

Option d) is correct.

The equals method is not overridden properly.


##########################################################


Given the following code, what would be the result of running the HashTest class?


public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(2), new Entity(2));
hashtable.put(new Entity(3), new Entity(3));


System.out.println(hashtable.size());


}

}



/**** Entity Class ****/


class Entity{

public final int CODE = 007;

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return CODE;
}

public boolean equals(Object o) {
return true;
}

}


a) 0 is printed to the console
b) 1 is printed to the console
c) 2 is printed to the console
d) 3 is printed to the console
e) compile time error
f) runtime error

Option b) is correct.

In this case, the value returned for console display is 1.

When placing an object into a HashMap, the JVM looks to see if an object with the given identified, or key, has been already added. If an object is added with a key that already exists, the object in the 'bucket' or 'place' associated with that key is essentially overwritten.

To figure out if the key being provided is already in use within the HashMap, the JVM calls the hashcode method of the key, looking for a match. From there, the equals method is called.

Since all instances of the entity class return the same value for the hashcode method, the JVM thinks all instances are pretty much the same. Furthermore, since .equals also returns true on every c

all, any secondary comparisons the JVM makes on the Entity key values return true as well. So, each time we use the entity class as a key, the JVM thinks we are just adding a replacement for the existing key, and as such, the current object held in the 'bucket' is replaced by the incoming one. In the end, in this example, there is only one entity in the Hashtable when we ask the Hashtable for its size.

################################################




public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(2), new Entity(2));
hashtable.put(new Entity(3), new Entity(3));


System.out.println(hashtable.size());


}

}


###################################################

Given the following code, what would be the result of running the HashTest class?



public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(2), new Entity(2));
hashtable.put(new Entity(3), new Entity(3));


System.out.println(hashtable.size());


}

}


/**** Entity Class ****/


class Entity{

public final int CODE = 007;

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return id;
}

public boolean equals(Object o) {
return true;
}

}



a) 0 is printed to the console
b) 1 is printed to the console
c) 2 is printed to the console
d) 3 is printed to the console
e) compile time error
f) runtime error


Option d) is correct.

In this case, the equals method always returns true, but if the hashcode method indicates that two instances are NOT the same, the equals method does not need to be called. As a result, the HashMap treats every Entity key as a unique entity or instance, despite the fact that all three instances would actually generate a true value when compared using the equals method.

Since the key values appear unique to the JVM using the HashMap and the hashcode method of the entities, each key being used by the HashMap is considered unique.


###################################################


Given the following code, what would be the result of running the HashTest class?




public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(2), new Entity(2));
hashtable.put(new Entity(3), new Entity(3));


System.out.println(hashtable.size());


}

}


/**** Entity Class ****/


class Entity{

public final int CODE = 007;

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return CODE;
}

public boolean equals(Object o) {
return false;
}

}


a) 0 is printed to the console
b) 1 is printed to the console
c) 2 is printed to the console
d) 3 is printed to the console
e) compile time error
f) runtime error

Option d) is correct.

Although the Hashcode value always returns the same number, the JVM will always call the equals method to absolutely confirm that two instances are exactly the same. Since the equals method always returns false, regardless of what the hashcode method returns, then every instance of the entity class is considered different from the other, even if we as cognizant human beings know that this is not the case.

##############################################



Given the following code, what would be the result of running the HashTest class?

public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(1), new Entity(1));
hashtable.put(new Entity(1), new Entity(1));


System.out.println(hashtable.size());


}

}


/**** Entity Class ****/


class Entity{

public final int CODE = 007;

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return CODE;
}

public boolean equals(Object o) {
return false;
}

}



a) 0 is printed to the console
b) 1 is printed to the console
c) 2 is printed to the console
d) 3 is printed to the console
e) compile time error
f) runtime error

Option d) is correct.

This is a nasty question, because it looks like we are always using the same key to keep track of instances. However, since the hashcode method always returns the same value, and the equals method always indicates that two instances are not the same, the HashMap thinks that every Entity key used in this example is different. As such, each object being added to the map is placed in a separate bucket.

Remember, it is important to always provide meaningful and proper implementations to the hashcode and equals methods when creating new classes. Not doing so can have unpredictable and unforseen consequences, especially when using various frameworks such as TopLink and Hibernate.


##############################################


Given the following code, what would be the result of running the HashTest class?

public class HashTest{

public static void main (String args[]){

java.util.Hashtable hashtable = new java.util.Hashtable();

hashtable.put(new Entity(1), new Entity(1));

Entity x = new Entity(1);
Entity y = new Entity(2);


System.out.println(x.equals(y));


}

}


/**** Entity Class ****/


class Entity{

public final int CODE = 007;

int id;

Entity(int id) {
this.id = id;
}

public int hashCode() {
return id;
}

public boolean equals(Object o) {
return true;
}

}



a) true is printed to the console
b) false is printed to the console
c) runtime error is thrown
d) compile time error is generated

Option a) is correct.

In this case, the equals method always returns true, so when we call the equals method, we get a value of true.

This sometimes confuses people, because various objects call the hashcode method first when comparing two entities. For example, in the case of the HashMap collection class, when the hashcode method returns two different numbers for two instances being compared, the instances are considered to be different, and the equals method is not invoked. Only when two instances produce the same hashcode are they then compared using the equals method.

As was mentioned, this type of comparison happens in various circumstances, making some people believe the answer to this question should be false. However, since we are calling the equals method directly, the hashcode method does not come into play at all, and we get the word true printed to the console.

No comments: