読者です 読者をやめる 読者になる 読者になる

Java8時代のenum逆引きあれこれ

前に同僚と話題になったので。最初HogeAで考えていて、同僚がHogeBがいいよといい。

実行コード

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.common.collect.Maps;

public class EnumSample {

    public static void main(String[] args) {

        {
            long base = System.currentTimeMillis();
            for (int i = 0; i < 1000000; i++) {
                HogeTypeA type = HogeTypeA.getEnum(1);
            }
            long diff = System.currentTimeMillis() - base;
            System.out.println("testA:" + String.valueOf(diff));
        }

        {

            long base = System.currentTimeMillis();
            for (int i = 0; i < 1000000; i++) {
                HogeTypeB type = HogeTypeB.getEnum(1);
            }
            long diff = System.currentTimeMillis() - base;
            System.out.println("testB:" + String.valueOf(diff));
        }
        {

            long base = System.currentTimeMillis();
            for (int i = 0; i < 1000000; i++) {
                HogeTypeC type = HogeTypeC.getEnum(1);
            }
            long diff = System.currentTimeMillis() - base;
            System.out.println("testC:" + String.valueOf(diff));
        }

    }

}

enum HogeTypeA {

    ON(0),
    OFF(1);

    private int code;

    private HogeTypeA(int code) {
        this.code = code;
    }

    public int code() {
        return this.code;
    }

    public static HogeTypeA getEnum(int code) {
        return toEnum.get(code);
    }

    private static Map<Integer, HogeTypeA> toEnum = new HashMap<Integer, HogeTypeA>() {
        private static final long serialVersionUID = 1L;
        {
            Stream.of(HogeTypeA.values())
                    .forEach(type -> {
                        put(type.code(), type);
                    });
            ;
        }
    };
}

enum HogeTypeB {

    ON(0),
    OFF(1);

    private int code;

    private HogeTypeB(int code) {
        this.code = code;
    }

    public int code() {
        return this.code;
    }

    public static HogeTypeB getEnum(int code) {
        return toEnum.get(code);
    }

    private static final Map<Integer, HogeTypeB> toEnum = Maps.newHashMap();
    static {
        for (HogeTypeB type : values())
            toEnum.put(type.code(), type);
    }
}

enum HogeTypeC {

    ON(0),
    OFF(1);

    private int code;

    private HogeTypeC(int code) {
        this.code = code;
    }

    public int code() {
        return this.code;
    }

    public static HogeTypeC getEnum(int code) {
        return toEnum.get(code);
    }

    private static final Map<Integer, HogeTypeC> toEnum;
    static {
        toEnum = Stream.of(HogeTypeC.values())
                .collect(Collectors.toMap(HogeTypeC::code, type -> type));
    }
}

実行結果

testA:89
testB:48
testC:53

単純な実行だとHogeBが早そう。

Cも悪くなさそうなんだけど、JVMの最適化のせいなのか、Aを抜いて、BとCだけ実行すると下記のようなスコアになるので、Streamは速度いまいちっぽいのよね。

実行結果2

testB:45
testC:118