java中从值获取枚举常量的优化方法

java中从值获取枚举常量的优化方法,java,optimization,enums,Java,Optimization,Enums,我需要有带有字节值的枚举常量,可以在超级性能排序系统中使用。但是,当我需要从相应的字节值中获取枚举时,这会出现问题。IE fromValue() 我想知道当我想要高度优化的东西时,下面使用字节值映射到常量的方法是否被认为是一个坏主意,或者我是否应该坚持使用静态常量。我试图避免的是在运行时循环遍历枚举值以找到正确的枚举值,我相信这会在执行数百万次此类操作时增加不必要的开销 public enum ReferenceTargetType { BINARY((byte)0x1), TOPIC(

我需要有带有字节值的枚举常量,可以在超级性能排序系统中使用。但是,当我需要从相应的字节值中获取枚举时,这会出现问题。IE fromValue()

我想知道当我想要高度优化的东西时,下面使用
字节
值映射到常量的方法是否被认为是一个坏主意,或者我是否应该坚持使用静态常量。我试图避免的是在运行时循环遍历枚举值以找到正确的枚举值,我相信这会在执行数百万次此类操作时增加不必要的开销

public enum ReferenceTargetType {
  BINARY((byte)0x1),
  TOPIC((byte)0x2),
  MAP((byte)0x3),
  UNKNOWN((byte)0x4);

  private static Map<Byte,ReferenceTargetType> targetTypeMap = new HashMap<Byte,ReferenceTargetType>();

  static {
    for(ReferenceTargetType type : ReferenceTargetType.values()){
      targetTypeMap.put(type.getValue(), type);
    }
  }

  private byte value;

  ReferenceTargetType(byte value){
    this.value = value;
  }

  byte getValue(){
    return this.value;
  }

  static ReferenceTargetType fromValue(byte value){
    return targetTypeMap.get(value);
  }
}
公共枚举引用目标类型{
二进制((字节)0x1),
主题((字节)0x2),
映射((字节)0x3),
未知((字节)0x4);
私有静态映射targetTypeMap=newHashMap();
静止的{
for(ReferenceTargetType:ReferenceTargetType.values()){
targetTypeMap.put(type.getValue(),type);
}
}
专用字节值;
ReferenceTargetType(字节值){
这个值=值;
}
字节getValue(){
返回此.value;
}
静态ReferenceTargetType fromValue(字节值){
返回targetTypeMap.get(值);
}
}
谢谢

更新

我创建了一些测试来查看各种方法的性能。第一种方法使用hashmap,第二种方法通过值、第三个数组偏移量和第四个数组偏移量循环使用int而不是字节(为了查看从字节向上转换到int是否会影响性能),第五种方法使用开关

平均运行次数超过100次,每次运行执行1亿次fromValue()调用。时间以毫秒为单位(我将其从nanotime改为nanotime,因为它的值越大,对我的影响越大)

结果如下:

  • 运行1平均值:385(哈希映射查找)
  • 运行2平均值:914(通过值循环)
  • 运行3平均值:0(数组(字节))
  • 运行4平均值:0(数组(整数))
  • 运行5平均值:314(开关)
以及守则:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.HashMap;
import java.util.Map;

@RunWith(JUnit4.class)
public class EnumFromValueTest {

  static int masterRuns = 100;
  static int runs = 100000000;
  static long[] r1runs = new long[masterRuns];
  static long[] r2runs = new long[masterRuns];
  static long[] r3runs = new long[masterRuns];
  static long[] r4runs = new long[masterRuns];
  static long[] r5runs = new long[masterRuns];

  static long average(long[] values){

      int total = 0;
      for(int i = 0; i < values.length; i++)
      {
        total += values[i];
      }
      int average = total / values.length;

    return average;

  }

  public enum ReferenceTargetType1 {
    BINARY((byte)0x0),
    TOPIC((byte)0x1),
    MAP((byte)0x2),
    UNKNOWN((byte)0x3);

    private static
    Map<Byte,ReferenceTargetType1>
        targetTypeMap = new HashMap<Byte, ReferenceTargetType1>();

    static {
      for(ReferenceTargetType1 type : ReferenceTargetType1.values()){
        targetTypeMap.put(type.getValue(), type);
      }
    }

    private byte value;

    ReferenceTargetType1(byte value){
      this.value = value;
    }

    byte getValue(){
      return this.value;
    }

    static ReferenceTargetType1 fromValue(byte value){

      return targetTypeMap.get(value);
    }

  }

  public enum ReferenceTargetType2 {
    BINARY((byte)0x0),
    TOPIC((byte)0x1),
    MAP((byte)0x2),
    UNKNOWN((byte)0x3);

    private byte value;

    ReferenceTargetType2(byte value){
      this.value = value;
    }

    byte getValue(){
      return this.value;
    }

    static ReferenceTargetType2 fromValue(byte value){
      for(ReferenceTargetType2 type : ReferenceTargetType2.values()){
        if(type.getValue() == value)
          return type;
      }

      return null;
    }

  }

  public enum ReferenceTargetType3 {
    BINARY((byte)0x0),
    TOPIC((byte)0x1),
    MAP((byte)0x2),
    UNKNOWN((byte)0x3);

    private byte value;

    private static ReferenceTargetType3[] values = new ReferenceTargetType3[ReferenceTargetType3.values().length];
    static {
      int i = 0;
      for(ReferenceTargetType3 type : ReferenceTargetType3.values()){
       values[i]= type;
        i++;
      }
    }
    ReferenceTargetType3(byte value){
      this.value = value;
    }

    byte getValue(){
      return this.value;
    }

    static ReferenceTargetType3 fromValue(byte value){
      return values[value];
    }

  }




  public enum ReferenceTargetType4 {
    BINARY(0),
    TOPIC(1),
    MAP(2),
    UNKNOWN(3);

    private int value;

    private static ReferenceTargetType4[] values = new ReferenceTargetType4[ReferenceTargetType4.values().length];
    static {

        int i = 0;
        for(ReferenceTargetType4 type : ReferenceTargetType4.values()){
          values[i]= type;
          i++;
        }

    }
    ReferenceTargetType4(int value){
      this.value = value;
    }

    int getValue(){
      return this.value;
    }

    static ReferenceTargetType4 fromValue(int value){
      return values[value];
    }

  }

  public enum ReferenceTargetType5 {
    BINARY((byte)0x0),
    TOPIC((byte)0x1),
    MAP((byte)0x2),
    UNKNOWN((byte)0x3);

    private byte value;

    ReferenceTargetType5(byte value){
      this.value = value;
    }

    byte getValue(){
      return this.value;
    }

    static ReferenceTargetType5 fromValue(byte value) {
      switch (value) {
        case 0x0: return BINARY;
        case 0x1: return TOPIC;
        case 0x2: return BINARY;
        case 0x3: return UNKNOWN;
        default:  return UNKNOWN;
      }
    }

  }

  @Test
  public void doPerformanceTest(){

    for(int i = 0; i < masterRuns;i++){
      doRuns(i);
    }

    System.out.println("Run 1 average: " + average(r1runs));
    System.out.println("Run 2 average: " + average(r2runs));
    System.out.println("Run 3 average: " + average(r3runs));
    System.out.println("Run 4 average: " + average(r4runs));
    System.out.println("Run 5 average: " + average(r5runs));
  }

  public void doRuns(int runnum){

    ReferenceTargetType1 type1 = ReferenceTargetType1.UNKNOWN;
    ReferenceTargetType2 type2 = ReferenceTargetType2.UNKNOWN;
    ReferenceTargetType3 type3 = ReferenceTargetType3.UNKNOWN;
    ReferenceTargetType4 type4 = ReferenceTargetType4.UNKNOWN;
    ReferenceTargetType5 type5 = ReferenceTargetType5.UNKNOWN;

    long startTime1 = System.currentTimeMillis();

    for(int i = 0; i < runs;i++){
      ReferenceTargetType1.fromValue(type1.getValue());
    }
    r1runs[runnum] = (System.currentTimeMillis() - startTime1);

    long startTime2 = System.currentTimeMillis();

    for(int i = 0; i < runs;i++){
      ReferenceTargetType2.fromValue(type2.getValue());
    }
    r2runs[runnum] = (System.currentTimeMillis() - startTime2);

    long startTime3 = System.currentTimeMillis();

    for(int i = 0; i < runs;i++){
      ReferenceTargetType3.fromValue(type3.getValue());
    }

    r3runs[runnum] = (System.currentTimeMillis() - startTime3);

    long startTime4 = System.currentTimeMillis();

    for(int i = 0; i < runs;i++){
      ReferenceTargetType4.fromValue(type4.getValue());
    }

    r4runs[runnum] = (System.currentTimeMillis() - startTime4);

    long startTime5 = System.currentTimeMillis();

    for(int i = 0; i < runs;i++){
      ReferenceTargetType5.fromValue(type5.getValue());
    }

    r5runs[runnum] = (System.currentTimeMillis() - startTime5);


  }
}
import org.junit.Test;
导入org.junit.runner.RunWith;
导入org.junit.runners.JUnit4;
导入java.util.HashMap;
导入java.util.Map;
@RunWith(JUnit4.class)
公共类枚举值测试{
静态整数主运行=100;
静态整数运行=100000000;
静态长[]r1runs=新长[主运行];
静态长[]r2runs=新长[主运行];
静态长[]r3runs=新长[主运行];
静态长[]r4runs=新长[主运行];
静态长[]r5运行=新长[主运行];
静态长平均值(长[]值){
int-total=0;
对于(int i=0;iprivate final static ReferenceTargetType TYPES = ReferenceTargetType.values();

public ReferenceTargetType byteToType(byte b) {
    int index = b - 1;
    if (0<=index && index<TYPES.length) return TYPES[index];
    ... throw SomeException or return null;
}
Run 1 average: 57729
Run 2 average: 93424
Run 3 average: 797
Run 4 average: 776
Run 5 average: 237
public enum ReferenceTargetType5 {
    BINARY((byte) 0x0), TOPIC((byte) 0x1), MAP((byte) 0x2), UNKNOWN((byte) 0x3);

    private byte value;

    ReferenceTargetType5(byte value) {
        this.value = value;
    }

    byte getValue() {
        return this.value;
    }

    static ReferenceTargetType5 fromValue(byte value) {
        switch (value) {
        case 0x0: return BINARY;
        case 0x1: return TOPIC;
        case 0x2: return BINARY;
        case 0x3: return UNKNOWN;
        default:  return UNKNOWN;
        }
    }

}