How to update a value for a key in HashMap? - java

I am having HashMap like this,
HashMap<String,Set<String>> map = new HashMap<String,Set<String>>();
I am trying to do before adding an element in map,
Want to check whether the key exist or not, i can get it by using map.containsKey().
If the key exist, i want check the size of Set respective to that key.
If size <= 1 i want add an element in that set.

I wouldn't use containsKey and get as this means two lookups when you only need one.
private final Map<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> set = map.get(key);
if(set != null && set.size() <= 1)
set.add(some$value);
The only problem with this is that the value will always be null unless you set it somewhere so what you may want is
private final Map<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> set = map.get(key);
if(value != null)
map.put(key, set = new HashSet<String>());
if (set.size() <= 1)
set.add(some$value);
It is unusual to have a set with a maximum size of 2. Is there any reason for this?

Sounds like this:
HashMap<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> value = map.get("key");
if(value != null) {
if(value.size() <= 1) {
value.add("some value");
}
} else {
map.put("key", new HashSet<String>());
}
Now, either the last point was poorly worded (i.e. you want to update the Set associated with the key) or you really want to update the key itself, in which case you'd probably have to just remove it and add a new entry.

You could get the set from the map with map.get(String key).
Then test the size of the Set. If needed, add your element.
Now you can simply remove the old set from the map with map.remove(String key) and reinsert it with put(String, Set);

Related

Adding values under same key HashMap in Java [duplicate]

This question already has answers here:
Increment an Integer within a HashMap
(13 answers)
Closed 10 months ago.
I'm new to HashMaps, and I was wondering if there was a way to add values together if they have the same key.
For example, when I have the key 'a' and the value is 20 and later on I use the key 'a' again and the value is 10 the value should now be 30.
I don't know how I would check if the Value already is in the HashMap and then use the same value again. The adding part could be done with just a variable that copies the current value and adds the new one, I guess.
I am guessing you want a hashmap for character vs integer and want to add the integer to already present value in case the value is present.You can do something like below:
public hashMapImpl(char ch, int number){
Map<Character,Integer> map = new HashMap<>();
if(map.containsKey(ch)){
map.put(ch, map.get(ch)+number);
}
else{
map.put(ch,number);
}
}
Where ch will be your key and number will be something that you want to store at particular key.
you can use compute method to add/sum a value in case a key exists, or create a new entry in case it doesn't.
Map<String, Integer> map = new HashMap<>();
String myKey = "a";
Integer myValue = 10;
map.compute(myKey, (key, value) -> {
if (value == null)
return myValue;
else
return value + myValue;
}
);
System.out.println(map);
map.compute(myKey, (key, value) -> {
if (value == null)
return myValue;
else
return value + myValue;
}
);
System.out.println(map);
Outputs:
a={10}
a={20}
Of course, putting this compute logic inside a method will make you code cleaner :)
I will use an example class called HashMapExamle to explain this.
Inside the class I will create a HashMap called bigHashMap assuming that was your initial hashMap with prior data.
I also have a main method to call the method that will solve your problem. I have named the method bigHashMap. So for starters, i have initialized our prior HashMap named bigHashMap and initialized wit with some new key-value pairs.
I will printout the value of the HashMap. I will then add a value with the same key, in this case food with the value 15, by calling the hashMapValueAdd method I have created and passing the key(food) and value(15) to it.
The concept of the method is:
Check if the HashMap contains the key.
if it has it, it will get the value with that ky and add the new value to it. it will then replace the value at the key with the new value.
If the key is not found in the hashmap then the new key-value pair will just be inserted.
class HashMapExample {
private static HashMap<String, Integer> bigHashMap;
public static void main(String[] args) {
bigHashMap = new HashMap<>();
// Add test data
bigHashMap.put("food", 200);
bigHashMap.put("transport", 20);
bigHashMap.put("entertainment", 40);
System.out.println("Data before : \n" + bigHashMap);
hashmapValueAdd("food", 15);
System.out.println("Data after : \n" + bigHashMap);
}
private static void hashmapValueAdd(String key, int value) {
// Check if hashMap contains the given key
if (bigHashMap.containsKey(key)) {
// Get previous value with the same key
int valueWithSameKey = bigHashMap.get(key);
// Increment the value with incoming value
int newValue = valueWithSameKey + value;
// Put updated value into HashMap
// bigHashMap.put(key, +value);
bigHashMap.replace(key, newValue);
} else {
// Put the current key since it does not exist in the HashMap
bigHashMap.put(key, value);
}
}
}
I hope this solves your problem.
You can check out these HashMap explanations to get a better understanding.
Java HashMap - W3Schools
Java MAp - Jakob Jenkov
Java HashMap replace()
Update the Value Associated With a Key in a HashMap

Remove entry from Map if object meets certain criteria

