Как изменить значение в map java
Интерфейс Map представляет отображение или иначе говоря словарь, где каждый элемент представляет пару «ключ-значение». При этом все ключи уникальные в рамках объекта Map. Такие коллекции облегчают поиск элемента, если нам известен ключ — уникальный идентификатор объекта.
Следует отметить, что в отличие от других интерфейсов, которые представляют коллекции, интерфейс Map НЕ расширяет интерфейс Collection.
Среди методов интерфейса Map можно выделить следующие:
- void clear() : очищает коллекцию
- boolean containsKey(Object k) : возвращает true, если коллекция содержит ключ k
- boolean containsValue(Object v) : возвращает true, если коллекция содержит значение v
- Set> entrySet() : возвращает набор элементов коллекции. Все элементы представляют объект Map.Entry
- boolean equals(Object obj) : возвращает true, если коллекция идентична коллекции, передаваемой через параметр obj
- boolean isEmpty : возвращает true, если коллекция пуста
- V get(Object k) : возвращает значение объекта, ключ которого равен k. Если такого элемента не окажется, то возвращается значение null
- V getOrDefault(Object k, V defaultValue) : возвращает значение объекта, ключ которого равен k. Если такого элемента не окажется, то возвращается значение defaultVlue
- V put(K k, V v) : помещает в коллекцию новый объект с ключом k и значением v. Если в коллекции уже есть объект с подобным ключом, то он перезаписывается. После добавления возвращает предыдущее значение для ключа k, если он уже был в коллекции. Если же ключа еще не было в коллекции, то возвращается значение null
- V putIfAbsent(K k, V v) : помещает в коллекцию новый объект с ключом k и значением v, если в коллекции еще нет элемента с подобным ключом.
- Set keySet() : возвращает набор всех ключей отображения
- Collection values() : возвращает набор всех значений отображения
- void putAll(Map map) : добавляет в коллекцию все объекты из отображения map
- V remove(Object k) : удаляет объект с ключом k
- int size() : возвращает количество элементов коллекции
Чтобы положить объект в коллекцию, используется метод put , а чтобы получить по ключу — метод get . Реализация интерфейса Map также позволяет получить наборы как ключей, так и значений. А метод entrySet() возвращает набор всех элементов в виде объектов Map.Entry .
Обобщенный интерфейс Map.Entry представляет объект с ключом типа K и значением типа V и определяет следующие методы:
- boolean equals(Object obj) : возвращает true, если объект obj, представляющий интерфейс Map.Entry , идентичен текущему
- K getKey() : возвращает ключ объекта отображения
- V getValue() : возвращает значение объекта отображения
- V setValue(V v) : устанавливает для текущего объекта значение v
- int hashCode() : возвращает хеш-код данного объекта
При переборе объектов отображения мы будем оперировать этими методами для работы с ключами и значениями объектов.
Классы отображений. HashMap
Базовым классом для всех отображений является абстрактный класс AbstractMap , который реализует большую часть методов интерфейса Map. Наиболее распространенным классом отображений является HashMap , который реализует интерфейс Map и наследуется от класса AbstractMap.
Пример использования класса:
import java.util.*; public class Program < public static void main(String[] args) < Mapstates = new HashMap(); states.put(1, "Germany"); states.put(2, "Spain"); states.put(4, "France"); states.put(3, "Italy"); // получим объект по ключу 2 String first = states.get(2); System.out.println(first); // получим весь набор ключей Set keys = states.keySet(); // получить набор всех значений Collection values = states.values(); //заменить элемент states.replace(1, "Poland"); // удаление элемента по ключу 2 states.remove(2); // перебор элементов for(Map.Entry item : states.entrySet()) < System.out.printf("Key: %d Value: %s \n", item.getKey(), item.getValue()); >Map people = new HashMap(); people.put("1240i54", new Person("Tom")); people.put("1564i55", new Person("Bill")); people.put("4540i56", new Person("Nick")); for(Map.Entry item : people.entrySet()) < System.out.printf("Key: %s Value: %s \n", item.getKey(), item.getValue().getName()); >> > class Person < private String name; public Person(String value)< name=value; >String getName() >
Чтобы добавить или заменить элемент, используется метод put, либо replace, а чтобы получить его значение по ключу — метод get. С помощью других методов интерфейса Map также производятся другие манипуляции над элементами: перебор, получение ключей, значений, удаление.
Изменить значение элемента HashMap
Доброго времени суток, форумчане!
Подскажите пожалуйста, что не так
Делаю метод, который изменяет количество ингредиента по заданному имени ингредиента и количеству на которое нужно изменить, нижепредставленный метод меняет количество во всём HashMap storeSet
1 2 3 4 5 6 7 8 9 10 11 12
public void changeIngredientQuantityInStore(String inputName, long inputQuantity) { for (Ingredient ingr : storeSet) { if (ingr.getQuantity() - inputQuantity >= 0) { if (ingr.getName() == inputName) { long i = ingr.getQuantity() + inputQuantity; ingr.setQuantity(i); } } else { System.out.println(IConstants.INGREDIENT_NUMBER_LIMIT); } } }
1 2 3 4 5 6 7 8 9 10
public class Ingredient implements Serializable { public int Id; public String name; public long quantity; public Ingredient( int Id, String name, long quantity) { this.Id = Id; this.name = name; this.quantity = quantity; }
1 2 3 4 5 6 7 8 9 10 11 12 13
public class IngredientStore implements IterableIngredient> { private SetIngredient> storeSet = new HashSet(); public boolean ingredientPresentInStore; public void initializeStore() { storeSet.add(new Ingredient(1, "колбаса", 2000)); storeSet.add(new Ingredient(2, "сыр", 2000)); storeSet.add(new Ingredient(3, "грибы", 2000)); storeSet.add(new Ingredient(4, "майонез", 2000)); storeSet.add(new Ingredient(5, "лук", 2000)); storeSet.add(new Ingredient(6, "помидор", 1000)); }
Добавлено через 31 минуту
Люди! Есть кто живой?
Как изменить значение в map java
Всем доброго дня!
public static Map variableDictionary = new TreeMap (); . // Установить новое значение по заданному ключу public void setValue (String var, int value) < Set entries = variableDictionary.entrySet (); for (Map.Entry entry : entries) < if (entry.getKey () == var) < entry.setValue (value); break; > > >
Сделано согласно туториалу (Java 7):
With the entrySet view, it is also possible to change the value associated with a key by calling a Map.Entry’s setValue method during iteration (again, assuming the Map supports value modification to begin with). Note that these are the only safe ways to modify a Map during iteration; the behavior is unspecified if the underlying Map is modified in any other way while the iteration is in progress.
и все работает. Но терзают смутные сомнения: неужели для того, чтобы изменить значение, соответствующее ключу, надо перебирать всю коллекцию? А если в ней несколько сотен тысяч ключей? Как можно быстрее «выйти» на заданный ключ?
Приходиться заниматься гадостью — зарабатывать на жизнь честным трудом (Б.Шоу)
Re: Перебор коллекции для изменения
| От: | RomikT | |
| Дата: | 20.06.12 07:58 | |
| Оценка: | +1 | |
Здравствуйте, fplab, Вы писали:
F>и все работает. Но терзают смутные сомнения: неужели для того, чтобы изменить значение, соответствующее ключу, надо перебирать всю коллекцию? А если в ней несколько сотен тысяч ключей? Как можно быстрее «выйти» на заданный ключ?
variableDictionary.put(key, value);
А ваш код работать будет через раз потому что вы строки на == сравниваете.
Re[2]: Перебор коллекции для изменения
| От: | fplab | http://fplab.h10.ru http://fplab.blogspot.com/ |
| Дата: | 20.06.12 08:02 | |
| Оценка: |
Здравствуйте, RomikT, Вы писали:
RT>Здравствуйте, fplab, Вы писали:
F>>и все работает. Но терзают смутные сомнения: неужели для того, чтобы изменить значение, соответствующее ключу, надо перебирать всю коллекцию? А если в ней несколько сотен тысяч ключей? Как можно быстрее «выйти» на заданный ключ?
RT>
RT>variableDictionary.put(key, value); RT>
RT>?
RT>А ваш код работать будет через раз потому что вы строки на == сравниваете.
За указание на «= o m»> Приходиться заниматься гадостью — зарабатывать на жизнь честным трудом (Б.Шоу)
Re: Перебор коллекции для изменения
| От: | zubr |
| Дата: | 20.06.12 08:06 |
| Оценка: |
Здравствуйте, fplab, Вы писали:
F>Всем доброго дня!
F>Есть такой код
.
F>и все работает. Но терзают смутные сомнения: неужели для того, чтобы изменить значение, соответствующее ключу, надо перебирать всю коллекцию? А если в ней несколько сотен тысяч ключей? Как можно быстрее «выйти» на заданный ключ?
if (map.containsKey(key))
можно вот так. или я не понимаю.
Re: Перебор коллекции для изменения
| От: | DrDred | |
| Дата: | 20.06.12 08:42 | |
| Оценка: | +1 | |
Здравствуйте, fplab, Вы писали:
F>Всем доброго дня!
F>Есть такой код
F>Сделано согласно туториалу (Java 7):
F>
F>With the entrySet view, it is also possible to change the value associated with a key by calling a Map.Entry’s setValue method during iteration (again, assuming the Map supports value modification to begin with). Note that these are the only safe ways to modify a Map during iteration; the behavior is unspecified if the underlying Map is modified in any other way while the iteration is in progress.
F>и все работает. Но терзают смутные сомнения: неужели для того, чтобы изменить значение, соответствующее ключу, надо перебирать всю коллекцию? А если в ней несколько сотен тысяч ключей? Как можно быстрее «выйти» на заданный ключ?
Если аккуратно перевести на русский, особенно с учетом выделенного, мы видим, что в процессе перебора коллекции единственный валидный способ поменять значение — через setValue.
Но это не значит, что единственный способ поменять значение в Map — через прямой перебор ключей
—
WBR, Alexander
Re[3]: Перебор коллекции для изменения
| От: | RomikT |
| Дата: | 20.06.12 08:44 |
| Оценка: |
Здравствуйте, fplab, Вы писали:
F>А put не сработает. Если ключ key существует, то заменить его не получится
Работает, работает. Вы как-то неправильно проверяете.
Re[3]: Смеетесь или издеваетесь?
| От: | Skipy | http://www.skipy.ru |
| Дата: | 20.06.12 13:38 | |
| Оценка: |
Здравствуйте, fplab, Вы писали:
F>А put не сработает. Если ключ key существует, то заменить его не получится
Конкретно — описание возвращаемого put значения:
Returns:
the previous value associated with key, or null if there was no mapping for key.
Если значение уже было — оно возвращается. Если не было — возвращается null. Это описание означает, что предыдущее значение может быть.
Ну и в конце концов — проверьте на практике!
package ru.skipy.tests; import java.util.Map; import java.util.TreeMap; /** * MapTest * * @author Eugene Matyushkin aka Skipy * @since 20.06.12 */ public class MapTest < public static void main(String[] args) < Mapmap = new TreeMap<>(); map.put("key", "old value"); System.out.println(map); map.put("key", "new value"); System.out.println(map); > >
С уважением,
Евгений aka Skipy
www.skipy.ru
Re: Перебор коллекции для изменения
| От: | ResidentR6 |
| Дата: | 21.06.12 00:36 |
| Оценка: |
Map всего лишь интерфейс, он НИЧЕГО не делает!
TreeMap — сортированная реализация! В большинстве случаев эффективен
HashMap, практически всегда когда ключ — число или строка.
Откройте исходники Java и посмотрите реализацию если любопытно. Если
хотите сделать бенчмарк, скормите ему Войну и мир пословно,
удостоверьтесь в скорости HashMap.
Простой рецепт: используйте HashMap всегда.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Перебор коллекции для изменения
| От: | Eugeny__ |
| Дата: | 21.06.12 17:40 |
| Оценка: |
Здравствуйте, fplab, Вы писали:
RT>>variableDictionary.put(key, value); RT>>
RT>>?
RT>>А ваш код работать будет через раз потому что вы строки на == сравниваете.
F>За указание на «= o m»> Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Самый эффективный способ увеличить значение Map в Java – искать только один раз
Этот вопрос может считаться слишком простым, но его часто задают на форумах. В этом посте я расскажу об одном способе, который ищет только ключ в Map ONCE .
Давайте сначала посмотрим на пример. Скажем, я создаю список частоты строк, используя карту , где каждый ключ является строкой , которая подсчитывается, а значением является целое число, которое увеличивается каждый раз при добавлении строки . Прямой способ достижения этого
int count = map.containsKey(string) ? map.get(string) : 0 ;
map.put(string, count + 1 );
Этот фрагмент кода выполняется довольно медленно, потому что он содержит три потенциально дорогостоящих операции на карте, а именно содержит K.Key () , get () и [put ()] (http://docs.oracle.com/javase/7/docs/ api / java / util / Map.html # put (K, V)) . Каждый требует поиска ключа на карте. Теперь давайте проведем рефакторинг кода для повышения производительности.
Целое число против MutableInteger против AtomicInteger
Одна важная причина, по которой мы должны вызвать три дорогостоящие операции, – это использование Integer для подсчета. В Java Integer является неизменным . Это не позволяет нам изменять целочисленное значение после построения. Поэтому, чтобы увеличить счетчик, мы должны сначала получить целое число из карты, затем создать другое новое целое число, добавив его, и вернуть его обратно на карту.
Чтобы сделать счетчик изменчивым, есть несколько способов. Один из них – просто создать свой собственный MutableInteger , как показано ниже.
public class MutableInteger < private int val; public MutableInteger( int val) < this .val = val; public int get() < return val; public void set( int val) < this .val = val;
Другим способом может быть использование AtomicInteger в Java, который используется в приложениях, таких как счетчики с атомным приращением. Но основной выбор для AtomicInteger – если вы хотите добиться безопасности потоков с помощью операций с целым числом. Поэтому его нельзя использовать в качестве замены для целого числа. Исходя из этого, если потокобезопасность не является серьезным фактором для вашего проекта, я не рекомендую использовать AtomicInteger .
Поиск ключа только один раз
После использования MutableInteger мы можем изменить приведенный выше код на
if (map.containsKey(string)) < MutableInteger count = map.get(string); count.set(count.get() + 1 ); map.put(string, new MutableInteger( 1 )); MutableInteger count = map.get(string); if (count != null ) < count.set(count.get() + 1 ); map.put(string, new MutableInteger( 1 ));
В худшем случае, когда ключ не был виден раньше, код будет искать ключ дважды: один для получения, другой для установки. Это намного лучше, чем предыдущий. Но мы НЕ должны быть удовлетворены прямо сейчас и остановиться. Если вы проверили метод [Map.put ()] (http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#put (K, V)) в документе Java, вы обнаружите, что этот метод вернет the previous value associated with key . Это означает, что мы можем объединить получение и настройку в одно. Однако вы можете задаться вопросом: если мы не получим счетчик первым, как мы можем установить новый счетчик? Теперь мы наконец-то коснемся самой сложной части этого поста: мы можем упростить установку счетчика нулевой частоты !
public int incrementCount(K key, int count) < MutableInteger tmpCount = new MutableInteger( 0 ); MutableInteger oldCount = map.put(key, tmpCount); if (oldCount != null ) < count += oldCount.get(); tmpCount.set(count); return count;
Еще один счетчик
Похоже, что помещение всех необходимых операций в класс будет полезным для будущего использования. Поэтому я создаю класс Counter и делаю его общедоступным. Счетчик определяет коллекцию, которая подсчитывает, сколько раз объект появляется в коллекции. Предположим, у вас есть счетчик, который содержит . Вызов getCount () для «a» вернет 2, в то время как вызов keySet () вернет . Этот класс работает как Map , но с различными методами для простого получения / установки / увеличения количества объектов и вычисления различных функций с помощью счетчика. Конструктор Counter и метод addAll () могут использоваться для копирования содержимого другого Counter. Класс Counter изменяется в соответствии с IntCounter и AbstractMapBag .
Некоторые выделенные операции на счетчике включают
- incrementCount () и decmentCount () : Добавляет / вычитает данное количество к текущему числу для данного ключа. Если ключ не был виден раньше, предполагается, что он имеет счетчик 0, и, таким образом, метод приращения установит его счетчик на заданную сумму. Для декремента будет установлено значение -1.
- getCount () : возвращает текущий счетчик для данного ключа, который равен 0, если его раньше не видели.
- keysAt () , keysAbove () и keysBelow () : возвращает набор ключей, число которых равно , выше или ниже заданного порогового значения. Этот набор может иметь 0 элементов, но не будет нулевым.
- argmin () и argmax () : находит и возвращает ключ в этом счетчике с наименьшим / наибольшим числом. Если имеется несколько минимальных / максимальных значений, возвращается случайное значение. Возвращает ноль, если этот счетчик пуст.
