Changing HashMap keys during iteration

2020-01-29 06:42发布

is it possible to change keys of a the same HashMap instance during iteration ? Because map entry set don't have a method entry.setKey(). Now what I can think off is create another HashMap...

MultipartParsingResult parsingResult = parseRequest(request);

Map<String, String[]> mpParams = parsingResult.getMultipartParameters();
Map<String, String[]> mpParams2 = new HashMap<String, String[]>();

Iterator<Entry<String,String[]>> it = mpParams.entrySet().iterator();

while (it.hasNext()) {
    Entry<String,String[]> entry = it.next();
    String name = entry.getKey();

    if (name.startsWith(portletNamespace)) {
        mpParams2.put(name.substring(portletNamespace.length(), name.length()), entry.getValue());
    }
    else {
        mpParams2.put(name, entry.getValue());
    }
}

5条回答
成全新的幸福
2楼-- · 2020-01-29 07:20

Maybe this helps:

map.put(newkey,map.remove(oldkey));
查看更多
小情绪 Triste *
3楼-- · 2020-01-29 07:21

The best thing to do is to copy the map into a new one with the modifications you want, then return this new maps and destroy the old one. I wonder what's the performance impact of this solution however.

查看更多
smile是对你的礼貌
4楼-- · 2020-01-29 07:24

There are four common types of modification you might want to do to the keys or values in a HashMap.

  1. To change a HashMap key, you look up the value object with get, then remove the old key and put it with the new key.
  2. To change the fields in a value object, look the value object up by key with get, then use its setter methods.
  3. To replace the value object in its entirely, just put a new value object at the old key.
  4. To replace the value object with one based on the old, look the value object up with get, create a new object, copy data over from the old one, then put the new object under the same key.

Something like this example.

static class Food
    {
    // ------------------------------ FIELDS ------------------------------

    String colour;

    String name;

    float caloriesPerGram;
    // -------------------------- PUBLIC INSTANCE  METHODS --------------------------

    public float getCaloriesPerGram()
        {
        return caloriesPerGram;
        }

    public void setCaloriesPerGram( final float caloriesPerGram )
        {
        this.caloriesPerGram = caloriesPerGram;
        }

    public String getColour()
        {
        return colour;
        }

    public void setColour( final String colour )
        {
        this.colour = colour;
        }

    public String getName()
        {
        return name;
        }

    public void setName( final String name )
        {
        this.name = name;
        }

    public String toString()
        {
        return name + " : " + colour + " : " + caloriesPerGram;
        }

    // --------------------------- CONSTRUCTORS ---------------------------

    Food( final String name, final String colour, final float caloriesPerGram )
        {
        this.name = name;
        this.colour = colour;
        this.caloriesPerGram = caloriesPerGram;
        }
    }

// --------------------------- main() method ---------------------------

/**
 * Sample code to TEST HashMap Modifying
 *
 * @param args not used
 */
public static void main( String[] args )
    {
    // create a new HashMap
    HashMap<String, Food> h = new HashMap<String, Food>( 149
            /* capacity */,
            0.75f
            /* loadfactor */ );

    // add some Food objecs to the HashMap
    // see http://www.calorie-charts.net  for calories/gram
    h.put( "sugar", new Food( "sugar", "white", 4.5f ) );
    h.put( "alchol", new Food( "alcohol", "clear", 7.0f ) );
    h.put( "cheddar", new Food( "cheddar", "orange", 4.03f ) );
    h.put( "peas", new Food( "peas", "green", .81f ) );
    h.put( "salmon", new Food( "salmon", "pink", 2.16f ) );

    // (1) modify the alcohol key to fix the spelling error in the key.
    Food alc = h.get( "alchol" );
    h.put( "alcohol", alc );
    h.remove( "alchol" );

    // (2) modify the value object for sugar key.
    Food sug = h.get( "sugar" );
    sug.setColour( "brown" );
    // do not need to put.

    // (3) replace the value object for the cheddar key
    // don't need to get the old value first.
    h.put( "cheddar", new Food( "cheddar", "white", 4.02f ) );

    // (4) replace the value object for the peas key with object based on previous
    Food peas = h.get( "peas" );
    h.put( "peas", new Food( peas.getName(), peas.getColour(), peas.getCaloriesPerGram() * 1.05f ) );

    // enumerate all the keys in the HashMap in random order
    for ( String key : h.keySet() )
        {
        out.println( key + " = " + h.get( key ).toString() );
        }
    }// end main
}

I hope this helps

查看更多
三岁会撩人
5楼-- · 2020-01-29 07:27

You should keep information in other collection to modify it after iteration. You can only remove entry using iterator.remove() during iterator. HashMap contract forbids mutating it during iteration.

查看更多
爷的心禁止访问
6楼-- · 2020-01-29 07:30

i got to this thread when i needed to change the keys of the map entries. in my case i have a JSON representation in a Map , meaning it can hold map or list of maps, here is the code:

private Map<String,Object> changeKeyMap(Map<String, Object> jsonAsMap) throws InterruptedException {

    Map<String,Object> mapClone = new LinkedHashMap<>();
    for (Map.Entry<String, Object> entry : jsonAsMap.entrySet()) {
        if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
        Object value = entry.getValue();
        if (entry.getValue() instanceof Map) {
            value = changeKeyMap((Map) entry.getValue());
        } else if (isListOfMaps(entry.getValue())) {
            value = changeKeyListOfMaps((List<Map<String, Object>>) entry.getValue());
        }
        String changedKey = changeSingleKey(entry.getKey());
        mapClone.put(changedKey, value);
    }
    return mapClone;
}

private List<Map<String,Object>> changeKeyListOfMaps(List<Map<String,Object>> listOfMaps) throws InterruptedException {
    List<Map<String,Object>> newInnerMapList = new ArrayList<>();
    for(Object singleMapFromArray :listOfMaps){
        Map<String,Object> changeKeyedMap = changeKeyMap((Map<String, Object>) singleMapFromArray);
        newInnerMapList.add(changeKeyedMap);
    }
    return newInnerMapList;
}
private boolean isListOfMaps(Object object) {
    return object instanceof List && !((List) object).isEmpty() && ((List) object).get(0) instanceof Map;
}

private String changeSingleKey(String originalKey) {
    return originalKey + "SomeChange"
}
查看更多
登录 后发表回答