2011-11-23 22 views
7

के लिए एक जटिल कुंजी मैं एक बिंदु वस्तु है:अमरूद कैश (स्थानांतरण)

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

क्योंकि इन बातों का प्रयोग किया जाएगा/मेरी कोड में जगह भर में बनाया है, मैं अमरूद कैश का उपयोग शुरू करना चाहते हैं। असुविधाजनक रूप से कैशलोडर केवल एक पैरामीटर स्वीकार करता है। Another question यहां स्टैक ओवरफ्लो पर एक समान समस्या के लिए एक जोड़ी ऑब्जेक्ट का उपयोग करें। लेकिन मुझे हर कैश अनुरोध के लिए डमी ऑब्जेक्ट बनाने का विचार पसंद नहीं है। तो मैं अपने स्वयं के कामकाज के साथ आया:

क्योंकि ऑब्जेक्ट x और y द्वारा निर्दिष्ट किया गया है, मुझे लगता है कि मैं दोनों मानों को एक लंबे समय में विलय कर सकता हूं, जो मेरी कुंजी होगी।

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

मैं वास्तव में एक पारी noob हूँ। यह काम करेगा? क्या मैं कुछ भुल गया? क्या यह जोड़ी वर्ग की तुलना में "तेज" है? यह मेरा सवाल है!

हाँ, मैं कोड का परीक्षण करता हूं और यह अब तक काम करता है मैं बता सकता हूं।

+3

उफ़। * कृपया * बिंदु के लिए एक असली वस्तु (दो अच्छी तरह से नामित फ़ील्ड के साथ) बनाएँ! आप पहले से ही 'डमी' ऑब्जेक्ट बना रहे हैं, एक java.lang.Long, बस अधिक obfuscated। –

उत्तर

7

कैसे इस बारे में? आपकी प्वाइंट क्लास को equals() और hashcode() को सही ढंग से कार्यान्वित करना होगा।

static class Points { 
    static final Interner<Point> INTERNER = Interners.newStrongInterner(); 

    public static Point cached(final int x, final int y) { 
    return INTERNER.intern(new Point(x, y)); 
    } 
} 

आपका वास्तविक उद्देश्य समान वस्तुओं को कैश करना था, है ना? इससे आपकी ज़रूरतें पूरी होंगी। उपयोग:

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

या अपने कैश उदाहरण के एक समायोजित संस्करण:

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

हम यह इंटर्नर मेरे लिए नया है। दिलचस्प लग रहा है। धन्यवाद! बेशक 'बराबर' और 'हैशकोड' सही तरीके से लागू होते हैं। मैं नहीं चाहता कि श्री ब्लोच ने मुझे जावा-नरक में रखा :- डी –

+4

ओच। बहुत बुरा विचार। सबसे पहले, आप ऑब्जेक्ट्स को एक छोटे से जीवन चक्र (सभी कचरा कलेक्टरों के लिए केक का टुकड़ा) के साथ बदलते ऑब्जेक्ट्स में बदल रहे हैं, जिससे भविष्य में पूर्ण जीसी धीमा हो जाता है। फिर, यह बात असीमित हो जाती है, स्मृति स्मृति रिसाव से बहुत अलग नहीं है। तीसरा, स्मृति के संदर्भ में भी तोड़ने के लिए, * सभी कैश किए गए बिंदुओं को कम से कम दो स्थानों पर बनाए रखा जाना चाहिए *। केवल अगर उनका पुन: उपयोग किया जाता है तो कोई भी स्मृति सहेजने वाला होगा। अकेले रहने दो कि लुकअप के अलावा, इन वस्तुओं को * चारों ओर रखने की आवश्यकता नहीं है, अकेले ही दो स्थानों पर रखें। मैं इस जवाब को हटाने पर विचार करता हूं: - \ –

+0

आप सही हैं। StrongInterner कार्यान्वयन अंत तक अंक स्टोर करेगा। Interners.newWeakInterner() चाल करेगा। लाभ केवल तब तक पहुंच जाता है जब अंक वास्तव में पुन: उपयोग किए जाते हैं। – bjmi

2

यह शायद तेज़ है (यदि अंतर बिल्कुल मापने योग्य है), लेकिन जोड़ी कक्षा आपके कोड को समझने या पुन: उपयोग करने के लिए बेहतर बनाती है। मैं एक सामान्य जोड़ी वर्ग के साथ जाना चाहते हैं:

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

} 

एक बार जब आप है कि अपने कोड बेस में, आप इसके लिए एक से अधिक उपयोग मिलेगा है। बिट स्थानांतरण वास्तव में जावा की तरह नहीं है (हालांकि कई अन्य असहमत होंगे)।

Guava docs

+0

ठीक है, अंतर शायद मापने योग्य नहीं है। समझ गया! लेकिन आप किस नुकसान का उल्लेख करते हैं ?! यह पहली जगह में मेरा एक प्रश्न था। –

+1

@ मर्ससेल जैस्के ऑब्जेक्ट्स का उपयोग करके आपके कोड को पठनीय, समझने योग्य और पुन: प्रयोज्य बनाता है। बिट स्थानांतरण नहीं करता है। यदि आप मुझसे पूछते हैं, तो यह समयपूर्व अनुकूलन है। –

+0

हां मुझे ओओपी की अवधारणा बहुत अच्छी तरह से पता है! लेकिन मुझे लगता है कि आपका रास्ता सिर्फ एक तरह का इंजीनियरिंग है! ऑब्जेक्ट पॉइंट में केवल दो int फ़ील्ड होते हैं। आपकी जोड़ी कक्षा में इन क्षेत्र दो हैं! वास्तव में आप वस्तु की एक प्रति बनाते हैं! तो आप वास्तव में वस्तु को पहले स्थान पर कुंजी के रूप में उपयोग कर सकते हैं! मेरा मतलब है (प्रारूप के लिए खेद है): प्वाइंट बिंदु = नया प्वाइंट (एक्स, वाई); प्वाइंट pointFromCache = cache.get (बिंदु); CacheLoader <प्वाइंट, प्वाइंट> लोडर = नए CacheLoader <प्वाइंट, प्वाइंट>() { सार्वजनिक प्वाइंट लोड (प्वाइंट कुंजी) अपवाद { वापस कुंजी फेंकता है; } }; –