Java - HashMap Iteration - Exception - java

I want to iterate a HashMap like:
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
map.replace(entry.getKey(), entry.getValue()-1);
if (entry.getValue() == 0) {
map.remove(entry.getKey(), 0);
}
}
This ends in an Exception: java.util.ConcurrentModificationException
Any solutions?
Kind regards

Iterator<Map.Entry<Integer, Integer>> entryItr = map.entrySet().iterator();
while (entryItr.hasNext()) {
Map.Entry<Integer, Integer> entry = entryItr.next();
if (entry.getValue() > 1) {
entry.setValue(entry.getValue() - 1);
} else {
entryItr.remove();
}
}

You're removing items from the map as you're iterating through it. This is what's causing the exception.
To get a bit of intuition as to why this is: if your map contains three items and on the first iteration you remove the first item, should the next item be the second, or third? i.e. should the iteration continue as though the removed item was still there? And if so, how?
You can get around this by using an iterator on the map which safely goes through each element of the map.

You can't remove elements from an existing Set without using Iterator, otherwise, it will throw ConcurrentModificationException
So, place values to a new Map object if(value-1 !=0) as shown below:
Map<Integer, Integer> map = new HashMap<>();
Map<Integer, Integer> newMap = new HashMap<>();
Iterator<Integer> iterator =map.keySet().iterator();
while(iterator.hasNext()) {
int key = iterator.next();
int value = map.get(key);
if(value-1 !=0) {
newMap.put(key, value-1);
}
}

Related

Getting two elements from a map which their sum equals to a desired number

I am trying to find a way to get the first 2 elements from a map which their value combined gives me a desired sum.
I was thinking of a solution which combined 2 maps where the key of the second map is the reminder of the target number minus the value of the entry of the first map.
I am lost and not sure what I am missing.
What am I missing here?
I would suggest introducing a new Map remainderToItem, looping through all relevant items and adding their reminder to the Map as key and item key as the value
then iterate the relevantItems Map again to find the price is matching with some other reminder
Also check remainderToItem.get(entry.getValue()).equals(entry.getKey())) (in case the value is 50 reminder is also 50), this prevents adding same item again to itemsThatCanBeBought
private static List<String> getTwoItemsWhichSumTo100(Map<String, Integer> items, int target) {
Map<String, Integer> relevantItems = getRelevantItems(items, target);
Map<Integer, String> remainderToItem = new HashMap<>();
List<String> itemsThatCanBeBought = new ArrayList<>();
for (Map.Entry<String, Integer> entry : relevantItems.entrySet()) {
int remainder = target - entry.getValue();
remainderToItem.put(remainder, entry.getKey());
}
for (Map.Entry<String, Integer> entry : relevantItems.entrySet()) {
if (remainderToItem.containsKey(entry.getValue()) && !remainderToItem.get(entry.getValue()).equals(entry.getKey())) {
itemsThatCanBeBought.add(entry.getKey());
itemsThatCanBeBought.add(remainderToItem.get(entry.getValue()));
return itemsThatCanBeBought;
}
}
return itemsThatCanBeBought;
}
private static Map<String, Integer> getRelevantItems(Map<String, Integer> items, int target) {
Map<String, Integer> relevantItems = new HashMap<>();
for (Map.Entry<String, Integer> entry : items.entrySet()) {
if (entry.getValue() < target) relevantItems.put(entry.getKey(), entry.getValue());
}
return relevantItems;
}
the problem you're facing is that the int is the value , not the key.
so pairOfItems.containsKey(remainder) should not compile.
luckily for you, Map also has containsValue() method. as long as there is no requirement for minimum performance, that should solve your problem.
...and you don't need a 2nd map. you can just ask items.containsValue(reminder)

How to remove a key from HashMap? [duplicate]

