As per java docs:
The put returns the previous value associated with key, or null if there was no mapping for key. (A null return can also indicate that the map previously associated null with the key if the implementation supports null values.)
In your case when you did map.put(1, "ABC") nothing was associated with key 1 so it returns null but when you use put(1, "XYZ") then there was already an entry exists against the key 1 so it returns "ABC"
According to documentation, it's a generic function that returns the same datatype as the map value. So, in your case it should return String.
The
java.util.concurrent.ConcurrentMap
and from Java 8
Java.util.Map
has
putIfAbsent(K key, V value)
which returns the existing value, and if that is null inserts given value. So if no value exists for key returns null and inserts the given value, otherwise returns existing value
If you need lazy evaluation of the value there is
computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
Java 8 adds nice method to the Map: compute, computeIfPresent, computeIfAbsent
To achieve what you need:
Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());
I assume you mean Map.put - because there is no Map.add. But even if they had the same name - these methods behave differently enough to render any attempt to unify their interface meaningless.
Look at the way Collection.add's return value's doc is worded:
true if this collection changed as a result of the call
Now, the only valid reason for the collection to not change is if it's a set and the item is already in there(any other reason should throw), but that wording was chosen because it makes sense for all collections, without having to make special clauses for sets and not-sets.
But does it make sense for maps? Consider this:
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 2);
map.put(2, 2);
/*case 1*/ map.put(1, 1); // value changed - would have returned `true`
/*case 2*/ map.put(2, 2); // nothing changed - would have returned `false`
/*case 3*/ map.put(3, 3); // key-value pair added - would have returned `true`
Case 1 and 3 both return true, but they are very different - one is overriding an entry and the other adding a new one. So maybe case 1 should have returned false? But then it would have been the same as case 2, even though one is changing the map and the other doesn't...
So, copying Collection.add's behavior to Map.put makes no sense. How about copying Map.put's behavior to Collection.add? What if we had Collection.add return the old value?
I see several problems with that:
- It makes the interface more complicated - now it needs to give different definitions for maps and sets, or make a more complex definition(e.g. - "if the item was not added because it was already there, return the item that was already there". Ugh...)
- It's not very useful. You already have the item that's already in the collection - you just sent it as an argument to
add! What if we have a
TreeSetwith a custom comparator?TreeSet<Integer> treeSet = new TreeSet<Integer>((a, b) -> Integer.compare(a % 10, b % 10)); treeSet.add(11); treeSet.add(21); // should this return `11` or `21`?This is not a problem with
Map, because it's looking by the key, and is already forced to define what you get when you request for that key.It forces the collection to actually retrieve the value. What if the
Collectionimplementation is a bloom filter? It now has to actually look for the object instead of doing a quick hash match. What if it's a wrapper around a database table? It now has to create an object that you already have!Of course,
Mapwould have a similar problem - but at least there the old value is important, because you don't know what it is and it's going to disappear. But withCollection? It's all cost and no gain...
Collection.add returns whether the collection has changed or not.
Map.put returns the previous element for the key.
These are simply different functionality.
There is not "equivalent" method in Collection interface. However you have List.set which returns the previous element in the position. Note that a Map is not a Collection.
There are two issues here.
Firstly, you can't use the [] syntax like you may be able to in other languages. Square brackets only apply to arrays in Java, and so can only be used with integer indexes.
data.put is correct but that is a statement and so must exist in a method block. Only field declarations can exist at the class level. Here is an example where everything is within the local scope of a method:
public class Data {
public static void main(String[] args) {
Map<String, String> data = new HashMap<String, String>();
data.put("John", "Taxi Driver");
data.put("Mark", "Professional Killer");
}
}
If you want to initialize a map as a static field of a class then you can use Map.of, since Java 9:
public class Data {
private static final Map<String, String> DATA = Map.of("John", "Taxi Driver");
}
Before Java 9, you can use a static initializer block to accomplish the same thing:
public class Data {
private static final Map<String, String> DATA = new HashMap<>();
static {
DATA.put("John", "Taxi Driver");
}
}
The syntax is
data.put("John","Taxi driver");