Question

Avez-vous un problème avec l'aide d'un tableau d'octets comme la clé carte? Je pourrais aussi faire et hachage par new String(byte[]) mais il est String plus simple à utiliser byte[].

Était-ce utile?

La solution

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

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

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

  1. dans un emballage String, mais vous devez être prudent sur le codage des questions (vous devez vous assurer que l'octet -> String -> octet vous donne le même octets).
  2. Utilisez List<Byte> (peut être coûteux en mémoire).
  3. Faites votre propre classe d'emballage, l'écriture et <=> utiliser le <=> contenu du tableau d'octets.

Autres conseils

Il est normal aussi longtemps que vous voulez que l'égalité de référence pour votre clé - tableaux ne mettent pas en œuvre « l'égalité de valeur » de la manière que vous voudrez probablement. 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 ne sont pas pertinentes, le fait qu'ils sont différents est important.)

En supposant que vous en fait veulent l'égalité, je vous suggère de créer votre propre enveloppe qui contient une génération et met en œuvre byte[] d'égalité et de code de hachage 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 avoir utilisé le ByteArrayWrapper, comme une clé dans un HashMap (etc), vous aurez des problèmes regardant à nouveau la touche ... vous pouvez prendre une copie des données dans le constructeur si vous voulez ByteBuffer, mais il est évident que ce sera une perte de performances si vous savez que vous pas être modifier le contenu du tableau d'octets.

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

Nous pouvons utiliser ByteBuffer pour cela (Ceci est essentiellement l'octet wrapper [] 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

Vous pouvez utiliser java.math.BigInteger. Il a un constructeur BigInteger(byte[] val). Il est un type de référence, donc peut être utilisé comme une clé pour Hashtable. Et .equals() et .hashCode() sont définis comme pour des nombres entiers respectifs, ce qui signifie BigInteger a cohérente est égal sémantique que l'octet matrice [].

Je suis très surpris que les réponses ne pointent pas vers la solution la plus simple.

Oui, il est impossible d'utiliser un HashMap, mais personne ne vous empêche d'utiliser un SortedMap comme alternative. La seule chose est d'écrire un Comparator qui a besoin de comparer les tableaux. Il n'est pas aussi performant que HashMap, mais si vous voulez une alternative simple, ici vous allez (vous pouvez remplacer SortedMap avec carte si vous souhaitez masquer la mise en œuvre):

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

Cette mise en œuvre peut être ajustée pour d'autres tableaux, la seule chose que vous devez savoir est que les tableaux égaux (= longueur égale avec des membres égaux) doivent retourner 0 et que vous avez un ordre determistic

Je crois que les tableaux en Java ne mettent pas nécessairement les méthodes hashCode() et intuitivement equals(Object). À savoir, deux tableaux d'octets identiques partagent pas nécessairement le même code de hachage et ils réclameront pas nécessairement égale. Sans ces deux traits, votre HashMap se comportera de façon inattendue.

Par conséquent, je vous recommande contre en utilisant comme clés dans byte[] HashMap.

Vous devez utiliser créer un somthing de classe comme ByteArrKey et hashcode de surcharge et les méthodes égales, rappelez-vous le contrat entre eux.

Cela vous donnera une plus grande flexibilité que vous pouvez sauter 0 entrées qui sont ajoutés à la fin du tableau d'octets, surtout si vous copiez seulement une partie forme l'autre tampon d'octets.

De cette façon, vous décidez comment les deux objets doivent être égaux.

Je vois des problèmes puisque vous devez utiliser Arrays.equals et Array.hashCode, en place des implémentations de tableau par défaut

Arrays.toString (octets)

Vous pouvez également convertir l'octet [] à une chaîne « sûr » en utilisant Base32 ou base64, par exemple:

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

Bien sûr, il existe de nombreuses variantes de ce qui précède, comme:

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

Voici une solution en utilisant TreeMap, interface Comparator et méthode Java java.util.Arrays.equals (byte [], byte []);

NOTE: L'ordre sur la carte ne sont pas pertinentes avec cette méthode

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;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top