74 votes

Utilisation d'un tableau d'octets en tant que clé HashMap (Java)

Voir le sujet - voyez-vous un problème avec cela? Je pourrais aussi faire new String(byte[]) et hachage de String mais il est plus simple d’utiliser byte[]

75voto

Jon Skeet Points 692016

C'est ok aussi longtemps que vous voulez seulement référence à l'égalité pour votre clé - tableaux de ne pas mettre en œuvre "la valeur de l'égalité", dans le sens que vous auriez probablement souhaitez. Par exemple:

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 quelque chose comme:

false
1671711
11394033

(Les chiffres réels sont sans importance; le fait qu'ils sont différents, c'est important.)

En supposant que vous avez réellement envie de l'égalité, je vous suggère de créer votre propre surcouche qui contient un byte[] et met en œuvre l'égalité de hachage et de génération de code de façon appropriée:

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);
    }
}

Notez que si vous modifiez les valeurs dans le tableau d'octets après l'utilisation de l' ByteArrayWrapper, comme une clé dans une HashMap (etc), vous aurez des problèmes à la recherche de la clé de nouveau... vous pouvez prendre une copie des données dans l' ByteArrayWrapper constructeur si vous le souhaitez, mais évidemment ce sera une perte de performance si vous savez que vous ne serez pas être en train de changer le contenu du tableau d'octets.

EDIT: Comme mentionné dans les commentaires, vous pouvez également utiliser ByteBuffer (en particulier, de son ByteBuffer#wrap(byte[]) méthode). Je ne sais pas si c'est vraiment une bonne chose, compte tenu de toutes les capacités supplémentaires qu' ByteBuffers qui vous n'avez pas besoin, mais c'est une option.

62voto

Kathy Van Stone Points 10310

Le problème est qu' byte[] utilise l'identité de l'objet pour equals et hashCode, de sorte que

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

ne correspondra pas à un HashMap. Je vois trois options:

  1. Emballage en String,, mais alors vous devez être prudent au sujet de problèmes de codage (vous avez besoin pour faire certain que l'octet -> String -> byte vous donne les mêmes octets).
  2. Utiliser List<Byte> (peut être coûteux en mémoire).
  3. Faire votre propre emballage de la classe, de l'écriture hashCode et equals à utiliser le contenu du tableau d'octets.

43voto

byte_array Points 594

Nous pouvons utiliser ByteBuffer pour cela (Il s’agit essentiellement du wrapper byte [] avec un comparateur)

 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)));
 

imprimera

 true
 

12voto

Artem Oboturov Points 2292

Vous pouvez utiliser java.math.BigInteger . Il a un constructeur BigInteger(byte[] val) . C'est un type de référence, il pourrait donc être utilisé comme clé pour hashtable. Et .equals() et .hashCode() sont définis comme pour les nombres entiers respectifs, ce qui signifie que BigInteger a une sémantique égale à égale sous forme de tableau byte [].

1voto

Adam Paynter Points 22056

Je pense que les tableaux en Java n'implémentent pas nécessairement les méthodes hashCode() et equals(Object) intuitive. C'est-à-dire que deux tableaux d'octets identiques ne partageront pas nécessairement le même code de hachage et ne prétendront pas nécessairement être égaux. Sans ces deux traits, votre HashMap se comportera de manière inattendue.

Par conséquent, je vous recommande de ne pas utiliser byte[] comme clés dans un HashMap.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X