2. 通过名称搜索枚举

枚举类型在 Java 中是一种特殊数据类型,用于定义一组预定义常量。先看一个方向枚举的例子:

public enum Direction {
    EAST, WEST, SOUTH, NORTH;
}

每个枚举常量的名称是固定的(如 Direction.EAST 的名称就是 "EAST")。实现名称搜索时,建议忽略大小写,这样 "East""east""EAST" 都能匹配到 Direction.EAST。添加搜索方法:

public static Direction findByName(String name) {
    Direction result = null;
    for (Direction direction : values()) {
        if (direction.name().equalsIgnoreCase(name)) {
            result = direction;
            break;
        }
    }
    return result;
}

踩坑提示:这里返回 null 是常见做法,但实际项目中建议:

  1. 返回默认值(如 Direction.EAST
  2. 抛出异常(如 IllegalArgumentException
  3. 使用 Optional 包装(后续会讲)

测试用例:

@Test
public void givenWeekdays_whenValidDirectionNameProvided_directionIsFound() {
    Direction result = Direction.findByName("EAST");
    assertThat(result).isEqualTo(Direction.EAST);
}

@Test
public void givenWeekdays_whenValidDirectionNameLowerCaseProvided_directionIsFound() {
    Direction result = Direction.findByName("east");
    assertThat(result).isEqualTo(Direction.EAST);
}

@Test
public void givenWeekdays_whenValidDirectionNameMixedCaseProvided_directionIsFound() {
    Direction result = Direction.findByName("East");
    assertThat(result).isEqualTo(Direction.EAST);
}

3. 通过值搜索枚举

枚举可以包含自定义属性,比如星期枚举添加了全称属性:

public enum Weekday {
    MONDAY("Monday"),
    TUESDAY("Tuesday"),
    // ... 其他省略
    SUNDAY("Sunday"),
    ;
    private final String value;

    Weekday(String value) {
        this.value = value;
    }
}

实现按值搜索(同样忽略大小写):

public static Weekday findByValue(String value) {
    Weekday result = null;
    for (Weekday day : values()) {
        if (day.getValue().equalsIgnoreCase(value)) {
            result = day;
            break;
        }
    }
    return result;
}

测试用例:

@Test
public void givenWeekdays_whenValidWeekdayValueProvided_weekdayIsFound() {
    Weekday result = Weekday.findByValue("Monday");
    assertThat(result).isEqualTo(Weekday.MONDAY);
}

@Test
public void givenWeekdays_whenInvalidWeekdayValueProvided_nullIsReturned() {
    Weekday result = Weekday.findByValue("mon");
    assertThat(result).isNull();
}

4. 通过整数值搜索枚举

枚举属性可以是任意类型,如月份枚举包含字符串和整数代码:

public enum Month {
    JANUARY("January", 1),
    FEBRUARY("February", 2),
    // ... 其他省略
    DECEMBER("December", 12),
    ;

    private final String value;
    private final int code;

    Month(String value, int code) {
        this.value = value;
        this.code = code;
    }
}

使用 Java 8 Stream API 实现整数搜索,返回 Optional 更优雅:

public static Optional<Month> findByCode(int code) {
    return Arrays.stream(values())
                 .filter(month -> month.getCode() == code)
                 .findFirst();
}

测试用例:

@Test
public void givenMonths_whenValidMonthCodeProvided_optionalMonthIsReturned() {
    Optional<Month> result = Month.findByCode(1);
    assertThat(result).isEqualTo(Optional.of(Month.JANUARY));
}

@Test
public void givenMonths_whenInvalidMonthCodeProvided_optionalEmptyIsReturned() {
    Optional<Month> result = Month.findByCode(0);
    assertThat(result).isEmpty();
}

5. 搜索方法抛出异常

某些场景下需要严格校验输入,找不到时抛出异常比返回 null/Optional 更合适。以月份枚举为例:

public static Month findByValue(String value) {
    return Arrays.stream(values())
                 .filter(month -> month.getValue().equalsIgnoreCase(value))
                 .findFirst()
                 .orElseThrow(IllegalArgumentException::new);
}

测试用例:

@Test
public void givenMonths_whenInvalidMonthValueProvided_illegalArgExIsThrown() {
    assertThatIllegalArgumentException()
        .isThrownBy(() -> Month.findByValue("Jan"));
}

6. 总结

本文系统梳理了枚举搜索的核心方法:

搜索类型 实现要点 返回值建议
按名称搜索 忽略大小写,遍历 values() 默认值/异常/Optional
按字符串值搜索 同上,比较自定义属性 同上
按整数值搜索 使用 Stream API,返回 Optional Optional
严格校验 使用 orElseThrow() 抛出异常 直接返回枚举

开发建议

  1. 优先使用 Optional 避免空指针
  2. 枚举常量较少时,遍历性能可接受
  3. 复杂场景考虑使用 Map 缓存枚举映射

完整代码示例可在 GitHub 获取。


原始标题:Check if an Enum Value Exists in Java