This question already has answers here:
How to remove a key from HashMap while iterating over it? [duplicate]
(2 answers)
Closed 7 years ago.
i have this hashmap
HashMap <Integer,Integer> H = new HashMap <Integer,Integer>();
and when i try to remove the key from HashMap i recive this error
**Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
at java.util.HashMap$KeyIterator.next(HashMap.java:956)
at Livre.montantTotal(Livre.java:42)**
this is my code
for (int e : H.keySet()){
H.put(e, H.get(e)-1);
if (H.get(e) == 0){
H.remove(e);
}
}
You are getting this error because you are trying to remove the element and rearrange the hashmap while its already in use (while looping through it).
To loop through an collection objects in Java, you have an Iterator class which can solve your problem. That class has a remove() method to remove a key pair value from HashMap.
Possible duplicate of How to remove a key from HashMap while iterating over it? and
iterating over and removing from a map
EDIT:
Try this code on Java 7 and earlier versions:
Map<String, String> map = new HashMap<String, String>() {
{
put("test", "test123");
put("test2", "test456");
}
};
for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
if(entry.getKey().equals("test")) {
it.remove();
}
}
In Java 8, you can try this:
map.entrySet().removeIf(e-> <boolean expression> );
You need to use an Iterator to remove from a collection while iterating over it.
for (Iterator<Map.Entry<Integer, Integer>> i = H.entrySet().iterator(); i.hasNext();) {
Map.Entry<Integer, Integer> e = i.next();
int v = e.getValue();
if (v == 1)
i.remove();
else
e.setValue(v - 1);
}
From the Documentation for HashMap.EntrySet() (https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html)
The set is backed by the map, so changes to the map are reflected in
the set, and vice-versa.
You can't change something while you're iterating through it. When you change the HashMap, you change it's keySet too, and since you're iterating through that, Java throws an error. What you might have to do is add every key that needs to be removed to a separate list, then iterate through that list afterward.
Like this:
ArrayList<Integer> otherList = new ArrayList<>();
for(int e : H.keySet()){
h.put(e, H.get(e) - 1);
if(H.get(e) == 0)
otherList.add(e);
}
for(int e : otherList){
H.remove(e);
}

How to iterate a TreeMap until a specific key?

I want iterate a TreeMap until a specific key .
for (int i = 0 ; i < specifickey ; i++)
How can i do this ?
TreeMap implements NavigableMap which can be useful to iterate over a range of keys.It is internally backed by the Map,so any changes you do to the Map is reflected vice-versa.You should use a headMap(K toKey, boolean inclusive) to get the map
NavigableMap<K,V> navigableMap = map.headMap(toKey, true);
for(Map.Entry entry : navigableMap .entrySet()){
//use the key value pair in Map.Entry
}
If you just want to iterate over the keys:
for (String key : map.keySet()) {
if (key.equals(target)) {
// do something
}
}
If you also need to access the values, then it's more efficient to iterate over the entries instead of the keys:
Map<String, Integer> map = new TreeMap<>();
String target = "something";
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getKey().equals(target)) {
// do something with entry.getValue()
}
}
Like every other map:
Map<Integer, Object> map = ...;
for (int key : map.keySet()) {
if(key == yourValue) {
//value found
}
}
Edit: Read your question again, if you only want to find out, if a key is present, then:
if(map.containsKey(key)) {
//do something
}

How do I remove an element from a hashtable using its value and not the key?

I'm new to hash table and I'm just figuring out the basic operations on it.
I have a hash table created as shown below and inserted values also.
Hashtable<Integer , String> ht = new Hashtable<Integer , String>();
ht.put(1234, "ABCD");
ht.put(2345, "EFGH");
ht.put(4567, "IJKL");
I am able to delete the element needed using the key as shown below
System.out.println("Deleting entry with key 2345");
ht.remove(2345);
System.out.println(ht.toString());
which gives the following output
Deleting entry with key 2345
{4567=IJKL, 1234=ABCD}
I am not able to find any method which helps with locating the element in the hashtable using the value as an index and deleting the element. How do I go about it?
try this
ht.values().remove("ABCD");
this will remove one entry with the specified value, if there may be multiple entries with the same value you can use this
ht.values().removeAll(Collections.singleton("ABCD"));
Navigate using Map.entrySet() and check for Map.Entry#getValue() equality.
You can have a value multiple times so iterate entrySet using an Iterator and delete elements using Iterator.remove()
void deleteItem(String item) {
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
if(entry.getValue().equals(item)) {
it.remove();
}
}
}
Map<Integer, String> map = ...
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
// Remove entry if value equals xxx.
if (entry.getValue() != null && entry.getValue().equals("X")) {
// Do something
}
}

