1

In the case of HashMap,it replaces the old value with the new one in case of key duplication.In the case of HashSet, the item isn't inserted at all. Since HashSet is implementing HashMap internally. Why are these two insertions handled differently?

3
  • You're comparing apples and oranges here. HashMaps work like Maps, and HashSets work like Sets. Maps and Sets are two entirely different concepts, and you shouldn't let the fact that a HashSet might be implemented on top of a HashMap lead you to believe otherwise. Commented May 5, 2018 at 8:49
  • 1
    You're confusing yourself with bad phrasing. "HashMap replaces the old Key value" is correct/incorrect. It replaces the old value, but the key is unchanged. A HashSet is actually implemented as a HashMap, where the value is ignored, i.e. any value added to the Set is put into the map as a key with a dummy value: public boolean add(E e) { return map.put(e, PRESENT)==null; } Commented May 5, 2018 at 9:00
  • So can i rephrase it as both the "Duplicate Key in HashMap" and "Duplicate Value in HashSet" wouldn't overwrite the previous ones and would return false as soon it finds a duplicate key(HashMap) or value(HashSet). Commented May 5, 2018 at 10:03

1 Answer 1

1

HashMap is replaces old value with a new one, when you are inserting it with the same key. Example:

Map<Integer, String> map = new HashMap<>(); map.put(1, "first put"); System.out.println(map.get(1)); // <-- prints `first put` map.put(1, "second put"); System.out.println(map.get(1)); // <-- prints `second put` 

So basically when the new value arrives with a key already present in the map, it just replaces the value for this key, because even if the key is the same, new value can be different from the one associated with this key in the map.

In case of the HashSet, there is only key, there is no value. So when already existing key arrives, there is noting to do, it is already there.

Regarding internal implementation of the HashSet, indeed it uses HashMap internally, but what it does, it just create one object:

// Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); 

and when you add some key to set, it just calls put(key, present) on this map, using the same object for all entries(in order not to allocate lots of useless objects:

public boolean add(E e) { return map.put(e, PRESENT)==null; } 

So all in all, indeed HashSetuses internally HashMap, and when you put something to hash map, new value is always assigned instead of the old one, however the key isn't, and as HashSet uses its keys as the keys in HashMap, then if you put duplicate key in HashSet it wouldn't remove the old one. Example:

Lets assume we have some entity class which has 2 fields, int id, and string name, but only id participates in equals method implementation.

 Entity entity1 = new Entity(1, "some name"); Entity entity2 = new Entity(1, "some other name"); System.out.println(entity1.equals(entity2)); // returns true Map<Integer, Entity> map = new HashMap<>(); map.put(entity1.id, entity1); map.put(entity2.id, entity2); System.out.println(map.get(entity1.id).name); // returns "some other name" Map<Entity, String> keyMap = new HashMap<>(); keyMap.put(entity1, entity1.name); keyMap.put(entity2, entity2.name); System.out.println(keyMap.keySet()); // returns [Entity{id=1, name='some name'}] System.out.println(keyMap.values()); // returns [some other name] Set<Entity> set = new HashSet<>(); set.add(entity1); set.add(entity2); System.out.println(new ArrayList<>(set)); // returns [Entity{id=1, name='some name'}] 

Also you shouldn't rely on that too, as its internal implementation details which can be changed in future releases, HashMap and HashSet use equals methods the check if the object is the same. If you have an two objects which equals returns true but you still want to treat the differently, most probably there is some problem in you Entity design, however there are rare cases when inded thats the desired effect, in such cases you can take a look at the IdentityHashMap.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the in depth explanation! Just one question though, would the duplicate Key value be overwritten from the previous one or it will return as soon it finds the duplicate.
@AnkushDutt as I mention this PRESENT object is static, meaning that all instances of HashSet would put this particular instance of Object as a value to underlying map, when you will call add on the HashSet, from the current implementation of HashMap I see that indeed it will reassign new value even if they are equal, but you shouldnt rely on it, as its the internal implementation details. However the key wouldn't be reassigned if its already present. If it matters to you which object was assigned, even if they are equal, then you should probably take a look at IdentityHashMap
@AnkushDutt I updated answer with some more explanation and examples
So can i rephrase it as both the "Duplicate Key in HashMap" and "Duplicate Value in HashSet" wouldn't overwrite the previous ones and would return false as soon it finds a duplicate key(HashMap) or value(HashSet).
@AnkushDutt yes, in case of HashSet key wouldn't be overwritten, in HashMap key wouldn't be overwritten too, however value would be. You can check last example in my answer, it shows this behaviour for all case

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.