我正在编写一个枚举,并确保该枚举不会引发nullpointer异常,因为这对使用此枚举的客户端来说很糟糕。我使用谷歌枚举,如果输入参数mood is null
,它仍然抛出NPE
import com.google.common.base.Enums;
public enum KnowYourMoodEnum {
ANGRY, SAD, HAPPY, FEELING_GOOD;
private static final Set<KnowYourMoodEnum> HAPPY_MOOD_LIST = Sets.newHashSet(HAPPY, FEELING_GOOD);
private static final Set<KnowYourMoodEnum> UPSET_MOOD_LIST = Sets.newHashSet(ANGRY, SAD);
public static boolean isHappyMood(String mood) {
return HAPPY_MOOD_LIST.stream()
.anyMatch(x -> x.equals(Enums.getIfPresent(KnowYourMoodEnum.class, mood).orNull()));
}
public static boolean isUpsetMood(String mood) {
return UPSET_MOOD_LIST.stream()
.anyMatch(x -> x.equals(Enums.getIfPresent(KnowYourMoodEnum.class, mood).orNull()));
}
}
(1(对于API来说,指定";不要递给我null
,否则你会得到NPE";。这在这里是有道理的。
(2( 如果不想这样做,那么if (mood == null) return false;
。
(3( 这是一个复杂而间接的实现。在枚举上具有属性boolean happy
似乎会更简单。
使用Enums.getIfPresent
似乎是多余的,将输入mood
与枚举的name()
:进行比较(可能忽略大小写(就足够了
public static boolean isHappyMood(String mood) {
return isInSet(mood, HAPPY_MOOD_LIST);
}
public static boolean isUpsetMood(String mood) {
return isInSet(mood, UPSET_MOOD_LIST);
}
private static boolean isInSet(String mood, Set<KnowYourMoodEnum> set) {
return set.stream().anyMatch(x -> x.name().equalsIgnoreCase(mood));
}
这是空安全的,因为name()
从不为空。
使用Streams并不是每个操作都会变得更好。而不是CCD_ 9只是使用了简单高效的CCD_。它更简单,而且不会执行线性搜索,而是进行高效的查找。对于这样的小集合来说,这并不是很重要,但仍然值得注意的是,Stream API不仅没有提供任何好处,反而降低了性能。
如果您希望该方法能够容忍与实际枚举常量不匹配的输入,那么首先初始化名称的Set
要简单得多。
public enum KnowYourMoodEnum {
ANGRY, SAD, HAPPY, FEELING_GOOD;
private static final Set<String> HAPPY_MOOD = Stream.of(HAPPY, FEELING_GOOD)
.map(Enum::name).collect(Collectors.toSet());
private static final Set<String> UPSET_MOOD = Stream.of(ANGRY, SAD)
.map(Enum::name).collect(Collectors.toSet());
public static boolean isHappyMood(String mood) {
return HAPPY_MOOD.contains(mood);
}
public static boolean isUpsetMood(String mood) {
return UPSET_MOOD.contains(mood);
}
}
对于null
或未知名称,这些方法已经计算为false
。
如果你想让支票不区分大小写,你可以使用
public enum KnowYourMoodEnum {
ANGRY, SAD, HAPPY, FEELING_GOOD;
private static final Set<String> HAPPY_MOOD = Stream.of(HAPPY, FEELING_GOOD)
.map(Enum::name).collect(Collectors.toCollection(
() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)));
private static final Set<String> UPSET_MOOD = Stream.of(ANGRY, SAD)
.map(Enum::name).collect(Collectors.toCollection(
() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)));
public static boolean isHappyMood(String mood) {
return mood != null && HAPPY_MOOD.contains(mood);
}
public static boolean isUpsetMood(String mood) {
return mood != null && UPSET_MOOD.contains(mood);
}
}
这将使用O(logn(查找而不是O(1(,但这仍然比O(n(Stream操作更好,并且仍然与此类小集合无关。此外,通过显式null
检查,这些方法稍微复杂一些,但仍然比不惜一切代价引入Stream API的任何尝试简单得多。
你不需要第三方图书馆来完成这样一项简单的任务…
顺便说一句,当变量包含Set
时,不要将其命名为…_LIST
。