2011-11-23 8 views
7

Ho un oggetto punto:Una chiave complessa per guaiave Cache (shifting)

class Point { 
    final int x,y; 
    ... 
    } 

Dato che questi punti saranno utilizzati/creato in tutto il luogo nel mio codice, voglio iniziare a utilizzare la cache guaiave. Unfortuinally il CacheLoader accetta solo un parametro. Another question qui su stackoverflow utilizzare un oggetto coppia per un problema simile. Ma non mi piace l'idea di creare un oggetto fittizio per ogni richiesta di cache. Quindi mi viene in mente la mia soluzione:

Poiché l'oggetto è specificato da x e y, penso di poter unire (spostare) entrambi i valori in un valore lungo, che sarà la mia chiave.

void test(int x, int y) { 
    Long key = (long) ((long) (x) << Integer.SIZE | y); 
    Point point = cache.get(key); 
} 

CacheLoader<Long, Point> loader = new CacheLoader<Long, Point>() { 
    public Point load(Long key) throws Exception { 
    final int x,y; 
     // shift magic 
     x = (int) (key >> Integer.SIZE); 
     y = key.intValue(); 
     return new Point(x, y); 
    } 
}; 

In realtà sono un noob turno. Funzionerà? Ho dimenticato qualcosa? Questo è "più veloce" rispetto alla coppia? Questa è la mia domanda!

Sì, provo il codice e funziona così lontano che posso dire.

+3

yikes. * Per favore * crea un oggetto reale (con due campi ben denominati) per il punto! Stai già creando un oggetto "fittizio", un java.lang.Long, solo più offuscato. –

risposta

7

ne dici di questo? La classe Point deve implementare correttamente equals() e hashcode().

Il tuo vero scopo era quello di memorizzare nella cache oggetti uguali, giusto? Di questo basterà i tuoi bisogni. Uso:

Point center = Points.cached(0, 0); 

o una versione adjusted del vostro esempio di cache:

CacheLoader<Point, Point> loader = new CacheLoader<Point, Point>() { 
    @Override 
    public Point load(final Point point) { 
    return point; 
    } 
} 
... 
Point center = cache.get(new Point(0, 0)); 
+0

Hum questo interner è nuovo per me. Sembra interessante. Grazie! Ovviamente sono 'equals' e' hashcode' implementano correttamente. Non voglio che il signor Bloch mi metta nell'inferno di Java MrGreen –

+4

Ouch. Pessima idea Innanzitutto, trasformi gli oggetti con un piccolo ciclo di vita (pezzo di torta per tutti i raccoglitori di rifiuti) in oggetti di riserva, rendendo più lento il futuro di tutti i gc completi. Quindi, questa cosa cresce senza limiti, non molto diversa da una perdita di memoria. In terzo luogo, solo per pareggiare in termini di memoria, * tutti i punti memorizzati nella cache dovrebbero essere conservati almeno in due punti *. Solo se vengono riutilizzati di più sarebbe una qualsiasi memoria salvata. Per non parlare del fatto che questi * oggetti * non * devono essere tenuti in giro, tranne che per la ricerca, per non parlare di essere tenuti in giro in due punti. Vorrei prendere in considerazione l'eliminazione di questa risposta: - \ –

+0

Hai ragione. L'implementazione di StrongInterner memorizzerebbe punti fino alla fine. Interners.newWeakInterner() farebbe il trucco. Il beneficio viene raggiunto solo se i punti vengono realmente riutilizzati. – bjmi

2

Probabilmente è più veloce (se la differenza è misurabile), ma la classe di coppia renderà il codice molto più facile da capire o riutilizzare. Mi piacerebbe andare con una classe generica coppia:

public final class Pair<L, R> { 

    private final L left; 
    private final R right; 

    private Pair(L left, R right) { 
     this.left = left; 
     this.right = right; 
    } 

    public static <L,R>Pair<L,R> of(L left, R right){ 
     return new Pair<L, R>(left,right); 
    } 

    @Override 
    public boolean equals(final Object obj) { 
     if (obj instanceof Pair) { 
      final Pair<?,?> other = (Pair<?,?>) obj; 
      return Objects.equal(left, other.left) 
       && Objects.equal(right, other.right); 
     } else { 
      return false; 
     } 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hashCode(left, right); 
    } 

    @Override 
    public String toString() { 
     return MoreObjects.toStringHelper(this) 
         .add("left", left) 
         .add("right", right) 
         .toString(); 
    } 

} 

Una volta che avete nella vostra base di codice, troverete più di un uso per esso. Lo spostamento dei bit non è proprio simile a Java (anche se molti altri non saranno d'accordo).

Guava docs

+0

Ok, la differenza potrebbe non essere misurabile. Fatto! Ma quali sono gli svantaggi che hai menzionato ?! Questa era una delle mie domande in primo luogo. –

+1

@MarcelJaeschke utilizzando oggetti rende il codice leggibile, comprensibile e riutilizzabile. il bit shifting no. Se me lo chiedi, è l'ottimizzazione prematura. –

+0

Sì, conosco molto bene il concetto di OOP! Ma penso che la tua strada sia solo una specie di sovraingegneria! Il punto dell'oggetto consiste solo di due campi int. La tua classe di coppia ha questi due campi! In effetti crei una copia dell'oggetto! Quindi puoi effettivamente usare l'oggetto come chiave in primo luogo! Voglio dire (mi dispiace per il formato): Punto punto = nuovo punto (x, y); Punto pointFromCache = cache.get (punto); CacheLoader loader = nuovo CacheLoader () { Punto pubblico carico (tasto Puntatore) genera Eccezione { chiave di ritorno; } }; –

Problemi correlati