У меня проблема, аналогичная обсуждаемой здесь , но с более сильным практическим использованием.
Например, у меня есть Map<String, Integer>
, и у меня есть некоторая функция, которой присваивается ключ, и в случае, если отображаемое целочисленное значение является отрицательным, помещает NULL
на карту:
Map<String, Integer> map = new HashMap<String, Integer>();
public void nullifyIfNegative(String key) {
Integer value = map.get(key);
if (value != null && value.intValue() < 0) {
map.put(key, null);
}
}
В этом случае поиск (и, следовательно, hashCode
вычисление для ключа) выполняется дважды: один для поиска и один для замены. Было бы неплохо иметь другой метод (который уже есть в HashMap
) и позволяет сделать это более эффективным:
public void nullifyIfNegative(String key) {
Map.Entry<String, Integer> entry = map.getEntry(key);
if (entry != null && entry.getValue().intValue() < 0) {
entry.setValue(null);
}
}
То же самое касается случаев, когда вы хотите манипулировать неизменяемыми объектами, которые могут быть значениями карты:
Map<String, String>
: я хочу добавить что-либо к строковому значению.
Map<String, int[]>
: я хочу вставить число в массив.
Так что дело довольно распространенное. Решения, которые могут работать, но не для меня:
- Отражение. Это хорошо, но я не могу пожертвовать производительностью только ради этой замечательной функции.
- Используйте
org.apache.commons.collections.map.AbstractHashedMap
(он имеет по крайней мере protected getEntry()
метод), но, к сожалению, коллекции commons не поддерживают дженерики.
- Используйте универсальные коллекции-сборники , но эта библиотека (AFAIK) устарела (не синхронизируется с последней версией библиотеки от Apache) и (что важно) недоступна в центральном хранилище maven.
- Использовать упаковщики значений, что означает «превращение значений в изменяемые» (например, использовать изменяемые целые числа [например,
org.apache.commons.lang.mutable.MutableInt
] или коллекции вместо массивов). Это решение приводит к потере памяти, чего я хотел бы избежать.
- Попробуйте расширить
java.util.HashMap
с помощью пользовательской реализации класса (которая должна быть в пакете java.util
) и поместить ее в одобренную папку (так как java.lang.ClassLoader
откажется загружать ее в Class<?> defineClass(String name, byte[] b, int off, int len)
, см. источники), но я не хочу исправлять JDK, и похоже, что список пакетов, которые могут быть одобрены, не включает java.util
.
Подобный вопрос уже поднимался на багтрекер sun.com , но я хотел бы знать, каково мнение сообщества и что может быть выходом с учетом максимальной памяти и производительности эффективность.
Если вы согласны, это полезная и полезная функция, пожалуйста, оцените эту ошибку!