Get Key value from iterator

I have a HashMap, which contains another HashMap. I want to iterate over the first HashMap and use the Key values from that. Then, as I iterate over the first HashMap I want to start an inner loop iterating over the second HashMap, getting all the values.
The problem I have so far is that I can't figure out how to get the keys from the Iterator.
HashMap<String, HashMap<Integer, String>> subitems = myHashMap.get("mainitem1");
Collection c = subitems.values();
Iterator itr = c.iterator();
while(itr.hasNext())
{
// Get key somehow? itr.getKey() ???
// contains the sub items
HashMap productitem = (HashMap)itr.next();
}
The data that i get from subitems is this:
{Item1{0=sub1, 1=sub2}, Item2{0=sub3, 1=sub4}}
Then, in the while loop productitem contains the 'sub items'. But i can't find out where i can get the key value 'Item1' and 'Item2' from.
How can i get those?
You can't get the key from values().iterator().
You need to use entrySet().iterator(). That will return Map.Entry<K,V> objects on which you can call getKey() and getValue().
for (Map.Entry<Integer,Key> entry : subitems.keySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
// do stuff
}
I'd also like to add that having deeply nested maps of lists of maps is usually a sign that you really want to write custom classes to hold your data. Especially when the maps have pre-defined keys to be used and interpretation of the values in the lists depends on the position within the list! I call this code smell "object denial".
You can't go from value to key in a map. (There may be several keys mapping to the same value!)
You can iterate over the map entries though using subitems.entrySet().iterator(), or you can iterate over the keys, and in each iteration retrieve the associated value through subitems.get(key).
You could do something like this (using iterators):
Set<Entry<String, HashMap<Integer, String>>> c = subitems.entrySet();
Iterator<Entry<String, HashMap<Integer, String>>> iterator = c.iterator();
while(iterator.hasNext())
{
Entry<String, HashMap<Integer, String>> entry = iterator.next();
System.out.println("key:" + entry.getKey());
HashMap<Integer, String> innerMap = entry.getValue();
if (innerMap == null) {
continue;
}
Iterator<Entry<Integer, String>> innerIterator = innerMap.entrySet().iterator();
while (innerIterator.hasNext()) {
Entry<Integer, String> innerEntry = innerIterator.next();
System.out.println("key:" + innerEntry.getKey() + " value: " + innerEntry.getValue());
}
}
or like this using foreach structure:
for (Entry<String, HashMap<Integer,String>> entry : subitems.entrySet())
{
System.out.println("key:" + entry.getKey());
HashMap<Integer, String> innerMap = entry.getValue();
if (innerMap == null) {
continue;
}
for (Entry<Integer, String> innerEntry : innerMap.entrySet())
System.out.println("key:" + innerEntry.getKey() + " value: " + innerEntry.getValue());
}
}
java Collections provide facility of EntrySet. This is a list of objects which contain individual keys and values as its properties. You can take a iterator out of this list.
You can get keys as follows.
Iterator i= subitems.entrySet().iterator();
while(i.hasNext()){
String key= i.next().getkey();
}
You can iterate over entries using entrySet().iterator() on the first HashMap or get the keys and iterate over them: Instead of subitems.values().iterator() use subitems.keys().iterator() and use the next key to get the inner hashmap.

Categories

Resources