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
是常见做法,但实际项目中建议:
- 返回默认值(如
Direction.EAST
)- 抛出异常(如
IllegalArgumentException
)- 使用
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() 抛出异常 |
直接返回枚举 |
开发建议:
- 优先使用
Optional
避免空指针- 枚举常量较少时,遍历性能可接受
- 复杂场景考虑使用
Map
缓存枚举映射
完整代码示例可在 GitHub 获取。