Подтвердить что ты не робот

Преимущества использования Enums over Collections

Я пытаюсь проверить, соответствует ли тип учетной записи пользователя одному из нескольких Strings.

В офисе обсуждается вопрос о том, должно ли оно быть представлено как enum с каждой записью, содержащей другую строку, или как Set of Strings. Хотя Set может быть более эффективным, перечисление может быть стилистически превосходным, поскольку он более ясен, он используется для логического потока.

В чем преимущества этих двух подходов?

4b9b3361

Ответ 1

Действительно, a Set<String> более эффективен с точки зрения производительности при поиске. Тем не менее, я бы не ожидал, что у вас тысячи типов учетных записей, но несколько, поэтому вы не почувствуете разницу при поиске. Однако есть одна проблема с этим подходом: вы сможете добавить любой String в Set, который является хрупким.

Мои личные предпочтения будут состоять в использовании enum, особенно если вы не ожидаете, что будут введены дополнительные типы учетных записей. И если у вас есть Set<AccountType>, вы будете ограничены значениями, которые вы можете добавить (т.е. Вы сможете добавлять типы только, но не что-то вроде подхода с Set<String>). Проблема с этим подходом заключается в Open/Closed Principle - рассмотрим, что вы имеете инструкцию switch по переменной AccountType со всеми соответствующими case s. Затем, если вы введете константу new AccountType, вы должны изменить оператор switch (с добавлением нового case), который нарушает принцип "Открытый/Закрытый". В этом случае наилучшим вариантом будет иметь abstract class/interface, называемый AccountType, который имеет все определенные типы учетных записей в качестве подклассов.

Итак, есть несколько подходов, за которыми вы можете следовать, но прежде чем выбрать один, вы должны попробовать ответить на вопрос "Как мы его будем использовать?"

Ответ 2

Перечисление будет лучше, поскольку типы учетных записей (обычно) не изменяются динамически. Кроме того, использование перечисления делает типы более точными - например, нет способа перепутать "Hello, World!" с типом учетной записи.

Ответ 3

Перечисления велики, потому что вы проверяете время компиляции. Недопустимые значения просто не будут компилироваться, поэтому он "не быстро".

Коллекция строк отлично подходит, если вы хотите добавить еще один вариант без компиляции/выпуска новой версии вашего приложения. Если, например, допустимые параметры были настроены в таблице базы данных.

Ответ 4

Следует отметить, что метод enum valueOf(String) реализован с использованием метода Enum.valueOf(Class,String), который, в свою очередь, реализуется с помощью HashMap.

В основном это означает, что поиск типа учетной записи из строки с помощью AccountTypes.valueOf() является операцией O (1) и такой же эффективной, как и заданная операция. Затем вы можете использовать возвращаемое значение (фактический объект перечисления) в программе, с полной безопасностью типа, более быстрыми сравнениями и всеми другими преимуществами перечисления.

Ответ 5

Мне кажется, что проблема заключается в том, что вы используете строку для представления данных, которые могут иметь только несколько действительных известных значений. Набор может быть полезен для проверки правильности строкового значения, но это не мешает ему стать недействительным.

Мое предложение состоит в том, чтобы определить перечисление с действительными типами учетных записей и использовать это вместо строк. Если у вас есть вход, исходящий извне, представляющий тип учетной записи, тогда ставьте метод на перечисление типа "fromString", который возвращает соответствующий экземпляр enum, тем самым сокращая окно, в котором недопустимые данные будут рассмотрены.

Вы можете создать Set из экземпляров AccountType enum, если вы реализуете соответствующие методы Comparator, compareTo или hashCode (в зависимости от того, использовались ли вы TreeSet или HashSet) и т.д..). Это может быть полезно, если у вас есть классификации типов учетных записей, которые необходимо проверить. Например, если есть "Локальные администраторы", "Глобальные админы" и "Администраторы безопасности", вы можете определить метод isAdmin(AccountType t), который ищет Set AccountTypes. Например:

private Set<AccountType> ADMIN_ACCOUNT_TYPES = new HashSet<AccountType>() {{
    add(AccountType.LOCAL_ADMIN);
    add(AccountType.GLOBAL_ADMIN);
    add(AccountType.SECURITY_ADMIN);
}};

public boolean isAdmin(AccountType t) {
    return ADMIN_ACCOUNT_TYPES.contains(t);
}

Теперь, если у вас есть случай, когда есть много разных типов учетных записей, со многими группировками, а производительность поисковых запросов вызывает беспокойство, так вы можете это решить.

Хотя, если честно, если у вас есть только несколько типов учетных записей, и они редко меняются, это может немного переработать. Если существует только 2 типа учетных записей, простая инструкция if с проверкой равенства будет более эффективной, чем поиск в хэш-таблице.

Опять же, производительность здесь не может быть проблемой. Не переопределяйте и не оптимизируйте преждевременно.

Ответ 6

По моему опыту, я предлагаю использовать перечисление в этом случае. Даже mysql поддерживает перечисление для случаев использования, когда вы хотите, чтобы столбец принимал значения из явно объявленного списка.

Ответ 7

Я бы использовал Map<String,Enum> = new HashMap<>(); для максимальной эффективности.