Изменение ключей HashMap во время итерации

можно ли изменить ключи одного и того же экземпляра HashMap во время итерации? Поскольку в наборе записей карты нет метода entry.setKey(). Теперь я могу придумать еще один 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());
    }
}

person lisak    schedule 21.11.2010    source источник


Ответы (5)


Вы должны хранить информацию в другой коллекции, чтобы изменить ее после итерации. Вы можете удалить запись только с помощью iterator.remove() во время итератора. HashMap контракт запрещает изменять его во время итерации.

person Chandra Patni    schedule 21.11.2010
comment
Вы не можете никогда изменить значение ключа на карте. - person user207421; 21.11.2010
comment
Итак, с точки зрения производительности, решение, которое у меня есть, в порядке? Потому что будут тысячи этих звонков в час - person lisak; 21.11.2010
comment
@EJP то, что я здесь меняю, это только ключи карты - person lisak; 21.11.2010
comment
Это моя точка зрения. Вы не можете изменить значение ключевого объекта на карте. См. Javadoc для карты. - person user207421; 21.11.2010

Возможно, это поможет:

map.put(newkey,map.remove(oldkey));
person Tolga Yılmaz    schedule 13.04.2013
comment
Если я перебираю набор ключей, будет ли этот вновь добавленный ключ отображаться в существующем наборе ключей? - person Ring; 23.04.2015

Есть четыре распространенных типа модификации, которые вы можете захотеть сделать с ключами или значениями в HashMap.

  1. Чтобы изменить ключ HashMap, вы ищете объект значения с помощью get, затем удаляете старый ключ и помещаете его с новым ключом.
  2. Чтобы изменить поля в объекте значения, найдите объект значения по ключу с помощью get, а затем используйте его методы установки.
  3. Чтобы полностью заменить объект-значение, просто поместите новый объект-значение на старый ключ.
  4. Чтобы заменить объект-значение на объект, основанный на старом, найдите объект-значение с помощью get, создайте новый объект, скопируйте данные из старого, а затем поместите новый объект под тот же ключ.

Что-то вроде этого примера.

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
}

надеюсь, это поможет

person Tejas    schedule 21.11.2010

Лучше всего скопировать карту в новую с нужными модификациями, затем вернуть эту новую карту и уничтожить старую. Интересно, каково влияние этого решения на производительность.

person Elemental    schedule 13.08.2014

я добрался до этой темы, когда мне нужно было изменить ключи записей карты. в моем случае у меня есть представление JSON на карте, что означает, что он может содержать карту или список карт, вот код:

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"
}
person Robocide    schedule 07.04.2019