I have a map of objects, and I want to delete it from the map if the objects attributes meet a certain criteria.
The map is as follows
Map<String, ExchangeSummaryItem> under20 = mapper.readValue(new URL("https://rsbuddy.com/exchange/summary.json"), new TypeReference<Map<String, ExchangeSummaryItem>>() {});
Each ExchangeSummary has a sell_average, sell_quantity, and buy_quantity, and I want to remove it from the map if sell_average > 2000, and buy/sell quantities are both 0.
My current code is as follows but doesn't successful remove any values from the map (the map still had the same size)
for (ExchangeSummaryItem item : under20.values()) {
int ObjSellAverage = item.getSellAverage();
int ObjSellQ = item.getSellQuantity();
int ObjBuyQ = item.getBuyQuantity();
if (ObjSellAverage > 20000 && ObjSellQ == 0 && ObjBuyQ == 0){
System.out.println(under20.size());
under20.remove(item);
}
}
Any help as to why this is happening would be much appreciated! Thank-you!
under20.remove(item); is calling remove with the value. It expects the key.
You also can't just change to iterating over under20.keySet() and calling remove, because you'd have a ConcurrentModificationException.
One easy way to solve it is to create another map:
Map<String, ExchangeSummaryItem> result = new HashMap<>();
//Map.entrySet() gives you access to both key and value.
for (Map.Entry<String,ExchangeSummaryItem> item : under20.entrySet()) {
int ObjSellAverage = item.getValue().getSellAverage();
int ObjSellQ = item.getValue().getSellQuantity();
int ObjBuyQ = item.getValue().getBuyQuantity();
if (!(ObjSellAverage > 20000 && ObjSellQ == 0 && ObjBuyQ == 0)){
result.put(item.getKey(), item.getValue());
}
}
And use filtered values in result

Update HashMap without adding new entry

My program uses two HashmMap and they have exactly the same number of entries and the same keys.
One (tableMap) is static and never changes. The other one is dynamic (partitionMap), this means that I need to update values.
My algorithm got a problem, because seems to be adding one more entry when it is supposed to be not.
//I have a LinkedList of strings that I want to add to the HashMap partitionMap
LinkedList<String> partition = new LinkedList<String>();
for (TerminalNode terminalNode : ctx.U()) {
partition.add(terminalNode.getText());
}
//for each entry of tableMap
for(Entry<String, LinkedList<String>> entry : tableMap.entrySet())
{
//I retrieve keys and values from tableMap
String key = entry.getKey();
LinkedList<String> attributes = entry.getValue();
//the condition: if my linkedlist is included in the other do...
if(attributes.containsAll(partition))
{
//get the list of values
ArrayList<LinkedList<String>> l = partitionMap.get(key);
//but the first time is always null since I init partitionMap without values
if(l==null)
{
ArrayList<LinkedList<String>> firstLL = new ArrayList<LinkedList<String>>();
firstLL.add(partition);
partitionMap.put(key, firstLL); //BUG HERE! add one more entry instead of just updating values
}
else
{
l.add(partition);
partitionMap.put(key, l);
}
}
}
Does anybody have an idea why this is wrong?

Getting intersection of a keys of a map

This is my map
Map<String,Set<Integer>> transactions = new HashMap<String,Set<Integer>>();
This is the Set of string
Set<String> check_set
Now question is how to make this method
Set<Integer> getIntersection(Map<String,Set<Integer>> transactions, Set<String> check_set)
Which will return intersection of all the Set of integers corresponding to the keys in check_set.
If the MAP is
tea=[1,3,5,7,9],
milk=[2,3,6,7,9],
sugar=[1,4,6,8,9]...
and if check_set is {"tea","milk"} then the method should return values which are present in both tea and milk i.e {3,7,9}. Or if it has {"milk","sugar"} then it should return {6,9}. if it has all three {"sugar","milk",tea"} then it should return {3,9}.
I understand I need to use retainAll function to get intersection. But how to formulate a logic to check all sets of integer in map and get their intersection.
EDIT : must use a copy of the first set in map (thanks to Bohemian)
In pseudo-code, you could have
Init result set to null to know it is still not initialized
Loop for each key in check_set
if result is null then result = map{key} // take first set
else result = intersection(result, map{key}) // and keep on intersecting
That gives in java
Set<Integer> result = null;
for (String key: check_set) {
if (result == null) {
result = new HashSet<Integer>(map.get(key));
}
else {
result.retainAll(map.get(key));
}
}
private static Set<Integer> getIntersection(Map<String, Set<Integer>> transactions, Set<String> checkSet) {
Iterator<String> iterator = checkSet.iterator();
// create a copy of the original set
Set<Integer> result = new HashSet<>(transactions.get(iterator.next()));
while (iterator.hasNext()) {
result.retainAll(transactions.get(iterator.next()));
}
return result;
}

Contains if and only if in the Collection class- Java

Map<String, Integer> successors = new HashMap <String, Integer> ();
// I have added some elements into the successors.
Collection<Integer> uniqueValues = successors.values();
Is there a way for me to find out in java if uniqueValues can show me that all the values in it are the same?
I planned on using the if(uniqueValues.contains(1))statement. But I just could not figure it out. Since this statement will say true if 1 is present and other values different from 1 are also present. I just want it to return true if 1 is the only value in the collections.
eg; {1,1,1,1,1,1,1,1,1,1,1,1,1} should return true.
But {1,2,1,3,1,4,2,4,22,1,1,1,4} should return false.
Some code along the lines of "Contains if and only if."
This will be of great help. Thanks in advance.
Do it the CPU-clock-wasting way:
if(new HashSet(successors.values()).size()>1) {...}
Well, you could do something like this (inefficiently),
boolean uniqueValues = new HashSet<Integer>(successors.values()).size() == 1;
Since that will check every value every time, a more efficient approach might be,
boolean uniqueValues = true;
Collection<Integer> values = successors.values();
Iterator<Integer> iter = values.iterator();
if (iter.hasNext()) {
int t = iter.next();
while (iter.hasNext()) {
int i = iter.next();
if (t != i) {
// stop if we find a different value
uniqueValues = false;
break;
}
}
}
Some sort of Set sounds like easiest solution
if(new HashSet<Integer>(successors.values)).size() == 1)
Because Set can contain only unique values, logical consequence of having input collection with same values is the Set of size one. Or you can of course introduce you own util method which will check this condition.

Categories