当前位置:天才代写 > tutorial > JAVA 教程 > Java列举的反向查找

Java列举的反向查找

2017-11-02 08:00 星期四 所属: JAVA 教程 浏览:1253

副标题#e#

java的列举经常被用来替代常量值,每个列举值代表一个特定的常数。

在反序列化时有经常需要用到常数到列举的转换,这就涉及到列举的反向查找。

1、从列举名反向查找列举

这种要领是最先利用也最为轻便的

可以用到列举的静态要领valueOf(String name)

valueOf要领为内置要领,利用轻便,但在查找不到列举时会抛出异常。

熟悉异常的同学大概知道异常抛出时,需要收集虚拟机的挪用仓库上下文信息,对机能影响较大。

利用时,经常需要利用这么一个反序列化查找要领

E find(String name, E defaultValue),在查找不到时可以或许返回一个默认值而不是抛出异常

2、从列举值所包括的描写值反向查找列举

譬喻这种列举界说

public enum SomeEnum{
    A("ADes", 1),
    B("BDes", 2),
    unknown("UNKNWONDes", 3);
     
    private string des;
    private int order;
     
    private SomeEnum(string des, int order){
        this.des = des;
        this.order = order;
    }
}

此时可以在列举类中增加一个HashMap,并在类加载时初始化好。

public enum SomeEnum{
    A("ADes"),
    B("BDes"),
    unknown("UNKNWONDes");
     
    private string des;
     
    private static final map lookup = new hashmap();
     
    static {
        for(SomeEnum e : EnumSet.allOf(SomeEnum.class)){
            lookup.put(e.des, e);
        }
    }
     
    private SomeEnum(string des){
        this.des = des;
    }
     
    public static SomeEnum find(string des, SomeEnum defaultValue){
        SomeEnum value = lookup.get(des);
        if(value == null){
            return defaultValue;
        }
        return value;
    }
}

3、进一步,假如列举中有多个描写值,而且描写值范例纷歧样

这时初始化代码和查找代码需要写多遍。

public enum SomeEnum{
    A("ADes", 1),
    B("BDes", 2),
    unknown("UNKNWONDes", 3);
     
    private string des;
    private int order;
     
    private static final map lookup = new hashmap();
     
    private static final map lookup_int = new hashmap();
     
    static {
        for(SomeEnum e : EnumSet.allOf(SomeEnum.class)){
            lookup.put(e.des, e);
            lookup_int.put(e.order, e);
        }
    }
     
    private SomeEnum(string des, int order){
        this.des = des;
        this.order = order;
    }
     
    public static SomeEnum find(string des, SomeEnum defaultValue){
        SomeEnum value = lookup.get(des);
        if(value == null){
            return defaultValue;
        }
        return value;
    }
     
    public static SomeEnum find(int order, SomeEnum defaultValue){
        SomeEnum value = lookup_int.get(order);
        if(value == null){
            return defaultValue;
        }
        return value;
    }
}

不少代码有反复,

列举类需要本身实现反向查找映射干系在HashMap中的初始化。

按照DRY原则,反复代码处所一般都有必然的坏味道。

查察本栏目


#p#副标题#e#

4、改造

列举的反向查找其实只需存眷两件工作,

a 提供列举值描写到列举值的映射

b 能从列举值描写查找到列举值,查找不到能提供默认值

据此,可以提炼出列举反向查找的辅佐类:

public class EnumFindHelper<T extends Enum<T>, K> {
    protected Map<K, T> map = new HashMap<K, T>();
     
    public EnumFindHelper(Class<T> clazz, EnumKeyGetter<T, K> keyGetter) {
        try {
            for (T enumValue : EnumSet.allOf(clazz)) {
                map.put(keyGetter.getKey(enumValue), enumValue);
            }
        } catch (Exception e) {
            //eror handler
        }
    }
     
    public T find(K key, T defautValue) {
        T value = map.get(key);
        if (value == null) {
            value = defautValue;
        }
        return value;
    }
}

这里需要一个接口界说:

public static interface EnumKeyGetter<T extends Enum<T>, K> {
     
        K getKey(T enumValue);
     
}

查找辅佐类EnumFindHelper结构时需要EnumKeyGetter来提供列举值到列举范例的的对应干系。

界说列举类时实现EnumKeyGetter接口,并传入EnumFindHelper。

修改后的列举界说大概为:

public enum SomeEnum{
    A("ADes", 1),
    B("BDes", 2),
    unknown("UNKNWONDes", 3);
     
    private String des;
    private int order;
     
    private SomeEnum(string des, int order){
        this.des = des;
        this.order = order;
    }
     
    static final EnumFindHelper<SomeEnum, String> desptHelper = new EnumFindHelper<SomeEnum, String>(
        SomeEnum.class, new DesptGetter());
             
    static final EnumFindHelper<SomeEnum, Integer> orderHelper = new EnumFindHelper<SomeEnum, Integer>(
        SomeEnum.class, new OrderKeyGetter());
     
    static class DesptGetter implements EnumKeyGetter<SomeEnum, String> {
        @Override
        public String getKey(SomeEnum enumValue) {
            return enumValue.des;
        }
    }
         
    static class OrderKeyGetter implements EnumKeyGetter<SomeEnum, Integer> {
        @Override
        public String Integer(SomeEnum enumValue) {
            return enumValue.order;
        }
    }
         
    public static SomeEnum find(string despt, SomeEnum defaultValue){
        return desptHelper.find(des, defaultValue);
    }
     
    public static SomeEnum find(int order, SomeEnum defaultValue){
        return orderHelper.find(des, defaultValue);
    }
}

EnumFindHelper内部类的界说有些繁琐,不外java8之后用lambda实现后会轻便一些。

5 总结

每个列举类的反向查找成果委托一个辅佐类来实现,从列举类的结构上来看,较量雷同GOF的桥接模式。

而从委托类的实现查找成果来看,需要一个EnumKeyGetter接口,每种差异的接话柄现差异的查找方法,有按照描写字符查找,有按照列举顺序值查找。

这又有些雷同GOF的计策模式。

虽然不需要去纠结于哪种设计模式,代码的设计就是要求代码不冗余,成果的重用,依赖的解耦。

上面的设计中:

1)操作EnumFindHelper做到列举查找的算法重用,操作一个map提供列举描写到列举值的查找。

2)EnumFindHelper初始化时需要结构好查找用的map,所以会依赖于详细的列举界说。

这里抽象出EnumKeyGetter,EnumFindHelper由依赖于详细的列举类改为依赖于EnumKeyGetter接口,在结构时注入了EnumKeyGetter的实现。

这么看起来是不是有些DPI(依赖注入)的感受?!

 

    关键字:

天才代写-代写联系方式