9
votes

Cartes imbriquées ou clés combinées en Java

J'ai besoin d'une carte pour faire un cache en Java pour les mêmes valeurs que j'ai deux clés de chaîne. Ma question Il est préférable de faire des cartes imbriquées (une pour chaque touche) ou de créer un type de clé personnalisé fabriqué avec les deux chaînes?

L'accès aux données sur le cache y accédera tous fois avec les deux clés et je n'ai pas besoin de le grouper par aucune de ces deux clés.

Ensuite, si c'est mieux combiner la clé de chaîne en un seul de quoi c'est mieux?

  • classe personnalisée avec la méthode personnalisée gethash . Mais alors le problème est ce que la fonction de hachage est mise en œuvre?
  • Concaténer simplement deux cordes ensemble. Par exemple:

    cache.put (clé1 + key2, valeur)


0 commentaires

6 Réponses :


2
votes

Utiliser des clés combinées semble plus logique pour moi et plus facile à utiliser (vous n'avez pas à vous soucier de la carte imbriquée d'être instantanée).

À propos de la combinaison des touches, utilisez une classe personnalisée. Il a plus de sens sémantiquement et empêche les colis que si vous avez des chaînes similaires. Une telle colision pourrait apparaître si vous avez la clé ["AB", "C"] et la clé ["A", "BC"] . .

N'oubliez pas que lorsque vous écrivez votre classe personnalisée, vous devez écrire le Equals et méthodes correctement, ou votre cache pourrait ne pas fonctionner (et pourrait subir des problèmes de performance. ).


0 commentaires

3
votes

Il est préférable de créer des cartes imbriquées (une pour chaque touche) ou de faire un type de clé personnalisé fabriqué avec les deux chaînes?

Une seule hache avec un type de clé composite peut avoir une meilleure localité de référence. Cela prendra presque moins de mémoire et sera un peu plus rapide, bien que cela dépend de votre application.

La conception d'une fonction de hachage personnalisée peut être délicate, mais vous pouvez commencer par une fonction qui prend simplement les hachages déjà définis des membres de la clé composite et les xors les ensemble. Vous pouvez également prendre la route à cordes, mais assurez-vous de concaténer les membres avec un marqueur entre eux (tels que ": "), il est peu probable de se produire dans eux.


0 commentaires

12
votes

Vous pouvez simplement créer des cartes imbriquées ou utiliser une classe personnalisée définissant hashcode () code>.

Ce n'est généralement pas une bonne idée de concaténer les clés, vous pouvez vous retrouver avec des collisions, comme dans le Cas avec clés 1 code> et 22 code> et des touches 12 code> et 2 code>. Ils mappaient à la même valeur 122 code>. P>

Si vous utilisez toujours les deux clés, à l'aide d'une seule carte code> sera toujours un peu plus efficace, et vous pouvez toujours définir votre propre adaptateur à la carte qui prendra deux arguments: p> xxx pré>

N'oubliez pas de définir égale () code> et et hashcode () code> dans votre classe de clé personnalisée (ajouter des chèques pour la nullité si nécessaire). P>

public int hashCode() {
    int result = 17;
    result = 37 * result + keyA.hashCode();
    result = 37 * result + keyB.hashCode();
    return result;
}

public boolean equals(Object another) { 
    return another.keyA.equals(keyA) && another.keyB.equals(keyB);
} 


0 commentaires

0
votes

Je pense que l'utilisation de cartes imbriquées est moins optimale. Je suis d'accord avec votre deuxième pensée - implémentez une classe personnalisée avec la nervation hashcode
xxx


et est égal à
xxx

n'oublie pas non plus de remplacer les mêmes méthodes de la classe d'objet stockée.

alors, en cas de ["AB", "C "] Vous aurez le même code de hachage, mais différents sont égaux de résultat


0 commentaires

12
votes

Vous voudrez peut-être envisager de Guava Table cours. Ils implémentent une carte code> avec deux clés par valeur. Cela peut fournir une solution plus lisible qu'une clé composite en fonction de vos besoins.

Table<String, String, MyValue>


3 commentaires

Merci beaucoup, c'était exactement ce que je cherchais! Seulement trébuché sur les multimaps de Guava, ce qui n'était pas assez pratique pour moi. ;)


Une note sur HashbasedTable de Guava, il utilise une approche de carte imbriquée.


Peut-il être stocké dans Redis?



1
votes

J'ai eu un problème similaire avec un système de mise en cache qui devait utiliser des paramattres de méthode pour la génération de clé. J'ai fini par écrire une classe d'enveloppe similaire à la réponse de Xavi.

public final class ArrayWrapper 
{
    private final Object[] array;

    public ArrayWrapper(final Object... array)
    {
        this.array = array;
    }

    public Object[] getArray()
    {
        return this.array;
    }

    public boolean equals(Object o)
    {
        if (o == null) return false;
        if (o == this) return true;
        if (o instanceof ArrayWrapper)
        {
            return Arrays.equals(this.array, ((ArrayWrapper)o).array);
        }
        return false;
    }

    private int hashCode(Object o)
    {
        if (o == null) return 0;
        return o.hashCode();
    }

    public int hashCode()
    {
        int sum = 17;
        if (this.array != null) for(int i = 0;i<this.array.length;i++)
        {
            sum = 37 * sum + this.hashCode(this.array[i]);
        }
        return sum;
    }

    public String toString()
    {
        if (this.array != null)
        {
            return "Wrapper " + Arrays.toString(array);
        }
        else return "Wrapper []";
    }
}


0 commentaires