在Java中迭代映射时访问和修改下一个条目集

时间:2019-02-14 05:25:11

标签: java dictionary collections

在处理问题陈述时,我需要访问Entry中的下一个Map,并且根据条件,我需要修改下一个条目值。

我一直在考虑这里提供的解决方案:How to get the previous key/value and the next key/value in Maps,在这里我可以使用higherEntry访问NavigableMap,但是它抛出:

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

这是完全理解的。这是代码段

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
    }
}

如何在需要时遍历Map,访问和修改下一个条目?

4 个答案:

答案 0 :(得分:0)

您可以使用普通的for循环而不用使用增强的for循环并跟踪索引。这很棘手,因为您需要一种访问下一个条目的方法,这取决于您是否使用Map的有序实现(例如LinkedHashMap)。如果您未使用LinkedHashMap或某些类似的有序映射,则这将不一致,并且条目可能会混乱。假设您使用的是有序映射,则可以先将条目集转换为数组,然后从该数组开始。看起来像Map.Entry<Character, Integer>[] entries = myMap.entrySet().stream().toArray(Map.Entry[]::new);,然后,您可以将此数组与for循环一起使用。

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
}

答案 1 :(得分:0)

TreeMap.higherEntry返回一个不可变条目,它解释了您所看到的UnsupportedOperationException

//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);
}

一种可能的解决方案/解决方法是将更新的条目收集到地图中,然后在循环之后修改原始地图:

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);

请注意,由于myMap.higherEntry可能返回null,因此我添加了空检查。

答案 2 :(得分:0)

        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); 

            }
        }

答案 3 :(得分:0)

方法higherEntry返回一个不可变的条目,但是您的代码也缺少对没有更高条目的情况的处理。另一方面,迭代器返回的下一个条目无论如何都是正确的条目(如果有的话),因此可以手动使用Iterator来完成,如下所示:

Iterator<Map.Entry<Character, Integer>> it = myMap.entrySet().iterator();
if(it.hasNext()) {
    for(Map.Entry<Character, Integer> current=it.next(), next; it.hasNext(); current=next) {
        next = it.next();
        // don't compare Integer objects via ==, use equals
        if (current.getValue().equals(next.getValue())) {
            // Code block
        } else if (current.getValue() > next.getValue()) {
            // Code block
        } else {
            next.setValue(1);
        }
    }
}

“不太干净”但相当简单的替代方法是

Map.Entry<Character, Integer> current = null;
for(Map.Entry<Character, Integer> next: myMap.entrySet()) {
    if(current != null) {
        if (current.getValue().equals(next.getValue())) {
            // Code block
        } else if (current.getValue() > next.getValue()) {
            // Code block
        } else {
            next.setValue(1);
        }
    }
    current = next;
}