2013-10-09 8 views
40

मैं बहुत अधिक Map.computeIfAbsent का उपयोग करना चाहता हूं लेकिन यह लैम्ब्डा अंडरग्रेड में बहुत लंबा रहा है।मैं नए computeIfAbsent फ़ंक्शन का उपयोग कैसे करूं?

लगभग डॉक्स से सीधे:

Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>(); 
String key = "snoop"; 
if (whoLetDogsOut.get(key) == null) { 
    Boolean isLetOut = tryToLetOut(key); 
    if (isLetOut != null) 
    map.putIfAbsent(key, isLetOut); 
} 

और नया तरीका:

map.computeIfAbsent(key, k -> new Value(f(k))); 

लेकिन उनकी उदाहरण में, मुझे लगता है कि यह काम करने के लिए पुराने तरीके का एक उदाहरण देता है मैं काफी "इसे प्राप्त नहीं कर रहा हूं।" मैं इसे व्यक्त करने के नए लैम्ब्डा तरीके का उपयोग करने के लिए कोड कैसे बदलूं?

+0

मुझे यकीन है कि तुम वहाँ उदाहरण से समझ में नहीं आता क्या नहीं कर रहा हूँ के बारे में एक अच्छा बात किया था? –

+2

"के" क्या है? क्या यह एक चर परिभाषित किया जा रहा है? "नया मूल्य" के बारे में - क्या यह जावा 8 से कुछ है, या किसी ऑब्जेक्ट का प्रतिनिधित्व करने के लिए मुझे परिभाषित करने या ओवरराइड करने की आवश्यकता है? WhoLetDogsOut.computeIfAbsent (कुंजी, के -> नया बूलियन (tryToLetOut (k))) संकलित नहीं करता है, इसलिए मुझे कुछ याद आ रहा है ... –

+0

वास्तव में संकलित नहीं करता है? यह किस त्रुटि का उत्पादन करता है? – axtavt

उत्तर

43

मान लीजिए आप निम्नलिखित कोड है:

import java.util.Map; 
import java.util.concurrent.ConcurrentHashMap; 

public class Test { 
    public static void main(String[] s) { 
     Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>(); 
     whoLetDogsOut.computeIfAbsent("snoop", k -> f(k)); 
     whoLetDogsOut.computeIfAbsent("snoop", k -> f(k)); 
    } 
    static boolean f(String s) { 
     System.out.println("creating a value for \""+s+'"'); 
     return s.isEmpty(); 
    } 
} 

तो फिर तुम संदेश creating a value for "snoop" ठीक एक बार computeIfAbsent के दूसरे मंगलाचरण के रूप में देखेंगे कि कुंजी के लिए एक मूल्य पहले से ही वहाँ है। लैम्ब्डा अभिव्यक्ति k -> f(k) में k कुंजी की गणना करने के लिए मानचित्र आपके लैम्ब्डा को पास करने वाली कुंजी के लिए केवल एक प्लेसहोल्डर (पैरामीटर) है। तो उदाहरण में कुंजी फ़ंक्शन आमंत्रण को पास कर दी जाती है।

वैकल्पिक रूप से आप एक हेलपर विधि के बिना एक ही परिणाम प्राप्त करने के लिए whoLetDogsOut.computeIfAbsent("snoop", k -> k.isEmpty()); लिख सकते हैं (लेकिन तब आप डिबगिंग आउटपुट नहीं देखेंगे)। और यहां तक ​​कि सरल, क्योंकि यह एक मौजूदा विधि के लिए एक साधारण प्रतिनिधिमंडल है जिसे आप लिख सकते हैं: whoLetDogsOut.computeIfAbsent("snoop", String::isEmpty); इस प्रतिनिधिमंडल को लिखे जाने वाले किसी भी पैरामीटर की आवश्यकता नहीं है।

अपने प्रश्न में उदाहरण के करीब होने के लिए, आप इसे whoLetDogsOut.computeIfAbsent("snoop", key -> tryToLetOut(key)); के रूप में लिख सकते हैं (इससे कोई फ़र्क नहीं पड़ता कि आप k या key पैरामीटर का नाम दें)। या इसे whoLetDogsOut.computeIfAbsent("snoop", MyClass::tryToLetOut); के रूप में लिखें यदि tryToLetOutstatic या whoLetDogsOut.computeIfAbsent("snoop", this::tryToLetOut); है tryToLetOut एक उदाहरण विधि है।

66

