如何在相同的替换位置替换LinkedHashmap中的整个键/值对

时间:2017-12-22 06:28:50

标签: java

我正在尝试从我的LinkedHashMap替换整个键/值对,但似乎它不起作用。我正在进行并发修改。 有没有办法在没有任何重大变化的情况下替换同一位置的键的整个键/值对。

我尝试执行以下操作:

    Map<String, String> testMap = new LinkedHashMap<String, String>();
    testMap.put("1", "One");
    testMap.put("2", "Two");
    testMap.put("3", "Three");
    testMap.put("4", "Four");
    testMap.put("5", "Five");
    testMap.put("6", "Six");
    /*
     * Removing an element from the Map.
     */
    Iterator<Entry<String, String>> iter = testMap.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry<String, String> entry = (Map.Entry<String, String>) iter.next();
        System.out.print(entry.getKey() + "->" + entry.getValue() + "; ");
        if (entry.getKey().equals("1"))
            iter.remove(); // remove one entry (key/value) with key "1". Ok

        if (entry.getValue().equalsIgnoreCase("Two"))
            iter.remove(); // removing all entries (key/value) for value "Two". Ok

        if (entry.getKey().equals("3"))
            entry.setValue("Updated_Three"); // Updating value for key 3. Ok

        // Below how to now add a new key/value pair in my testMap at this position
        // without affecting any other order?
        if (entry.getKey().equals("4")) {
            iter.remove();
            // How to now add a new key/value pair at this position without affecting any
            // other order.
            // testMap.put("44", "FourFour"); // Removing entry with key 4 and adding a new
            // key/valuepair to hashmap. It throws ConcurrentModificationException. Any
            // other way to perform this?
        }
    }

2 个答案:

答案 0 :(得分:2)

据我所知,你想坚持使用LinkedHashMap。如果您在迭代时尝试添加新数据(更改LinkedHashMap的结构),您将获得ConcurrentModificationException。

以下代码可能符合您的要求:

public static void main(String args[]) throws IOException {

    Map<String, String> testMap = new LinkedHashMap<>();
    testMap.put("1", "One");
    testMap.put("2", "Two");
    testMap.put("3", "Three");
    testMap.put("4", "Four");

    int indexOfFourtyFour = -1;
    System.out.println("Test Map before :: " + testMap);

    Iterator<Entry<String, String>> itr = testMap.entrySet().iterator();
    int index = 0;
    while (itr.hasNext()) {
        Map.Entry<String, String> entry = (Map.Entry<String, String>) itr.next();
        if (entry.getKey().equals("3")) {
            itr.remove();
            indexOfFourtyFour = index;
        }
        index ++;
    }
    if (indexOfFourtyFour > -1) {
        add(testMap, indexOfFourtyFour, "44", "FourFour");
    }
    System.out.println("Test Map after :: " + testMap);
}

public static <K, V> void add(Map<K, V> map, int index, K key, V value) {
    assert (map != null);
    assert !map.containsKey(key);
    assert (index >= 0) && (index < map.size());

    int i = 0;
    List<Entry<K, V>> rest = new ArrayList<Entry<K, V>>();
    for (Entry<K, V> entry : map.entrySet()) {
        if (i++ >= index) {
            rest.add(entry);
        }
    }
    map.put(key, value);
    for (int j = 0; j < rest.size(); j++) {
        Entry<K, V> entry = rest.get(j);
        map.remove(entry.getKey());
        map.put(entry.getKey(), entry.getValue());
    }
}

输出:

  

之前的测试图:: {1 =一,二=三,三=四,四=四}   测试地图:: {1 =一,二=二,44 =四四,四=四}

在LinkedHashMap中的特定索引处添加元素的代码 来自HERE

答案 1 :(得分:0)

如果您正在使用 LinkedHashMap 并希望使用 KEY 而不是索引,您可以执行以下操作(基于@vinS 的回答):

/**
   * Replaces the {@param originKey} and it's value with the new {@param key} and {@param value} for
   * the {@param map}. <b>CAUTION: This only works on {@link LinkedHashMap}!</b>
   *
   * @param map a {@link LinkedHashMap} to replace the key and value on
   * @param originKey the KEY which will be replaced
   * @param key the new KEY used
   * @param value the new VALUE used
   * @param <K> type of the KEYs for the {@link Map}
   * @param <V> type of the VALUEs for the {@link Map}
   */
  private static <K, V> void replaceAtPosition(Map<K, V> map, K originKey, K key, V value) {
    assert (map != null);
    assert !map.containsKey(key);
    Map<K, V> newMap = new LinkedHashMap<>(map.size());
    for (Map.Entry<K, V> entry : map.entrySet()) {
      if (entry.getKey().equals(originKey)) {
        newMap.put(key,value);
      }else{
        newMap.put(entry.getKey(),entry.getValue());
      }
    }
    map.clear();
    map.putAll(newMap);
  }