Access and modify the next entry set while iterating a map in Java

问题: While working on a problem statement, I need to access the next Entry of a Map and based on a condition, I need to modify the next entry value. I have been considering th...

问题:

While working on a problem statement, I need to access the next Entry of a Map and based on a condition, I need to modify the next entry value.

I have been considering the solution provided here: How to get the previous key/value and the next key/value in Maps where I can access the higherEntry using NavigableMap but it throws:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractMap$SimpleImmutableEntry.setValue(AbstractMap.java:797)

which is totally understood. Here is the code snippet

for (Map.Entry<Character, Integer> current : myMap.entrySet()) {

    Map.Entry<Character, Integer> next = myMap.higherEntry(current.getKey());

    if (current.getValue() == next.getValue()) {
        // Code block
    } else if (current.getValue() > next.getValue()) {
        // Code block
    } else {
        next.setValue(1); // Line that throws Exception
    }
}

How can I Iterate through a Map, access and modify the next Entry when required?


回答1:

Instead of using an enhanced for loop, you can use a normal for loop and keep track of the index. This is tricky because you need a way to access the next entry and it depends on if you are using a ordered implementation of Map (like LinkedHashMap). If you are not using LinkedHashMap or some similar ordered map this will not be consistent and the entries could get out of order. Assuming you are using an ordered map, you can first convert the entry set to an array and go from there. This would look like Map.Entry<Character, Integer>[] entries = myMap.entrySet().stream().toArray(Map.Entry[]::new); Then, you can use a for loop along with this array.

for (int i = 0; i < entries.length-1; i++) {
    Map.Entry<Character, Integer> current = entries[i];
    Map.Entry<Character, Integer> next = entries[i+1];
    //code that does stuff
}

回答2:

TreeMap.higherEntry returns an immutable entry, and that explains the UnsupportedOperationException that you're seeing:

//exportEntry is being called by TreeMap.higherEntry(K)
static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
    return (e == null) ? null :
        new AbstractMap.SimpleImmutableEntry<>(e);
}

One possible solution/workaround is to collect your updated entries into a map and then modify your original map after the loop:

Map<Character, Integer> updates = new HashMap<>();

for (Map.Entry<Character, Integer> current : myMap.entrySet()) {

    Map.Entry<Character, Integer> next = myMap.higherEntry(current.getKey());

    if(null != next) {
        if (current.getValue() == next.getValue()) {
        } else if (current.getValue() > next.getValue()) {
        } else {
            updates.put(next.getKey(), 1); // entry to be updated
        }
    }
}

myMap.putAll(updates);

Note that I've added a null check as myMap.higherEntry may return null.


回答3:

        Map.Entry<String, Integer> next = myMap.higherEntry(current.getKey());

        if(next != null)
        {
            if (current.getValue() == next.getValue())
            {
                //Code block
            }
            else if (current.getValue() > next.getValue()) {
                //Code block
            }

            else {
                myMap.put(current.getKey(), 1); 

            }
        }
  • 发表于 2019-02-15 16:00
  • 阅读 ( 212 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除