精华内容
下载资源
问答
  • Java Enum是一个非常...问题很简单:我们应该如何通过名称或值获取枚举,并忽略不存在的值?枚举这是我们将在示例中使用的枚举。 挑选更复杂的枚举是为了也可以通过其他字段展示查找枚举。public enum CardColor {...

    Java Enum是一个非常有用的功能,但很多人通常并不能充分利用,这是因为一些库不会优先择用该功能。通常我们也可以正确使用Java枚举功能,但在许多代码库中往往存在着这样一个问题,于是有了这篇文章。问题很简单:我们应该如何通过名称或值获取枚举,并忽略不存在的值?

    枚举

    这是我们将在示例中使用的枚举。 挑选更复杂的枚举是为了也可以通过其他字段展示查找枚举。

    public enum CardColor {
        RED,
        BLACK,
        ;
    }
    // Jackson annotation to print the enum as an Object instead of the default name.
    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum CardSuit {
        // Unicode suits - https://en.wikipedia.org/wiki/Playing_cards_in_Unicode
        SPADE("Spade", String.valueOf((char) 0x2660), CardColor.BLACK),
        HEART("Heart", String.valueOf((char) 0x2665), CardColor.RED),
        DIAMOND("Diamond", String.valueOf((char) 0x2666), CardColor.RED),
        CLUB("Club", String.valueOf((char) 0x2663), CardColor.BLACK),
        ;
        private String displayName;
        private String symbol;
        private CardColor color;
        private CardSuit(String displayName, String symbol, CardColor color) {
            this.displayName = displayName;
            this.symbol =  symbol;
            this.color = color;
        }
        public String getDisplayName() {
            return displayName;
        }
        public void setDisplayName(String displayName) {
            this.displayName = displayName;
        }
        public String getSymbol() {
            return symbol;
        }
        public void setSymbol(String symbol) {
            this.symbol = symbol;
        }
        public CardColor getColor() {
            return color;
        }
        public void setColor(CardColor color) {
            this.color = color;
        }复制代码


    问题

    在你知道输入有效的时候,使用Enum.valueOf非常棒。但是,如果传入无效的名称,那么将抛出异常。在某些情况下,这很好。不过,在通常情况下,我们宁愿忽略异常并返回null。

    log.debug("Running valueOf");
    for (String name : names) {
        try {
            log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.valueOf(name)));
        } catch (Exception ex) {
            log.warn("Exception Thrown", ex);
        }
    }复制代码


    2017-02-22 14:46:38.556 [main] DEBUG c.s.examples.common.EnumLookup - Running valueOf
    2017-02-22 14:46:38.804 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.808 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
    java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
      at java.lang.Enum.valueOf(Enum.java:238)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
      at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:154)复制代码

    拙劣的实现

    很不幸的是,以下两种方法在代码库中出现得是这么的频繁。反面例子,勿学。

    Enum.valueOf With Try Catch(劣)

    这种拙劣的做法最常见于初学者。异常不应该用于控制流,并且这样可能会有一些性能影响。不要偷懒。你必须用正确的方式去做。

    /*
     * Please don't do this! Using try / catch for
     * control flow is a bad practice.
     */
    public static CardSuit trycatchValueOf(String name) {
        try {
            return CardSuit.valueOf(name);
        } catch (Exception ex) {
            log.warn("Exception Thrown", ex);
            return null;
        }
    }复制代码


    log.debug("Running trycatchValueOf");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.trycatchValueOf(name)));
    }复制代码


    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running trycatchValueOf
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
    java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
      at java.lang.Enum.valueOf(Enum.java:238)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.trycatchValueOf(EnumLookup.java:89)
      at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:171)
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null复制代码

    通过迭代查找(劣)

    这种方法也很常见(见这里),但至少程序员知道不能用try/catch来捕获异常。那么,这种方法有什么问题呢?没错,它会迭代所有枚举,直到找到匹配的枚举或返回null——最坏的情况下需要n次,其中n就是枚举值的数量。有些人可能会认为这微不足道,这是过早优化了而已。但是,数据结构和算法是CS基础。使用Map而不是迭代集合要省力得多。这会大大提高性能吗?不,但它是一个很好的习惯。在面试候选人时,你会对线性复杂度搜索算法感到满意吗?此时,你不应该让这样的代码审查通过。

    /*
     * Please don't do this! It is inefficient and it's
     * not very hard to use Guava or a static Map as an index.
     */
    public static CardSuit iterationFindByName(String name) {
        for (CardSuit suit : CardSuit.values()) {
            if (name.equals(suit.name())) {
                return suit;
            }
        }
        return null;
    }复制代码
    log.debug("Running iteration");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.iterationFindByName(name)));
    }复制代码


    2017-02-22 14:46:38.808 [main] DEBUG c.s.examples.common.EnumLookup - Running iteration
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null复制代码

    较优的实现

    以下都可以通过使用Map形式的索引起作用。但是,它们之间也有一些细微的差别。

    静态Map索引(较优)

    用于快速查找固定大小的正确数据结构是什么?那就是HashMap。现在通过一些额外的样板,只要我们有很好的散列函数的话,我们就可以进行更有效的查找。稍微更冗长,但如果有办法减少样板的话,这将是极好的。

    private static final Map<String, CardSuit> nameIndex =
            Maps.newHashMapWithExpectedSize(CardSuit.values().length);
    static {
        for (CardSuit suit : CardSuit.values()) {
            nameIndex.put(suit.name(), suit);
        }
    }
    public static CardSuit lookupByName(String name) {
        return nameIndex.get(name);
    }复制代码


    log.debug("Running lookupByName");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.lookupByName(name)));
    }复制代码


    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByName
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null复制代码

    Guava Enums.getIfPresent(推荐)

    这是一个常见的用例,我们在Google的朋友为此提供了一个非常干净且无需样板的解决方案。探其究竟,它甚至使用了WeakReferences和WeakHashMaps。基本说来,这段代码将创建一个全局的静态地图,并以Enum的类名称键入,并将其用于查找。

    public static CardSuit getIfPresent(String name) {
        return Enums.getIfPresent(CardSuit.class, name).orNull();
    }复制代码


    log.debug("Running Guava getIfPresent");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.getIfPresent(name)));
    }复制代码


    2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - Running Guava getIfPresent
    2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null复制代码

    通过字段的进一步索引

    这个完全相同的方法可以用于枚举的其他字段。想要通过其显示的名称或其他属性来查找枚举并不少见。

    通过字段索引的静态Map(较优)

    与上述相同的方法,但是在显示名称上而不是枚举名称上进行索引。

    private static final Map<String, CardSuit> displayNameIndex =
            Maps.newHashMapWithExpectedSize(CardSuit.values().length);
    static {
        for (CardSuit suit : CardSuit.values()) {
            displayNameIndex.put(suit.getDisplayName(), suit);
        }
    }
    public static CardSuit lookupByDisplayName(String name) {
        return displayNameIndex.get(name);
    }复制代码


    log.debug("Running lookupByDisplayName");
    for (String displayName : displayNames) {
        log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayName(displayName)));
    }复制代码


    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayName
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null复制代码

    通过字段索引的静态Map(较优)

    我们不能在这里利用Guava,因为对于静态索引创建唯一的全局密钥将是一件困难的事。但是,这并不意味着我们没有帮手!

    public class EnumUtils {
        public static <T, E extends Enum<E>> Function<T, E> lookupMap(Class<E> clazz, Function<E, T> mapper) {
            @SuppressWarnings("unchecked")
            E[] emptyArray = (E[]) Array.newInstance(clazz, 0);
            return lookupMap(EnumSet.allOf(clazz).toArray(emptyArray), mapper);
        }
        public static <T, E extends Enum<E>> Function<T, E> lookupMap(E[] values, Function<E, T> mapper) {
            Map<T, E> index = Maps.newHashMapWithExpectedSize(values.length);
            for (E value : values) {
                index.put(mapper.apply(value), value);
            }
            return (T key) -> index.get(key);
        }
    }复制代码


    现在我们有了一个相与样板没多大关联的通用解决方案。

    private static final Function<String, CardSuit> func =
            EnumUtils.lookupMap(CardSuit.class, e -> e.getDisplayName());
    public static CardSuit lookupByDisplayNameUtil(String name) {
        return func.apply(name);
    }复制代码


    log.debug("Running lookupByDisplayNameUtil");
    for (String displayName : displayNames) {
        log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayNameUtil(displayName)));
    }复制代码


    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayNameUtil
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null复制代码

    结论

    这里有若干方法都可用于解决同一个问题。有些拙劣,有些更优。


    展开全文
  • Java Enum是一个非常有用的功能,但很多人通常并不能充分利用,这是因为一些库不会优先择用该功能。通常我们也可以正确使用Java枚举功能,但在...问题很简单:我们应该如何通过名称或值获取枚举,并忽略不存在的值?

    Java Enum是一个非常有用的功能,但很多人通常并不能充分利用,这是因为一些库不会优先择用该功能。通常我们也可以正确使用Java枚举功能,但在许多代码库中往往存在着这样一个问题,于是有了这篇文章。问题很简单:我们应该如何通过名称或值获取枚举,并忽略不存在的值?

    枚举

    这是我们将在示例中使用的枚举。 挑选更复杂的枚举是为了也可以通过其他字段展示查找枚举。

    public enum CardColor {
        RED,
        BLACK,
        ;
    }
    // Jackson annotation to print the enum as an Object instead of the default name.
    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum CardSuit {
        // Unicode suits - https://en.wikipedia.org/wiki/Playing_cards_in_Unicode
        SPADE("Spade", String.valueOf((char) 0x2660), CardColor.BLACK),
        HEART("Heart", String.valueOf((char) 0x2665), CardColor.RED),
        DIAMOND("Diamond", String.valueOf((char) 0x2666), CardColor.RED),
        CLUB("Club", String.valueOf((char) 0x2663), CardColor.BLACK),
        ;
        private String displayName;
        private String symbol;
        private CardColor color;
        private CardSuit(String displayName, String symbol, CardColor color) {
            this.displayName = displayName;
            this.symbol =  symbol;
            this.color = color;
        }
        public String getDisplayName() {
            return displayName;
        }
        public void setDisplayName(String displayName) {
            this.displayName = displayName;
        }
        public String getSymbol() {
            return symbol;
        }
        public void setSymbol(String symbol) {
            this.symbol = symbol;
        }
        public CardColor getColor() {
            return color;
        }
        public void setColor(CardColor color) {
            this.color = color;
        }

    在 GitHub 上查看。

    问题

    在你知道输入有效的时候,使用Enum.valueOf非常棒。但是,如果传入无效的名称,那么将抛出异常。在某些情况下,这很好。不过,在通常情况下,我们宁愿忽略异常并返回null。

    log.debug("Running valueOf");
    for (String name : names) {
        try {
            log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.valueOf(name)));
        } catch (Exception ex) {
            log.warn("Exception Thrown", ex);
        }
    }

     

    2017-02-22 14:46:38.556 [main] DEBUG c.s.examples.common.EnumLookup - Running valueOf
    2017-02-22 14:46:38.804 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.808 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
    java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
      at java.lang.Enum.valueOf(Enum.java:238)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
      at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:154)
    拙劣的实现

    很不幸的是,以下两种方法在代码库中出现得是这么的频繁。反面例子,勿学。

    Enum.valueOf With Try Catch(劣)

    这种拙劣的做法最常见于初学者。异常不应该用于控制流,并且这样可能会有一些性能影响。不要偷懒。你必须用正确的方式去做。

    /*
     * Please don't do this! Using try / catch for
     * control flow is a bad practice.
     */
    public static CardSuit trycatchValueOf(String name) {
        try {
            return CardSuit.valueOf(name);
        } catch (Exception ex) {
            log.warn("Exception Thrown", ex);
            return null;
        }
    }

     

    log.debug("Running trycatchValueOf");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.trycatchValueOf(name)));
    }

     

    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running trycatchValueOf
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] WARN  c.s.examples.common.EnumLookup - Exception Thrown
    java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
      at java.lang.Enum.valueOf(Enum.java:238)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
      at com.stubbornjava.examples.common.EnumLookup$CardSuit.trycatchValueOf(EnumLookup.java:89)
      at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:171)
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    通过迭代查找(劣)

    这种方法也很常见(见这里),但至少程序员知道不能用try/catch来捕获异常。那么,这种方法有什么问题呢?没错,它会迭代所有枚举,直到找到匹配的枚举或返回null——最坏的情况下需要n次,其中n就是枚举值的数量。有些人可能会认为这微不足道,这是过早优化了而已。但是,数据结构和算法是CS基础。使用Map而不是迭代集合要省力得多。这会大大提高性能吗?不,但它是一个很好的习惯。在面试候选人时,你会对线性复杂度搜索算法感到满意吗?此时,你不应该让这样的代码审查通过。

    /*
     * Please don't do this! It is inefficient and it's
     * not very hard to use Guava or a static Map as an index.
     */
    public static CardSuit iterationFindByName(String name) {
        for (CardSuit suit : CardSuit.values()) {
            if (name.equals(suit.name())) {
                return suit;
            }
        }
        return null;
    }

     

    log.debug("Running iteration");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.iterationFindByName(name)));
    }

     

    2017-02-22 14:46:38.808 [main] DEBUG c.s.examples.common.EnumLookup - Running iteration
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    较优的实现

    以下都可以通过使用Map形式的索引起作用。但是,它们之间也有一些细微的差别。

    静态Map索引(较优)

    用于快速查找固定大小的正确数据结构是什么?那就是HashMap。现在通过一些额外的样板,只要我们有很好的散列函数的话,我们就可以进行更有效的查找。稍微更冗长,但如果有办法减少样板的话,这将是极好的。

    private static final Map<String, CardSuit> nameIndex =
            Maps.newHashMapWithExpectedSize(CardSuit.values().length);
    static {
        for (CardSuit suit : CardSuit.values()) {
            nameIndex.put(suit.name(), suit);
        }
    }
    public static CardSuit lookupByName(String name) {
        return nameIndex.get(name);
    }
    log.debug("Running lookupByName");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.lookupByName(name)));
    }
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByName
    2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    Guava Enums.getIfPresent(推荐)

    这是一个常见的用例,我们在Google的朋友为此提供了一个非常干净且无需样板的解决方案。探其究竟,它甚至使用了WeakReferences和WeakHashMaps。基本说来,这段代码将创建一个全局的静态地图,并以Enum的类名称键入,并将其用于查找。

    public static CardSuit getIfPresent(String name) {
        return Enums.getIfPresent(CardSuit.class, name).orNull();
    }
    log.debug("Running Guava getIfPresent");
    for (String name : names) {
        log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.getIfPresent(name)));
    }
    2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - Running Guava getIfPresent
    2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    通过字段的进一步索引

    这个完全相同的方法可以用于枚举的其他字段。想要通过其显示的名称或其他属性来查找枚举并不少见。

    通过字段索引的静态Map(较优)

    与上述相同的方法,但是在显示名称上而不是枚举名称上进行索引。

    private static final Map<String, CardSuit> displayNameIndex =
            Maps.newHashMapWithExpectedSize(CardSuit.values().length);
    static {
        for (CardSuit suit : CardSuit.values()) {
            displayNameIndex.put(suit.getDisplayName(), suit);
        }
    }
    public static CardSuit lookupByDisplayName(String name) {
        return displayNameIndex.get(name);
    }
    log.debug("Running lookupByDisplayName");
    for (String displayName : displayNames) {
        log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayName(displayName)));
    }

     

    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayName
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    通过字段索引的静态Map(较优)

    我们不能在这里利用Guava,因为对于静态索引创建唯一的全局密钥将是一件困难的事。但是,这并不意味着我们没有帮手!

    public class EnumUtils {
        public static <T, E extends Enum<E>> Function<T, E> lookupMap(Class<E> clazz, Function<E, T> mapper) {
            @SuppressWarnings("unchecked")
            E[] emptyArray = (E[]) Array.newInstance(clazz, 0);
            return lookupMap(EnumSet.allOf(clazz).toArray(emptyArray), mapper);
        }
        public static <T, E extends Enum<E>> Function<T, E> lookupMap(E[] values, Function<E, T> mapper) {
            Map<T, E> index = Maps.newHashMapWithExpectedSize(values.length);
            for (E value : values) {
                index.put(mapper.apply(value), value);
            }
            return (T key) -> index.get(key);
        }
    }

     

    现在我们有了一个相与样板没多大关联的通用解决方案。

    private static final Function<String, CardSuit> func =
            EnumUtils.lookupMap(CardSuit.class, e -> e.getDisplayName());
    public static CardSuit lookupByDisplayNameUtil(String name) {
        return func.apply(name);
    }
    log.debug("Running lookupByDisplayNameUtil");
    for (String displayName : displayNames) {
        log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayNameUtil(displayName)));
    }
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayNameUtil
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
    2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
    结论

    这里有若干方法都可用于解决同一个问题。有些拙劣,有些更优。

    原文来自:http://www.codeceo.com/article/java-enum-lookup-no-exception.html


    展开全文
  • 疯狂JAVA讲义

    2014-10-17 13:35:01
    10.6.4 不要忽略捕获到的异常 379 10.7 本章小结 379 本章练习 379 第11章 AWT编程 380 11.1 GUI(图形用户界面)和AWT 381 11.2 AWT容器 382 11.3 布局管理器 385 11.3.1 FlowLayout布局管理器 386 11.3.2 ...
  • java 面试题 总结

    2009-09-16 08:45:34
    java编译器要求方法必须声明抛出可能发生的非运行时异常,但是不要求必须声明抛出未被捕获的运行时异常。 6、说出Servlet的生命周期,说出Servlet和CGI的区别。 Servlet被服务器实例化后,容器运行其init方法,...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    50.JAVA语言如何进行异常处理,关键字:thorws,throw,try,catch,finally 51.Object类(或者其子类)的finalize()方法在什么情况下被调用? 52.一个“.java”原文件中是否可以包括多个类(不是内部类)? 53.掌握...
  • 异常详情: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. ...具体做法:需要在获取sslParams时,修改自定义TrustM

    异常详情:

    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

    问题原因:

    由于项目的https.bks证书不是正规的CA签发的证书,而是二级代理商等签发的证书,验证不通过造成的!!!

    解决方案:

    忽略https的证书校验

    具体做法:需要在获取sslParams时,修改并自定义TrustManager为trustAllCerts
    再主类里面加入该方法

     public static void handleSSLHandshake() {
            try {
                TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
    
                    @Override
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }
    
                    @Override
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }
                }};
    
                SSLContext sc = SSLContext.getInstance("TLS");
                // trustAllCerts信任所有的证书
                sc.init(null, trustAllCerts, new SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
                HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
            } catch (Exception ignored) {
            }
        }

     然后再oncreate()方法里面调用

    handleSSLHandshake();

    展开全文
  • java编译器要求方法必须声明抛出可能发生的非运行时异常,但是不要求必须声明抛出未被捕获的运行时异常。 9、说出Servlet的生命周期,说出Servlet和CGI的区别。  Servlet被服务器实例化后,容器运行其init方法...
  • 比如,跳转页面需要登陆状态如何拦截,跳转页面传递参数该怎么办,程序意外跳转异常或者失败又该如何处理? 使用Arouter注意事项有哪些?如何让代码变得更加容易让人维护? 直接看我这篇博客:...
  • 可设置是否自动引包(java中的import)及引入包路径(java类中的package),建议取消配合IDEA的自动引包更智能(Settings→Editor→General→Auto Import,勾选Add unambiguous imports on the fly以及Optimize imports ...
  • 运行./demo.sh client启动Demo客户端,忽略前面的调试信息,可以看到如下提示: Apollo Config Demo. Please input key to get the value. Input quit to exit. > 输入timeout,会看到如下信息: > timeout &...
  • 昆山工业技术研究院着眼于为委托用户和质检机构搭建良好的沟通桥梁,免去目前市场业务中企业用户需要实地地频繁地与检测机构沟通,从而提出自己的委托乃至下委托单、等待检测报告等,设计研发了市场上首款提供...
  • --c3p0将建一张名为Test的空表,使用其自带的查询语句进行测试。如果定义了这个参数那么 属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试 使用。Default: null /> --> ...
  • 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。 7. ...
  • asp.net知识库

    2015-06-18 08:45:45
    忽略大小写Replace效率瓶颈IndexOf 随机排列算法 理解C#中的委托[翻译] 利用委托机制处理.NET中的异常 与正则表达式相关的几个小工具 你真的了解.NET中的String吗? .NET中的方法及其调用(一) 如何判断ArrayList,...
  • task : 审批流节点,可以在节点上直接配置审批人列表,或者配置服务从业务方获取审批人列表 流程模板示例(本例子比较全,业务方可以按需使用): <process name="process"> <start name="i'm start"> ...
  • 确保在同一事务处理种对相同数据的两次查询看到的是相同的值。 值范围: TRUE | FALSE 默认值: FALSE row_locking: 说明: 指定在表已更新或正在更新时是否获取行锁。如果设置为 ALWAYS, 只有在表被更新后才获取...
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    8.4 异常处理语句 .95 8.5 小 结 .100 第三部分 面向对象的 C#.101 第九章 面向对象的程序设计 .101 9.1 面向对象的基本概念.101 9.2 对象的模型技术 .103 9.3 面向对象的分析 .105 9.4 面向对象的设计...
  •  Ivor Horton是撰著Java、C和C++编程语言图书的杰出作家之一。大家一致认为,他的著作独具风格,无论是编程新手,还是经验丰富的编程人员,都很容易理解其内容。在个人实践中, Ivor Horton也是一名系统顾问。他...
  •  Ivor Horton是撰著Java、C和C++编程语言图书的杰出作家之一。大家一致认为,他的著作独具风格,无论是编程新手,还是经验丰富的编程人员,都很容易理解其内容。在个人实践中,Ivor Horton也是一名系统顾问。他从事...
  • Visual C++ 2008入门经典--详细书签版

    热门讨论 2013-02-02 16:07:15
    IvorHorton还著有关于C、C++和Java的多部入门级好书,如《C语言入门经典(第4版)》和《C++入门经典(第3版)》。 目录 封面 -19 前言 -18 目录 -10 第1章 使用Visual C++ 2008编程 1 1.1 .NET Framework 1 1.2 CLR 2...
  • C#微软培训资料

    2014-01-22 14:10:17
    8.4 异常处理语句 .95 8.5 小 结 .100 第三部分 面向对象的 C#.101 第九章 面向对象的程序设计 .101 9.1 面向对象的基本概念.101 9.2 对象的模型技术 .103 9.3 面向对象的分析 .105 9.4 面向对象的设计...
  • 经过跟踪变量值发现循环变量i的阀值pSysHead->dbf_count的数值为0xFFFFFFFF,该值是从被破坏的内存数据库中获取的,正常情况下该值小于127。而pDBFat是数据库的起始地址,如果pSysHead->dbf_count值异常过大,将...
  • IvorHorton还著有关于C、C++和Java的多部入门级好书,如《C语言入门经典(第4版)》和《C++入门经典(第3版)》。 目录 封面 -19 前言 -18 目录 -10 第1章 使用Visual C++ 2008编程 1 1.1 .NET Framework 1 1.2 CLR 2...
  • Visual C++ 2005 入门经典 详细书签版

    热门讨论 2013-02-02 16:39:43
    Ivor Horton还著有Beginning Visual C++ 6、Beginning C Programming和Beginning Java 2等多部入门级好书。 目录 封面 -18 前言 -14 目录 -9 第1章 使用Visual C++ 2005编程 1 1.1 .NET Framework 1 1.2 CLR 2...
  • Ivor Horton还著有Beginning Visual C++ 6、Beginning C Programming和Beginning Java 2等多部入门级好书。 目录 封面 -18 前言 -14 目录 -9 第1章 使用Visual C++ 2005编程 1 1.1 .NET Framework 1 1.2 CLR 2...
  • 笔者在此指定其为一种类C++/MATLAB/VB/Java等高级语言的运算输入规则,以与通用的软件和人们的书写习惯基本相同。此种类MATLAB运算规则基本与MATLAB软件的语法相同,但也同时兼容其他语言如:C/C++、VB、Pascal等,...
  • 测试培训教材

    2014-04-01 12:10:48
    Using VAPI-XP test scripts, you can test COM/DCOM servers, SOAP-based Web services, Java APIs (such as Java classes and EJBs), and console applications. You can also use VAPI-XP to create a ...
  • 操作系统(内存管理)

    热门讨论 2009-09-20 12:55:25
    从可用的内存中获取一部分内存。 向可用内存池(pool)中返回部分内存,以使其可以由程序的其他部分或者其他程序使用。 实现这些需求的程序库称为 分配程序(allocators),因为它们负责分配和回收内存。程序的...
  • 使用jquery实现ajax同样异常简单 代码 (1) $.get("search. do",{id:1},rend); function rend(xml){ alert(xml); } (2) $.post("search. do",{id:1},rend); function rend(xml){ alert(xml); } (3) $...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

java获取异常并忽略

java 订阅