Повышенная безопасность типов в коллекциях Java

StackOverflow https://stackoverflow.com/questions/2516080

  •  22-09-2019
  •  | 
  •  

Вопрос

В моем java-кодировании я часто получаю несколько Map<String,Map<String,foo>> или Map<String,List<String>> и тогда мне становится трудно вспомнить, какая строка является ключом.Я комментирую это заявление следующим образом //Map<capabiltyId,Map<groupId,foo>> или //Map<groupId,List<capabilityId>, но это не самое лучшее решение.Если бы String не был окончательным, я бы создал новые классы CapabilityId extends String и GroupId extends String, но я не могу.Есть ли лучший способ отслеживать, какая вещь является ключом, и, возможно, заставить компилятор применить ее?

Это было полезно?

Решение

Вместо того, чтобы иметь CapabilityId продлевать String, CapabilityId мог бы включать String поле под названием «id»;тогда твой Map можно определить как Map<CapabilityId, Map<GroupId, Foo>>, и вы можете получить доступ к отдельным полям идентификатора через getId() на ваших ключевых занятиях.

Я не уверен, что сделал бы это сам, но если бы я это сделал, вероятно, я бы сделал именно это.

Вы можете ограничить беспорядок, установив abstract GenericId класс с полем id и getId() метод и иметь CapabilityId и GroupId наследовать от него.

Другие советы

Оберните строки в классы-оболочки, если хотите:

class GroupId implements Comparable {
   private String groupId;

   public GroupId (String groupId) {
       this.groupId = groupId;
   }
   ...
}

Map<GroupId, List<CapabilityId>> m = ...

Создать ID класс, который вы можете подклассифицировать и который состоит из String области и реализации equals() и hashCode() которые используют это поле.

Я бы поместил все это в один класс и использовал разумные имена полей/методов/аргументов.

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..
}

Таким образом, вы можете увидеть в именах методов/аргументов то, что он ожидает/возвращает.

Есть несколько способов сделать это (некоторые уже упоминались):

  • Как и @Roman, оберните тип общего назначения в более конкретный тип, который обеспечивает более строгую типизацию.Строгая типизация хороша, ИМХО.
  • В качестве @nanda используйте более конкретный тип коллекции.Библиотека Java в этой области немного скудна.Это зависит от того, как вы относитесь к зависимостям.
  • В роли @BalusC переместите все неприятные вещи в неприятный класс.На самом деле проблему не устраняет, но сдерживает ее (как в «Охотниках за привидениями»).
  • Map<String,Map<String,foo>> очень похоже, что у вас составной ключ, т.е.ключ, состоящий из двух частей.Итак, представьте неизменяемый класс составного ключа, который представляет собой объект значения, представляющий два объекта значения компонента.

Вместо Map<String,List<String>> вам следует использовать Multimap из Google Guava/Google Collection

http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/Multimap.html

Добавление к другим ответам:

Заверните это.

Это не просто решение вашей проблемы, но и хорошая идея в целом, т.е.избегайте простых параметров.Ваш код станет удобочитаемым, разумным и ремонтопригодным.Вы можете добавить к нему всевозможные приятные свойства, напримеробъявите его @Неизменяемым.Как вы выяснили, этот способ лучше запоминать и контролировать.Вы владеете классом и можете делать с ним все, что вам заблагорассудится.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top