how to get the old value of an object in map.putAll()? - java

HashMap map= new HashMap();
System.out.println(map.put(101,"john"));//null
System.out.println(map.put(101,"abhraham"));//john
If I give the key which is existing it replaces the value and returns the old value.
But if I use putAll how can I get the oldvalues?
HashMap map2=new HashMap();
map2.put(101,"Lincoln");
System.out.println(map.putAll(map2));//runtime exception
If I want the old value that has been replaced what I should use in map?
leave the printing part if i want the old value what i must do.

You can replace them one at a time using Map.put(), which will return the old value:
HashMap oldValues = new HashMap();
map2.forEach((key, value) -> {
oldValues.put(key, map.put(key, value));
});

The HashMap.putAll() method has a void return type, which is why you get the exception. You must call the HashMap.put() method for each element of the map2 variable and then either print them individually or put them in another map and then print it's content (or do what you want with them).

Related

Java 8 - How to reduce the size (lines) of this map operation?

I need to get value map for a key, if its not there create new map and insert the key/value. How can i reduce the number of lines of this operation using java 8 ?
Map<String, Map<String, String> map = new HashMap();
Map<String, String> valueMap = map.get(key_1);
if(valueMap == null) {
valueMap = new HashMap();
}
valueMap.put(key_2, value);
map.put(key_1, valueMap);
You can use computeIfAbsent method of Map See The Documentation
map.computeIfAbsent(key_1, k -> new HashMap<>()).put(key_2, value);
Note that you won't need to create a new HashMap instance (unlike getOrDefault method for example), if there is a key, only if there is nothing (corresponds to if(valueMap == null) in your example.
Looking at the documentation for Map: https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
It looks like computeIfAbsent does what you want.
First, declare a function newMap() that simply returns a new HashMap(). Then:
Map<String, Map<String, String> map = new HashMap();
map.computeIfAbsent(key_1, newMap);
map.get(key_1).put(key_2, value);
EDIT: Rather than declaring a named function newMap, you can use an anonymous function k -> new HashMap<>(), as suggested in Mark Bramnik's answer.
Do not use .putIfAbsent(key_1, new HashMap()), or .getOrDefault, or any other non-lazy function that would evaluate its default value even if the default value is not needed. These functions are appropriate if the default value is a simple value, for instance an int; they are not appropriate if the default value requires a call to new to be built.

If hashmap only contains one key, is there a way to get that key without knowing anything about it?

I have a hashamp with only one key (and a value). Lets say I don't know the key or value of that one key. Is there a way to find it? This may sound dumb but since there is only ONE key, then would there be a way to get that key.
For a single key map just do the following:
Map<String,String> map = Map.of("A","B");
System.out.println(map.keySet().iterator().next());
prints
A
For a more populated map you can do the following:
You can get the keySet() of the map via map.keySet() and iterate thru that.
If you want to try and find a particular key associated with a value you can
get the entrySet() of the map and do something like this:
String targetVal = "some value";
for (Entry<String,String> e : map.entrySet()) {
if (e.getValue().equals(targetVal)) {
System.out.println(e.getKey());
// or
System.out.println(e);
// keep iterating since multiple keys can
// map to the same value.
}
}
You can get all of your keys with hash_map.keySet()
https://www.geeksforgeeks.org/hashmap-keyset-method-in-java/
Yes, you can use iterators, which enable you to iterate over any Collection (or Map's entrySet()):
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("First", "Entry");
System.out.println(map.entrySet().iterator().next());
}
}
This prints: First=Entry, where First is the key and Entry is the value.
hashMapObj.entrySet().iterator().next();
is the answer to your question.

extract an element from an hash map and update it