हाल ही में मैं इस विधि के साथ भी खेल रहा था। मैंने कैलकुलेट फाइबोनैकी संख्याओं के लिए एक ज्ञापन एल्गोरिदम लिखा जो विधि का उपयोग करने के तरीके पर एक और उदाहरण के रूप में कार्य कर सकता है।

हम एक मानचित्र को परिभाषित करने और आधार के मामलों के लिए उस में मूल्यों डाल, अर्थात्, fibonnaci(0) और fibonacci(1) द्वारा शुरू कर सकते हैं:

private static Map<Integer,Long> memo = new HashMap<>(); 
static { 
    memo.put(0,0L); //fibonacci(0) 
    memo.put(1,1L); //fibonacci(1) 
} 

और आगमनात्मक कदम के लिए हम सभी क्या करना है हमारे फाइबोनैचि समारोह को फिर से परिभाषित है इस प्रकार है:

public static long fibonacci(int x) { 
    return memo.computeIfAbsent(x, n -> fibonacci(n-2) + fibonacci(n-1)); 
} 

आप देख सकते हैं, विधि computeIfAbsent प्रदान की लैम्ब्डा अभिव्यक्ति फिबोनैकी संख्या की गणना करने के लिए जब संख्या मानचित्र में मौजूद नहीं है का उपयोग करेगा। यह पारंपरिक, वृक्ष रिकर्सिव एल्गोरिदम पर एक महत्वपूर्ण सुधार का प्रतिनिधित्व करता है।

+3

पर सेट किया गया था, गतिशील प्रोग्रामिंग के लिए अच्छा, सिंगल-लाइन रूपांतरण। बहुत चालाक –

+2

+1, मुझे यह फिबोनाकी संस्करण पसंद है: डी –

+2

यदि आपके पास पहले (एन -2) कॉल है तो आपको कम रिकर्सिव कॉल मिल सकती हैं? –

13

एक और उदाहरण। नक्शे के जटिल मानचित्र का निर्माण करते समय, computeIfAbsent() विधि मानचित्र की get() विधि के लिए एक प्रतिस्थापन है।

// Stores regional movie ratings 
    Map<String, Map<Integer, Set<String>>> regionalMovieRatings = new TreeMap<>(); 

    // This will throw NullPointerException! 
    regionalMovieRatings.get("New York").get(5).add("Boyhood"); 

    // This will work 
    regionalMovieRatings 
    .computeIfAbsent("New York", region -> new TreeMap<>()) 
    .computeIfAbsent(5, rating -> new TreeSet<>()) 
    .add("Boyhood"); 
-8

computeIfAbsent() और सरल पुट (का उपयोग कर के बीच कोई अंतर नहीं है) (मिल) के
कार्य: computeIfAbsent() कॉल एक साथ, लापता कंटेनर प्रदान की लैम्ब्डा भाव से ऑन-द-फ्लाई निर्माण कर रहे हैं की श्रंखला के माध्यम से एक नक्शा।दूसरे शब्दों में आप इस तरह से अपने कार्य को फिर से लिखने कर सकते हैं

for (char ch : input){ 
      Integer value; 
      if(countMap.containsKey(ch)){ 
       value = countMap.get(ch); 
       value++; 
       countMap.put(ch, value); 
      } 
      else{ 
       value = 1; 
       countMap.put(ch, value); 

      } 
     } 
+0

क्या कोई डाउनवॉट्स को समझा सकता है? – alexander

4

में यह बहुत सहायक आप अमरूद पुस्तकालय (https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html)

का उपयोग कर उदाहरण के लिए बिना एक मल्टीमैप बनाना चाहते हैं यह है: आप एक सूची संग्रहीत करना चाहते हैं एक विशेष विषय के लिए नामांकित छात्रों के। इस का उपयोग करते हुए JDK पुस्तकालय के लिए सामान्य समाधान

Map<String,List<String>> studentListSubjectWise = new TreeMap<>(); 
List<String>lis = studentListSubjectWise.get("a"); 
if(lis == null) { 
    lis = new ArrayList<>(); 
} 
lis.add("John"); 

//continue.... 

चूंकि यह कुछ बॉयलर प्लेट कोड है, लोगों को अमरूद Mutltimap का प्रयोग होता हैं।

Map.computeIfAbsent का उपयोग करके, हम निम्नानुसार अमरूद मल्टीमैप के बिना एक पंक्ति में लिख सकते हैं।

studentListSubjectWise.computeIfAbsent("a", (x -> new ArrayList<>())).add("John"); 

स्टुअर्ट मार्क्स & ब्रायन गोएज़ इस https://www.youtube.com/watch?v=9uTVXxJjuco

संबंधित मुद्दे