Java 通过其内部字段获取枚举
具有带有内部字段的枚举,类似于映射 现在我需要通过它的内部字段得到enum 他写道:Java 通过其内部字段获取枚举,java,enums,Java,Enums,具有带有内部字段的枚举,类似于映射 现在我需要通过它的内部字段得到enum 他写道: package test; /** * Test enum to test enum =) */ public enum TestEnum { ONE(1), TWO(2), THREE(3); private int number; TestEnum(int number) { this.number = number; } pu
package test;
/**
* Test enum to test enum =)
*/
public enum TestEnum {
ONE(1), TWO(2), THREE(3);
private int number;
TestEnum(int number) {
this.number = number;
}
public TestEnum findByKey(int i) {
TestEnum[] testEnums = TestEnum.values();
for (TestEnum testEnum : testEnums) {
if (testEnum.number == i) {
return testEnum;
}
}
return null;
}
}
但每次我需要找到合适的实例时,查找所有枚举并不是很有效
还有其他方法可以做到这一点吗?您应该有一个HashMap,其中数字作为键,枚举值作为值 此地图通常可以位于您的存储库中。然后,您可以轻松地用首选枚举值替换数据库中的int变量
如果您的键(int值)存储在数据库中,那么我会说在业务层的枚举中携带这些键是一种糟糕的设计。如果是这种情况,我建议不要将int值存储在枚举中。您可以使用带有
静态
初始值设定项的静态映射
,该初始值设定项使用由数字
字段键入的TestEnum
值填充它
请注意,findByKey
已成为static
,而number
也已成为final
import java.util.*;
public enum TestEnum {
ONE(1), TWO(2), SIXTY_NINE(69);
private final int number;
TestEnum(int number) {
this.number = number;
}
private static final Map<Integer,TestEnum> map;
static {
map = new HashMap<Integer,TestEnum>();
for (TestEnum v : TestEnum.values()) {
map.put(v.number, v);
}
}
public static TestEnum findByKey(int i) {
return map.get(i);
}
public static void main(String[] args) {
System.out.println(TestEnum.findByKey(69)); // prints "SIXTY_NINE"
System.out.println(
TestEnum.values() == TestEnum.values()
); // prints "false"
}
}
import java.util.*;
公共枚举测试数{
一(1)、二(2)、六十九(69);
私人最终整数;
TestEnum(整数){
这个数字=数字;
}
私有静态最终地图;
静止的{
map=新的HashMap();
for(TestEnum v:TestEnum.values()){
地图放置(v.编号,v);
}
}
公共静态TestEnum findByKey(int i){
返回地图。获取(i);
}
公共静态void main(字符串[]args){
System.out.println(TestEnum.findByKey(69));//打印“六十九”
System.out.println(
TestEnum.values()==TestEnum.values()
);//打印“假”
}
}
您现在可以期望findByKey
成为O(1)
操作
工具书类
关于
values()
main
方法中的第二条println
语句显示:values()
每次调用都返回一个新分配的数组!原始的O(N)
解决方案只需调用values()
一次并缓存数组,就可以做得更好一些,但该解决方案平均来说仍然是O(N)
。一个解决方案是添加
public final Test[] TESTS = { null, ONE, TWO, THREE };
public static Test getByNumber(int i) {
return TESTS[i];
}
到枚举
如果内部数据不是整数,则可以在
静态{…}
初始值设定项中填充一个映射。此映射稍后可以在上面的getByNumber
方法中使用。尽管有人建议使用map
请三思
您的原始解决方案,特别是对于小枚举,可能比使用HashMap快很多
在枚举包含至少30到40个元素之前,HashMap可能不会更快
这是“如果没有损坏,就不要修复”的一种情况。以下是通过字段查找枚举值的最方便方法:
public enum TestEnum {
A("EXAMPLE_1", "Qwerty", 1),
B("EXAMPLE_2", "Asdfgh", 2),
C("EXAMPLE_3", "Zxcvbn", 3);
private final String code;
private final String name;
private final Integer typeID;
TestEnum(String code, String name, Integer typeID) {
this.code = code;
this.name = name;
this.key = typeID;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
public Integer getKey() {
return key;
}
public static TestEnum findValueByTypeId(Integer key) {
return Arrays.stream(TestEnum.values()).filter(v ->
v.getKey().equals(key)).findFirst().orElseThrow(() ->
new Exception(String.format("Unknown TestEnum.key: '%s'", key)));
}
}
很好的解决方案。这也是我想到的。我通常在
static{…}
中填充映射,您发布的延迟版本不是线程安全的。考虑线程A和B都在map=null之前停止。A继续并在返回前停止。B执行map=并在初始化值之前停止。然后A继续进行,并可能返回不正确的null。虽然这种情况不太可能发生,但对于多线程来说,代码仍然是不正确的。嗯,在进一步搜索之后,我稍微有点不对劲。我想这只是一个问题,如果您试图访问枚举构造函数中的静态映射。我的错,这应该是正常的。Re:“O(N)”。当N是某个可能变大的变量时,比较大操作系统是有用的。当N是我的枚举中的常量数时,我确切地知道有多少个,一个O(N^2)解决方案可能比其他人的O(logn)解决方案更好。69是如何出现的?是什么让你认为HashMap
如此缓慢?它被初始化一次,然后比调用values()
(每次都必须是新分配的数组;尝试TestEnum.values()==TestEnum.values()
是false
)然后遍历每个元素要快得多。@polygene润滑剂:我只做过一次经验测试。查看HashMap.get的实现。它比OP最初的实现做得更多。不久前,我做了这个精确的测试,发现在你至少有30个元素要遍历之前,考虑哈希图是不值得的。这就是说,您的实现是完全正确的,将完成一项工作。我认为30-40可能是夸大了,但我将尝试对此进行基准测试。我认为这个答案基本上是正确的,但对于这个数字的一些选择,需要指出。我已经用枚举中的10个常量做了一个粗略的第一个基准测试。对于较小的int值,我的macbook上的性能相当——hashmap的性能仅比线性搜索差10%左右。使用随机的、较大的整数作为值,映射性能会变得更差,因为每个查询都需要分配一个整数实例。我在计时循环中测试了10个成功查询和2个未找到的查询。这远不是最终的答案,但至少应该表明亚历山大的答案并没有太离谱。如果有机会,我会完成并发布基准代码。哦!当然,在我的基准测试中,findByKey方法不调用values()。values()缓存在私有静态字段中。很遗憾,values()在每次调用时都被迫创建并填充一个全新的数组,因为它被声明为返回一个数组而不是集合类型。您能详细说明一下吗?对我来说,在Java端使用enum
作为数据库级别的int
表示的枚举似乎很自然。什么使使用enum
成为一种糟糕的设计?您有什么建议?@Pascal:在分层应用程序中,您的服务