If I extract an element from a hash map through the method get(<key>) and update the extracted element, will these updates persist in the map? Or do I have to re-insert the element back to the hash map?
If you change fields of the object you got out, like this...
Thing thing = map.get(key);
thing.setOtherThing(yetAnotherThing);
then that'll update the value in the map.
On the other hand, if you modify the reference that you obtained by getting a value out of the map...
Thing thing = map.get(key);
thing = doSomethingWith(thing);
then you need to put it back into the map.
If you modify the object obtained by the Map.get(K) method, the object does not need to be re-inserted. However, if you change a key in a way that the hashCode() function is affected, then you need to remove the map entry before modifying the key and then you can put back your value using your new key.
Consider the following map corruption case:
Map<List<String>, String> map = new HashMap<List<String>, String>();
List<String> key1 = new ArrayList<String>();
key1.add("key1");
map.put(key1, "value1");
System.out.println(map.get(key1)); //prints "value1"
key1.add("buzz2");
System.out.println(map.get(key1)); //prints "null"
List<String> k = map.keySet().iterator().next();
System.out.println(map.get(k)); //prints "null"
Morale of the story: for maps, always use immutable keys like String or int.

Java code to Prevent duplicate <Key,Value> pairs in HashMap/HashTable

I have a HashMap as below (assuming it has 10,0000 elements)
HashMap<String,String> hm = new HashMap<String,String>();
hm.put("John","1");
hm.put("Alex","2");
hm.put("Mike","3");
hm.put("Justin","4");
hm.put("Code","5");
==========================
Expected Output
==========================
Key = John",Value = "1"
Key = Alex",Value = "2"
Key = Mike",Value = "3"
Key = Justin",Value = "4"
Key = Code",Value = "5"
===========================
I need Java code to prevent Addition of Duplicate <Key,Value> Pairs in HashMap such
that below conditions are staisfied.
1> hm.put("John","1"); is not accepted/added again in the Map
2> hm.put("John","2"); is not accepted/added again in the Map
Hope its clear.
Java code provided will be appreciated.(generic solution needed since i can add any duplicate to the existing map)
You can wrap HashMap in a class, which delegates put, get, and other methods you use from HashMap. This method is wasteful but safe, since it doesn't depend on the internal implementation of HashMap, AbstractMap. The code below illustrates put, get delegating:
public class Table {
protected java.util.HashMap<String, Integer> map =
new java.util.HashMap<String, Integer>();
public Integer get(String key) { return map.get(key); }
public Integer put(String key, Integer value) {
if (map.containsKey(key)) {
// implement the logic you need here.
// You might want to return `value` to indicate
// that no changes applied
return value;
} else {
return map.put(key, value);
}
}
// other methods goes here
}
Another option is to make a class which extends HashMap, and depend on its internal implementation. Java 1.6 sources shows that put is called only in putAll in HashMap, so you can simply override put method:
public class Table extends java.util.HashMap<String, Integer> {
public Integer put(String key, Integer value) {
if (containsKey(key)) {
// implement the logic you need here.
// You might want to return `value` to indicate
// that no changes applied
return value;
} else {
return super.put(key, value);
}
}
}
Another option is similar to the first, and can make an utility method in your class which contains the HashMap instance and call that method wherever you need put something to your map:
public final Integer putToMap(String key, String value) {
if(this.map.containsKey(key)) {
return value;
} else {
return this.map.put(key, value);
}
}
This is an "inline" equivalent of checking manually.
I note that you clarify the question by suggesting you might have "100000000 elements". You still won't have duplicates in the HashMap, because, as two other posters have pointed out, you can't get duplicate keys in a Map. I'm still not sure we understand the question, though, as it's not at all clear how you expected to generate the block titled "Output", or what you intend to do with it.
This may be old question but I thought to share my experience with this. As others pointed out you can't have the same element in a HashMap. By default HashMap will not allow this but there are some cases that you could end up with two or more elements are almost alike that you do not accept but HashMap will. For example, the following code defines a HashMap that takes an array of integers as a key then add :
HashMap<int[], Integer> map1 = new HashMap<>();
int[] arr = new int[]{1,2,3};
map1.put(arr, 4);
map1.put(arr, 4);
map1.put(arr, 4);
At this point, the HashMap did not allow dublicating the key and map1.size() will return 1. However, if you added elements without creating the array first things will be different:
HashMap<int[], Integer> map2 = new HashMap<>();
map2.put(new int[]{4,5,6}, 6);
map2.put(new int[]{4,5,6}, 6);
map2.put(new int[]{4,5,6}, 6);
This way, the HashMap will add all the three new elements so the map2.size() will return 3 and not 1 as expected.
The explanation is that with the first map I created the object arr once and tried to add the same object 3 times which HashMap does not allow by default so only the last usage will be considered. With the second map, however, evey time I recreate a new object on the stack. The three objects created are different and separated thought the three of them have the same data but they are different. That's why HashMap allowed them as different keys.
Bottom line, you don't need to prevent HashMap from adding dublicated keys because it won't by design. However, you have to watch out how you define these keys because the fault may be on your side.
List<String> keys = new ArrayList<String>(); (1000000)
List<String> values = new ArrayList<String>(); (1000000)
Map<String, String> map = new HashMap<String, String>();
int i =0;
for(String key : keys){
String returnedValue = map.put(key, values.get(i));
if(returnedValue!=null){
map.put(key, returnedValue);
system.out.println("Duplicate key trying to be entered with new value so reverting the duplicate key ="+key+"new Value"+values.get(i));
}
}
Unfortunately, it is the way that Map works.
The easiest workaround is to remove all pre existed keys and their values by calling hm.remove() first! like this:
for (String name : names) {
hm.remove(name);
hm.put(name,uri.getQueryParameter(name));
}
And if you don't use a for loop just call it like this:
hm.remove("John");
hm.put("John","1");
hm.remove("Alex");
hm.put("Alex","2");
hm.remove("Mike");
hm.put("Mike","3");
And so on ...
see even if u write same key values multiple times you will just have unique set of pairs. Check that by either iterating or by doing hm.size();
if(hm.put("John","1") != null)
{
// "John" was already a key in the map. The sole value for this key is now "1".
}
List<Object> yourElements = new ... // 10000000
for(Object O : yourElements) {
if(myMap.get(O.key)==null) {
myMap.put(O.key,O);
}
}

