通过数字ID获取枚举的最佳方法

时间:2017-01-05 10:01:15

标签: java enums

我需要创建一个包含大约300个值的枚举,并且能够通过id(int)获取其值。我目前有这个:

public enum Country {
    DE(1), US(2), UK(3);

    private int id;
    private static Map<Integer, Country> idToCountry = new HashMap<>();
    static {
        for (Country c : Country.values()) {
            idToCountry.put(c.id, c);
        }
    }

    Country(int id) {
        this.id = id;
    }

    public static Country getById(int id) {
        return idToCountry.get(id);
    }
}

这个枚举将会被大量使用,所以我想知道这是否是性能最佳的解决方案。

我一遍又一遍地阅读http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html,但无法找到描述

的部分

static {

}
调用

块,如果确保它只被调用一次。那么 - 是吗?

4 个答案:

答案 0 :(得分:4)

如果第一个国家/地区ID为0且ID增加1,您可以使用下一个方法: 缓存数组中的枚举值。 Enum.values()以与枚举中声明的顺序相同的顺序返回元素。但它应该被缓存,因为它每次调用时都会创建新数组。 通过id从缓存数组中获取值,这将是数组索引。 请看下面的代码: enum国家{     A,B,C,D,E;     private static final Country [] values = Country.values();     public static Country getById(int id){         返回值[id];     } } 更新:要获取国家/地区的ID,应使用ordinal()方法。为了使id代码更清晰,可以将下一个方法添加到枚举中: public int getId(){     return ordinal(); }

答案 1 :(得分:3)

静态初始化程序块一次调用when the class is initialized。它不能保证只被调用一次,但除非你正在使用类加载器做一些异国情调,否则它将被禁止。

因此,从性能角度来看,您的方法可能很好。我建议的唯一更改是制作您的字段final

表示映射的另一种方法是将元素存储在数组(或列表)中:

Country[] countries = new Countries[maxId + 1];
for (Country country : Country.values()) {
  countries[country.id] = country;
}

然后你可以按元素索引查找它们:

System.out.println(countries[1]);  // DE.

这样可以避免因为id打包idToCountry.get(Integer)而导致null的性能损失。

这当然要求您拥有非负ID(理想情况下,ID会合理连续,以避免在国家/地区之间存储大量var srcObj = {"success":"1","prescription_data":[{"_id":"586c95a4ce997012a44f777c","doctor_name":"new doctor","doctor_dept":"Cardiologist","prescription":[{"_id":"586c9f48fa0e603670cb01ae","name":"ASCOFER 33 mg, gélule","count":"1","type":"0","consume":"0","comment":"asdfd"}]},{"_id":"586ded3fdfc5f92724491f82","doctor_name":"asd asd","doctor_dept":"Cardiologist","prescription":[{"_id":"586dfda498c23d1a200cfb3b","name":"ALPHACAINE N, solution injectable à usage dentaire","count":"1","type":"0","consume":"0","comment":"test"}]},{"_id":"586ded3fdfc5f92724491f82","doctor_name":"asd asd","doctor_dept":"Cardiologist","prescription":[{"_id":"586dfdbe98c23d1a200cfb3f","name":"ALPHACAINE N, solution injectable à usage dentaire","count":"1","type":"0","consume":"0","comment":"test"}]}]}; var indexOfId = function(arr, obj){ for(var objIdx in arr){ if(arr[objIdx]._id === obj._id) return objIdx; } } srcObj.prescription_data = srcObj.prescription_data.filter((o, i, a) => indexOfId(a, o) == i); console.log(srcObj);)。

答案 2 :(得分:1)

首先,您不需要使用静态块来创建地图。您只需将代码添加到构造函数中,其中每个组件都将自己添加到地图中。枚举总是一个单一的结构,所以你的构造函数只能被调用一次(每个枚举值)你也不需要ID,因为Enum有方法public final int ordinal()返回它的零基序号。枚举。在你的情况下,对于DE来说,序数将是0,对于美国而言是1,对于英国是2。

以下是一个例子:

public enum Country {
DE, US, UK;

private static Map<Integer, Country> idToCountry = new HashMap<>();

    Country() {
       idToCountry.put(this.ordinal(), this);
    }

    public static Country getById(int id) {
        return idToCountry.get(id);
    }
}

答案 3 :(得分:0)

你也可以尝试这个。简单,因为它显示。

enum Country {
  DE(1), US(2), UK(3);

  public int id;

  Country(int id) {
  this.id = id;
}

 public static Country getCountry(int id) {
    Country[] c = new Country[Country.values().length];
    c = Country.values();
    return c[id];
  }
}

非常感谢。