#java #map
#java #словарь
Вопрос:
Я часто вижу списки объектов в java, содержащих компоненты, объекты которых выбираются путем проверки поля ID, т. Е.
List<BeanObj> list = …
BeanObj myObj = null;
for(BeanObj b : list)
if(b.getId().equals(whatIAmLookingFor)){
myObj = b;
break;
}
(Второй вариант этого — сохранение объектов в режиме гибернации и извлечение их с помощью SQL.)
Здесь действительно было бы разумно использовать интерфейс Map, но есть трудности, т.е.
- ключевое поле может быть изменено (в целом или даже одновременно)
- доступ к ключу может быть нетривиальным (подумайте о
b.getRoot().getAttribute("id").equals(…)
Существовали ли подходы для решения этой проблемы более эффективным способом, например, реализация
SpecialMap<String, BeanObj>("id") // use String getId() on BeanObj
или даже
SpecialMap<String, BeanObj>("getRoot().getAttribute({0})", "id")
// use String getAttribute("id") on result of getRoot()
с помощью add() вместо put(), который использует функцию получения идентификатора для построения своей внутренней карты? Вероятно, эта карта потребует от отображаемых объектов реализации некоторого интерфейса, позволяющего карте получать уведомления об обновлениях поля id.
Возможно, map могла бы также позаботиться о том, чтобы изменение идентификатора объекта на идентификатор существующего объекта либо было невозможно, либо приводило к удалению объекта, у которого ранее был этот идентификатор.
Ответ №1:
Вы можете управлять функциональным аспектом добавления элемента к вашей карте с помощью утилит guava:
import com.google.common.base.Function;
public class SpecialMap<K, V> extends HashMap<K, V>{
private Function<V, K> function;
public SpecialMap(Function<V, K> function) {
this.function = function;
}
public void add(V value) {
K key = function.apply(value);
this.put(key, value);
}
public static void main(String[] args) {
SpecialMap<String, BeanObj> specialMap = new SpecialMap<String, BeanObj>(new Function<BeanObj, String>() {
@Override
public String apply(BeanObj arg) {
return arg.getRoot().getAttribute("id");
}
});
specialMap.add(new BeanObj());
}
}
В этом примере функция сопоставит ваш тип компонента со строковым ключом.