Pregunta

¿Ves algún problema con el uso de una matriz de bytes como clave del Mapa?Yo también podría hacer new String(byte[]) y hash por String pero es más sencillo de usar byte[].

¿Fue útil?

Solución

El problema es que byte[] los usos de la identidad del objeto para equals y hashCode, por lo que

byte[] b1 = {1, 2, 3}
byte[] b2 = {1, 2, 3}

no coinciden en un HashMap.Veo tres opciones:

  1. Envolver en un String, pero entonces usted tiene que tener cuidado acerca de los problemas de codificación (que usted necesita para asegurarse de que el byte -> String -> byte da los mismos bytes).
  2. Uso List<Byte> (puede ser costoso en la memoria).
  3. Hacer su propia envoltura de la clase, escribir hashCode y equals para utilizar el contenido de la matriz de bytes.

Otros consejos

Está bien siempre y cuando usted sólo desea la igualdad de referencia para su clave - matrices de no aplicar "la igualdad de valor" en la forma en que quizás quieras.Por ejemplo:

byte[] array1 = new byte[1];
byte[] array2 = new byte[1];

System.out.println(array1.equals(array2));
System.out.println(array1.hashCode());
System.out.println(array2.hashCode());

imprime algo como:

false
1671711
11394033

(Los números reales son irrelevantes;el hecho de que son diferentes es importante.)

Suponiendo que en realidad quieren igualdad, sugiero crear su propia envoltura que contiene un byte[] e implementa la igualdad y el código hash de la generación adecuadamente:

public final class ByteArrayWrapper
{
    private final byte[] data;

    public ByteArrayWrapper(byte[] data)
    {
        if (data == null)
        {
            throw new NullPointerException();
        }
        this.data = data;
    }

    @Override
    public boolean equals(Object other)
    {
        if (!(other instanceof ByteArrayWrapper))
        {
            return false;
        }
        return Arrays.equals(data, ((ByteArrayWrapper)other).data);
    }

    @Override
    public int hashCode()
    {
        return Arrays.hashCode(data);
    }
}

Tenga en cuenta que si cambia los valores dentro de la matriz de bytes después de usar el ByteArrayWrapper, como una llave en una HashMap (etc) vas a tener problemas a mirar de nuevo la tecla...usted puede tomar una copia de los datos en el ByteArrayWrapper constructor si quieres, pero obviamente que va a ser una pérdida de rendimiento si usted sabe que usted no ser la evolución de los contenidos de la matriz de bytes.

EDITAR:Como se ha mencionado en los comentarios, también se podría utilizar ByteBuffer para esto (en particular, su ByteBuffer#wrap(byte[]) el método).No sé si es realmente lo correcto, dadas todas las habilidades extra que ByteBuffers que no es necesario, pero es una opción.

Podemos utilizar ByteBuffer para esto (Esto es básicamente el byte [] envoltorio con un comparador)

HashMap<ByteBuffer, byte[]> kvs = new HashMap<ByteBuffer, byte[]>();
byte[] k1 = new byte[]{1,2 ,3};
byte[] k2 = new byte[]{1,2 ,3};
byte[] val = new byte[]{12,23,43,4};

kvs.put(ByteBuffer.wrap(k1), val);
System.out.println(kvs.containsKey(ByteBuffer.wrap(k2)));

imprimirá

true

Usted podría utilizar java.math.BigInteger.Tiene un BigInteger(byte[] val) constructor.Es un tipo de referencia, por lo que podría ser utilizado como una clave para la tabla hash.Y .equals() y .hashCode() se definen como para los respectivos números enteros, lo que significa que BigInteger ha coherente es igual a la semántica como byte[] matriz.

Estoy muy sorprendido de que las respuestas no están señalando la alternativa más sencilla.

Sí, no es posible utilizar un HashMap, pero nadie le impide utilizar un SortedMap como alternativa. La única cosa es escribir un comparador que necesita comparar las matrices. No es tan performante como un HashMap, pero si quieres una alternativa sencilla, aquí tienes (se puede sustituir SortedMap con el mapa Si desea ocultar la implementación):

 private SortedMap<int[], String>  testMap = new TreeMap<>(new ArrayComparator());

 private class ArrayComparator implements Comparator<int[]> {
    @Override
    public int compare(int[] o1, int[] o2) {
      int result = 0;
      int maxLength = Math.max(o1.length, o2.length);
      for (int index = 0; index < maxLength; index++) {
        int o1Value = index < o1.length ? o1[index] : 0;
        int o2Value = index < o2.length ? o2[index] : 0;
        int cmp     = Integer.compare(o1Value, o2Value);
        if (cmp != 0) {
          result = cmp;
          break;
        }
      }
      return result;
    }
  }

Esta aplicación se puede ajustar para otras matrices, lo único que hay que tener en cuenta es que la igualdad de las matrices (= igual longitud con miembros iguales) deben devolver 0 y que tiene una orden de determistic

Yo creo que los arrays en Java no necesariamente implementar el hashCode() y equals(Object) métodos de forma intuitiva.Es decir, idénticos dos matrices de bytes no necesariamente comparten el mismo código hash y no necesariamente reclamación a ser igual.Sin estas dos características, su HashMap se comporte de manera inesperada.

Por lo tanto, recomiendo en contra de el uso de byte[] como claves en un HashMap.

Debe utilizar crear una clase como somthing ByteArrKey y código hash sobrecarga y métodos iguales, recordar el contrato entre ellos.

Esto le dará mayor flexibilidad como se puede omitir 0 entradas que se anexan al final del conjunto de bytes, especialmente si copia solamente una parte forma la otra memoria intermedia de bytes.

De esta manera se decide cómo ambos objetos deben ser iguales.

Veo problemas, ya que debe utilizar Arrays.equals y Array.hashCode, en lugar de las implementaciones de matriz por defecto

Arrays.toString (bytes)

También puede convertir el byte [] para una cadena 'seguro' usando Base32 o base 64, por ejemplo:

byte[] keyValue = new byte[] {…};
String key = javax.xml.bind.DatatypeConverter.printBase64Binary(keyValue);

Por supuesto que hay muchas variantes de lo anterior, como:

String key = org.apache.commons.codec.binary.Base64.encodeBase64(keyValue);

Aquí está una solución utilizando TreeMap, interfaz Comparador y java.util.Arrays.equals método Java (byte [], byte []);

NOTA: El orden en el mapa no es relevante con este método

SortedMap<byte[], String> testMap = new TreeMap<>(new ArrayComparator());

static class ArrayComparator implements Comparator<byte[]> {
    @Override
    public int compare(byte[] byteArray1, byte[] byteArray2) {

        int result = 0;

        boolean areEquals = Arrays.equals(byteArray1, byteArray2);

        if (!areEquals) {
            result = -1;
        }

        return result;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top