views:

262

answers:

3

I am wondering what the rationale is behind having Java's Map.put(key, value) method overwrite equivalently key'd values that are already in the collection, while Set.add(value) does not overwrite a pre-existing equivalent value that is already in the collection?

Edit:

It looks like majority viewpoint is that objects in a set that evaluate to equality should be equal in every respect, thus it shouldn't matter if Set.add(Object) overwrites equivalently valued objects or not. If two objects evaluate to equality, but do in fact hold different data, then a Map-type collection is a more appropriate container.

I somewhat disagree with this veiwpoint.
Example: A set holding a group of "Person" objects. In order to update some information about that person, you might want to pass the set a new, updated, person object to overwrite the old, outdated person object. In this case, a Person would hold a primary key that identifies that individual and the set would identify and compare people based only on their primary keys. This primary key is part of the person's identity as opposed to an external reference such as a Map would imply.

+2  A: 

The Map behavior allows changing the values associated with equivalent keys. That is a pretty common use case: a : b becomes a : c.

Yes, over-writing Set contents with add could change something (reference value) - but that seems like a pretty narrow use case (which can be accomplished anyways - always try to remove before adding: s.remove(o); s.add(o);) relative to what one would be getting in most cases - nothing for cycles.

edit:

the one potential use I could see for that behavior, is having a constrained memory budget, lots of heavy-but-equivalent objects being created, and having references to different equal versions in various places, preventing garbage collection of the duplicate ones. Having run into that problem before, however, I don't think this behavior is even the best way to solve it.

Carl
The `if`-check could even be removed ;)
aioobe
indeed, you can - fixed!
Carl
+3  A: 

In my opinion, there is no point in overwriting something in Set, since nothing will change.

However when you update a map, the key might be the same, but the value might be different.

Alexandru Luchian
Depending on how you implement set, it would change. In my case, I was using key'd objects. I implemented comparable and overrode .equals() and .hashcode() so that the set only looked at the primary keys on the object. When adding an element in the set, I wanted it to overwrite any object that already had that key with the object that held the new information. I was surprised when this didn't happen.
DutrowLLC
Sounds like you really have a map: `primaryKey -> object`
Michael Brewer-Davis
I used at map at first. The issue I had with that is that I was duplicating the keys in the map and the object which provided an opportunity for data incongruency. Its possible that I could get away with taking the key out of the object and only having it in the map, but that may cause problems in other places.
DutrowLLC
@DutrowLLC - you shouldn't be able to have duplicate keys in a map, that defeats the purpose of the map.
Alexandru Luchian
@DutrowLLC, nothing prevents you from doing map.put(object.key, object). Just make sure the key doesn't change (as your map may loose track of it if it changes hash-code for instance).
aioobe
@DutrowLLC - you should be able to take the key out of the object, unless sometimes you need to get the key from the object. In which case, you should consider a BiMap - good implementations in Guava aka Google Collections and Apache Commons Collections.
Carl
@HeavyBites - I don't have duplicate keys. If you do Map.put(Object.key, Object), the key is two places: It is in the object as well as the key in the map.
DutrowLLC
A: 

I disagree with the premise of your question. Both Map and Set are abstract interfaces. Whether they overwrite or not is an implementation detail.

  1. an implementation of Map that does not overwrite.
  2. You could create a mutable singleton set - adding stuff to the set overwrites the existing singleton value.
emory
Have you actually read the javadocs for java.util.Set, and particular for the add method?
GregS
The javadocs for Set clearly suggest that it is intended to model the mathematical concept of set. What it actually does is specified in implementation classes. The compiler does not enforce javadocs comments.
emory
If you are familiar at all with Java you know that the language does not have the expressive power to provide enforcement for all the contractual requirements of an interface. Nevertheless, you may *assume* that all classes that implement Set (or List or whatever) obey the contract. All Sun classes do, and if you implement Set and don't your code will actually catch fire and burn you.
GregS