В моем кодировании Java я часто заканчиваю с несколькими Map<String,Map<String,foo>>
или Map<String,List<String>>
и затем я испытываю затруднения при запоминании, который Строка который ключ. Я комментирую объявление с //Map<capabiltyId,Map<groupId,foo>>
или //Map<groupId,List<capabilityId>
, но это не самое большое решение. Если бы Строка не была окончательной, то я сделал бы новые классы CapabilityId extends String
и GroupId extends String
, но я не могу. Существует ли лучший способ отслеживать, которых вещью является ключ, и, возможно, имейте компилятор, осуществляют его?
Вместо того, чтобы CapabilityId
расширять String
, CapabilityId
может включать поле String
под названием "id"; тогда ваша Map
может быть определена как Map
, и вы можете получить отдельные поля ID через getId()
для ваших ключевых классов.
Я не уверен, что сделал бы это сам, но если бы сделал, то, вероятно, поступил бы следующим образом.
Вы можете ограничить беспорядок, создав абстрактный класс GenericId
с полем id и getId()
методом, и пусть CapabilityId
и GroupId
наследуются от него.
Создайте класс ID
, который вы можете создать в качестве подкласса и который состоит из поля String
и реализаций equals ()
и hashCode ()
, которые используют это поле.
Есть несколько способов перейти к этому (некоторые уже упоминались):
Map >
очень похоже на составной ключ, то есть ключ, состоящий из двух частей. Итак, представьте неизменяемый составной ключевой класс, то есть объект значения, представляющий два объекта значений компонента. Вместо Map
следует использовать Multimap из Google Guava / Google Collection
Оберните строки в классы-обертки, если хотите:
class GroupId implements Comparable {
private String groupId;
public GroupId (String groupId) {
this.groupId = groupId;
}
...
}
Map<GroupId, List<CapabilityId>> m = ...
Добавление к другим ответам:
Оберните его.
Это не просто решение вашей проблемы, а хорошая идея в целом, т. Е. Избегайте простых параметров . Ваш код станет читаемым, понятным и удобочитаемым. Вы можете добавлять в него все виды хороших свойств, например объявите это @Immutable. Как вы выяснили, этот способ лучше запомнить и контролировать. Вы владеете классом и можете делать с ним все, что захотите.
Я бы поместил все это в один класс и использовал разумные имена полей / методов / аргументов.
public class GroupCapabilities {
private Map<String, Map<String, Group>> groupCapabilities;
public void addGroup(String capabilityId, Group group) {
Map<String, Group> groups = groupCapabilities.get(capabilityId);
if (groups = null) {
groups = new HashMap<String, Group>();
groupCapabilities.put(capabilityId, group);
}
groups.put(group.getId(), group);
}
public Map<String, Group> getGroups(String capabilityId) {
return groupCapabilities.get(capabilityId);
}
public Group getGroup(String capabilityId, String groupId) {
Map<String, Group> groups = groupCapabilities.get(capabilityId);
return (groups != null) ? groups.get(groupId) : null;
}
// Etc..
}
Таким образом, вы можете увидеть в именах метода / аргумента, что он ожидает / возвращает.