How to retrieve all the values associated with a key?

I want to get all the values associated with a key in Map.
For e.g,
Map tempMap = new HashMap();
tempMap.put("1","X");
tempMap.put("2","Y");
tempMap.put("3","Z");
tempMap.put("1","ABC");
tempMap.put("2","RR");
tempMap.put("1","RT");
How to retrieve all the values associated with key 1 ?
the thing you must understand is that in a Map, the key is unique.
that means that after
tempMap.put("1","X");
"1" is mapped to "X"
and after
tempMap.put("1","ABC");
"1" is mapped to "ABC" and the previous value ("X") is lost
From the HashMap javadoc:
public V put(K key, V value)
Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
What you can do is this:
Map<String, List<String>> tempMap = new HashMap<String, List<String>>();
tempMap.put("1", new LinkedList<String>());
tempMap.get("1").add("X");
tempMap.get("1").add("Y");
tempMap.get("1").add("Z");
for(String value : tempMap.get("1")) {
//do something
}
This compartmentalizes values that correspond to the key "1" into their own list, which you can easily access. Just don't forget to initialize the list... else NullPointerExceptions will come to get you.
Yuval =8-)
can't
try using google collections's Multimap
I think you're missing something important:
Map tempMap = new HashMap();
tempMap.put("1","X");
tempMap.put("2","Y");
tempMap.put("3","Z");
tempMap.put("1","ABC"); // replaces "X"
tempMap.put("2","RR"); // replaces "Y"
tempMap.put("1","RT"); // replaces "ABC"
Also, you should use generics where possible, so your first line should be:
Map<String, String> tempMap = new HashMap<String, String>();
To do that you have to associate each key with a Set of values, with corresponding logic to create the set and enter/remove values from it instead of simple put() and get() on the Map.
Or you can use one of the readymade Multimap implementations such as the one in Apache commons.

Categories