Java の Map で byte 配列をキーにするときの注意点

    はじめに

    Java で HashMap のキーに byte[] 配列を利用したら, key を put しても containsKey で key がないよといわれてしまった.

    static void testbyteMap () {
        Map<byte[], Integer> map = new HashMap<byte[], Integer>();
        byte[] key = {1,2,3};
        byte[] key2 = {4,5,6};
        byte[] key3 = {1,2,3};
    
        map.put (key,1);
        map.put (key2,2);
    
        System.out.println (map.containsKey (key));
        System.out.println (map.containsKey (key2));
        System.out.println (map.containsKey (key3));
    }

    結果

    true
    true
    false

    調査

    どうも配列を入れても, うまく検出できないようだ.

    同一オブジェクトだと, 大丈夫だが, 値が同じでも違うオブジェクトだとだめ.

    static void testIntMap () {
        Map<int[], Integer> map = new HashMap<int[], Integer>();
        int[] key = {1,2,3};
        int[] key2 = {4,5,6};;
        int[] key3 = {1,2,3};;
    
        map.put (key,1);
        map.put (key2,2);
    
        System.out.println (map.containsKey (key));
        System.out.println (map.containsKey (key2));
        System.out.println (map.containsKey (key3));
    }

    解決策

    原因は, byte[] が 大小比較できないから.

    Stack Overflow によると

    • byte[] を String に変換
    • byte[] をを List<Byte>に変換
    • equals と hashmap を実装した ラッパーデータ型を作成

    String 変換を試す

    一番お手軽なのは, String 変換か?

    static void testStringMap () throws UnsupportedEncodingException {
        Map<String, Integer> map = new HashMap<String, Integer>();
        byte[] key = {1,2,3};
        byte[] key2 = {4,5,6};
        byte[] key3 = {1,2,3};
    
        String keyStr = new String (key, "UTF-8");
        String keyStr2 = new String (key2, "UTF-8");
        String keyStr3 = new String (key3, "UTF-8");        
    
        map.put (keyStr,1);
        map.put (keyStr2,2);
    
        System.out.println (map.containsKey (keyStr));
        System.out.println (map.containsKey (keyStr2));
        System.out.println (map.containsKey (keyStr3));
    }
    
    static void testStringMap2 () throws UnsupportedEncodingException {
        Map<String, Integer> map = new HashMap<String, Integer>();
        byte[] key = {1,2,3};
        byte[] key2 = {4,5,6};
        byte[] key3 = {1,2,3};
    
        String keyStr = Arrays.toString (key);
        String keyStr2 = Arrays.toString (key2);
        String keyStr3 = Arrays.toString (key3);        
    
        map.put (keyStr,1);
        map.put (keyStr2,2);
    
        System.out.println (map.containsKey (keyStr));
        System.out.println (map.containsKey (keyStr2));
        System.out.println (map.containsKey (keyStr3));
    }

    結果

    これで OK.

    true
    true
    true

    Special Thanks