Перечень Java, содержащий хэш-карту для поиска

У меня есть следующее перечисление. Мне нужно получить описание по коду. Он работает, но его можно еще улучшить?

public enum Maps {

    COLOR_RED("ABC", "abc description");

    private final String code;
    private final String description;
    private static Map<String, String> mMap;

    private Maps(String code, String description) {
        this.code = code;
        this.description = description;
    }
    public String getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }


    public static String getDescriptionByCode(String code) {
        if (mMap == null) {
            initializeMapping();
        }
        if (mMap.containsKey(code)) {
            return mMap.get(code);
        }
        return null;
    }

    private static void initializeMapping() {
        mMap = new HashMap<String, String>();
        for (Maps s : Maps.values()) {
            mMap.put(s.code, s.description);
        }
    }
}
29 голосов | спросил user755806 3 PMpThu, 03 Apr 2014 15:17:33 +040017Thursday 2014, 15:17:33

5 ответов


29

Ваш код очень аккуратный и чистый, есть только одна вещь, которую я бы изменил:

private static Map<String, String> mMap;

к

private static final Map<String, String> mMap = Collections.unmodifiableMap(initializeMapping());

Причины:

  1. Не объявляя его окончательным и не используя вызов unmodifiableMap, он изменен, и было бы возможно изменить ссылку с помощью отражения или использовать .remove("ABC") на карте. Объявив его окончательным, убедитесь, что ссылочная карта не может быть изменена и немодифицируемаMap гарантирует, что никакие изменения не могут быть сделаны с самой картой.

  2. Многопоточные проблемы. Как и в настоящее время, если два потока будут вызывать метод getDescriptionByCode в то же время, вы бы дважды инициализировали отображение, что не нужно.

Это также, конечно, требует небольшого изменения в initializeMapping():

private static Map<String, String> initializeMapping() {
    Map<String, String> mMap = new HashMap<String, String>();
    for (Maps s : Maps.values()) {
        mMap.put(s.code, s.description);
    }
    return mMap;
}

Кроме того, все выглядит хорошо. Молодцы!

ответил Simon Forsberg 3 PMpThu, 03 Apr 2014 15:41:10 +040041Thursday 2014, 15:41:10
21

Вы можете изменить

if (mMap.containsKey(code)) {
    return mMap.get(code);
}
return null;

к

return mMap.get(code);

, поскольку HashMap.get() возвращает null, нет такого ключа на карте.

ответил palacsint 3 PMpThu, 03 Apr 2014 16:06:11 +040006Thursday 2014, 16:06:11
13

Это может быть только вопросом предпочтения, но мне кажется более полезным, чтобы карта хранила экземпляр Maps, а не описание напрямую, потому что тогда вы также получаете бесплатно способность находить другую информацию (имя записи перечисления, ее порядковое значение и т. д.). Возможно, вам это не понадобится, но, поскольку это очень просто сделать, я определенно буду считать это лучше.

ответил Jules 3 PMpThu, 03 Apr 2014 17:52:42 +040052Thursday 2014, 17:52:42
5

Прежде всего, имена в вашем коде не очень ясны. Что означает Maps? почему COLOR_RED, и почему это связанный код ABC? У вас есть только одно значение в перечислении?

Возможно, это всего лишь пример кода, но это довольно сложно проанализировать.

Например, если ваше значение было названо ABC, вы можете просто вызвать Maps.valueOf("ABC"), чтобы связать перечисление и получить соответствующее описание без необходимо иметь внутреннюю карту.

Конечно, если вам нужны как Colors, так и Codes, вам придется как-то связать их. Но почему даже используют Strings ? Возможно, у вас может быть другое перечисление, называемое Colors (определяющее COLOR_RED), так что связь между цветом и кодом выполняется только с использованием перечисляемых типов.

Я не писал на Java некоторое время, но если я правильно помню, EnumMap s (например, от Colors до Codes и наоборот) очень эффективны (например, целые индексы в массиве); кроме того, switch case over enums также более эффективны и обеспечивают больше обратной связи от компилятора: статический анализ может рассказать вам, учитываете ли вы все возможные перечисления или нет; это упрощает ваш код, потому что вам не нужно беспокоиться об ошибке.

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

Надеюсь, что это поможет.

ответил coredump 3 PMpThu, 03 Apr 2014 18:21:18 +040021Thursday 2014, 18:21:18
4

Для этого класса ленивая инициализация приносит слишком мало преимуществ по сравнению с усложнением, которое он добавляет. У вас есть только один член в перечислении, и каждый член перечисления тривиально прост в построении. Поэтому вы должны заполнить карту во время загрузки класса, используя статический блок инициализатора. (В качестве бонуса гарантируется, что инициализация происходит только один раз, так что это потокобезопасно.)

public enum Maps {

    COLOR_RED("ABC", "abc description");

    private final String code;
    private final String description;

    private static final Map<String, String> MAP = new HashMap<String, String>();
    static {
        for (Maps s : Maps.values()) {
            MAP.put(s.code, s.description);
        }
    }

    private Maps(String code, String description) {
        this.code = code;
        this.description = description;
    }                                                                                                                               

    public String getCode() {                                                                                                       
        return code;                                                                                                                
    }                                                                                                                               

    public String getDescription() {                                                                                                
        return description;                                                                                                         
    }                                                                                                                               

    public static String getDescriptionByCode(String code) {                                                                        
        return MAP.get(code);
    }
}

Кроме того, если COLOR_RED не имеет никакого полезного значения, а строки кода также являются действительными идентификаторами Java, рассмотрите возможность использования самого кода как имени каждого члена перечисления. У перечислений уже есть возможность искать членов по имени, поэтому вы можете воспользоваться этим механизмом.

public enum SimplerMap {                                                                                                            

    ABC("abc description");

    private final String description;                                                                                               

    private SimplerMap(String description) {                                                                                        
        this.description = description;                                                                                             
    }                                                                                                                               

    public String getCode() {
        return this.toString();                                                                                                     
    }                                                                                                                               

    public String getDescription() {
        return this.description;                                                                                                    
    }                                                                                                                               

    public static String getDescriptionByCode(String code) {
        try {
            return valueOf(code).getCode();
        } catch (IllegalArgumentException noSuchCode) {
            return null;
        }
    }
}
ответил 200_success 4 AMpFri, 04 Apr 2014 09:36:17 +040036Friday 2014, 09:36:17

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132