मेरे पास एक Map<String, Integer> है, जिसमें कुछ कुंजियां और मान हैं। मैं सभी कुंजियों को मानों के साथ कुंजी की लंबाई के रूप में जोड़ना चाहता हूं। मैं इसे शुद्ध जावा और जावा -8 में हल करने में सक्षम हूं, लेकिन किसी भी तरह से मुझे नहीं लगता कि अंत में एक टर्मिनल ऑपरेशन जोड़ना .collect(Collectors.toList()); जो मेरे कोड में मेरे लिए आवश्यक नहीं है।

मेरा कोड: (जावा) ठीक काम करता है

 Map<String, Integer> nameLength = new HashMap<>();
   nameLength.put("John", null);
    nameLength.put("Antony", 6);
    nameLength.put("Yassir", 6);
    nameLength.put("Karein", 6);
    nameLength.put("Smith", null);
    nameLength.put("JackeyLent",null);
    for(Entry<String, Integer> length: nameLength.entrySet()){
      if(length.getValue() == null){
        nameLength.put(length.getKey(),length.getKey().length());
      }
    }

Java-8 भी ठीक काम करता है लेकिन टर्मिनल ऑपरेशन बेकार है, मैं .foreach() का उपयोग किए बिना इससे कैसे बचता हूं।

nameLength.entrySet().stream().map(s->{
  if(s.getValue() == null){
    nameLength.put(s.getKey(),s.getKey().length());
  }
  return nameLength;
}).collect(Collectors.toList());
System.out.println(nameLength);

जावा -8 और इसके बाद के संस्करण में मैं उपरोक्त तर्क को किसी अन्य तरीके से कर सकता हूं ??

3
Atta Boy 23 अप्रैल 2020, 16:29
आप ये कृत्रिम प्रतिबंध क्यों लगा रहे हैं: बयानों के लिए नहीं, नहीं forEach?
 – 
Sotirios Delimanolis
23 अप्रैल 2020, 16:31
1
यह XY समस्या की तरह लगता है - meta.stackexchange. com/questions/66377/what-is-the-xy-problem. आप क्या हासिल करने का प्रयास कर रहे हैं?
 – 
Ben R.
23 अप्रैल 2020, 16:31
1
कृपया अपने वास्तविक मुद्दे को दर्शाने के लिए अपना शीर्षक संपादित करें। Java-8 में रिफैक्टरिंग हमें कुछ नहीं बताता।
 – 
Sotirios Delimanolis
23 अप्रैल 2020, 16:34
यह जो कुछ भी कर रहा है, वह रिफैक्टरिंग नहीं कर रहा है। यदि आप बेतरतीब ढंग से अपने कोड में लैम्ब्डा डालते हैं तो आपको कुछ भी हासिल नहीं होता है, इस विशेष मामले में पूरी तरह से ठीक और काम करने वाले foreach लूप को धाराओं और लैम्ब्डा के आर्केन निर्माणों के साथ बदलने का कोई कारण नहीं है जो मूल कोड को मुश्किल से करते हैं।
 – 
M. Prokhorov
23 अप्रैल 2020, 16:52
यह map.. परिवर्तनशील ऑपरेशन के लिए भयानक उपयोग है, जो कुछ भी दिलचस्प नहीं लौटाता है
 – 
Coderino Javarino
23 अप्रैल 2020, 16:59

3 जवाब

यदि आप धाराओं का उपयोग करने जा रहे हैं तो आपको दुष्प्रभावों से बचना चाहिए। कार्यात्मक प्रोग्रामिंग सभी शुद्ध संचालन के बारे में है जहां आउटपुट केवल इनपुट पर निर्भर करता है और फ़ंक्शन का कोई दुष्प्रभाव नहीं होता है। दूसरे शब्दों में, मौजूदा मानचित्र को संशोधित करने के बजाय एक नया मानचित्र बनाएँ।

यदि आप ऐसा करते हैं तो आप आंशिक रूप से भरे हुए नक्शे को भी फेंक सकते हैं और खरोंच से सब कुछ फिर से गणना कर सकते हैं। String.length() को कॉल करना सस्ता है और यह पता लगाने के प्रयास के लायक नहीं है कि कौन से मान शून्य हैं और कौन से नहीं हैं। सभी लंबाई की पुनर्गणना करें।

Map<String, Integer> newMap = nameLength.keySet().stream()
    .collect(Collectors.toMap(
        name -> name,
        name -> name.length()
    ));

दूसरी ओर, यदि आप अपने वर्तमान मानचित्र धाराओं को ठीक करना चाहते हैं तो वास्तव में आपको कुछ भी नहीं खरीदना चाहिए। मैं धाराओं को शामिल किए बिना इसे बस जगह में संशोधित कर दूंगा।

for (Map.Entry<String, Integer> entry: nameLength.entrySet()) {
  if (entry.getValue() == null) {
    entry.setValue(entry.getKey().length());
  }
}

या, जैसा कि ऊपर चर्चा की गई है, आप सभी लंबाई को बदलकर मामलों को सरल बना सकते हैं:

nameLength.replaceAll((name, __) -> name.length());

(__ एक ऐसे वैरिएबल को दर्शाता है जिसका उपयोग नहीं किया जाता है और इसलिए कोई सार्थक नाम नहीं मिलता।)

4
John Kugelman 23 अप्रैल 2020, 17:08
@ एम.प्रोखोरोव मेरा उत्तर उसे संबोधित करता है। टुकड़ों में करने की तुलना में सब कुछ पुनर्गणना करना आसान है, इसलिए पहला और आखिरी स्निपेट यही करता है। बीच वाला केवल null मानों को प्रतिस्थापित करता है और परिणामस्वरूप सबसे खराब कोड होता है।
 – 
John Kugelman
23 अप्रैल 2020, 16:57

आप लगभग वहां हैं, बस फ़िल्टर करें और फिर कलेक्टर.toMap उन्हें कुंजी के साथ Map में एकत्रित करने के लिए मूल्य के रूप में लंबाई

Map<String, Integer> nameLengths = nameLength.entrySet()
                 .stream()
                 .filter(entry->entry.getValue()==null)
                 .collect(Collectors.toMap(Map.Entry::getKey, entry->entry.getKey().length()));

या इससे भी आसान तरीका है कि आप Collectors.toMap में चेक इन करें

  Map<String, Integer> nameLengths = nameLength.entrySet()
                 .stream()
                 .collect(Collectors.toMap(Map.Entry::getKey, entry->entry.getValue() == null ? entry.getKey().length() : entry.getValue()));
1
Deadpool 23 अप्रैल 2020, 16:49
1
सभी उत्तरों में से मुझे लगता है कि आप सबसे निकट हैं: nameLength.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue() != null ? entry.getValue() : entry.getKey().length()));
 – 
Olivier Grégoire
23 अप्रैल 2020, 16:45
ओएमजी, डाउनवोट्स के लिए भगवान का शुक्र है, समझाने का कोई मौका क्यों?
 – 
Deadpool
25 अप्रैल 2020, 01:16

तुम कर सकते हो:

nameLength.keySet().forEach(key -> nameLength.computeIfAbsent(key, String::length));
-2
Hadi J 23 अप्रैल 2020, 16:56
पुरज़ोर अनुशंसा करते हैं कि आप दस्तावेज़ को सटीक रूप से पढ़ें! docs.oracle.com/javase/8/docs/api/java/util/…
 – 
Hadi J
23 अप्रैल 2020, 16:45
1
बस अपने s -> nameLength.put(s, s.length()) को s -> s.length() से बदल दें; आपका संस्करण कुछ नहीं करता है। यह जावाडोक के बारे में नहीं है। यह सही कोड के बारे में है, और उस अतिरिक्त गणना को करने से मानचित्र के इतने सारे कार्यान्वयन में विफल होने का खतरा है। आप भाग्यशाली हैं कि यह यहां सफल होता है।
 – 
Olivier Grégoire
23 अप्रैल 2020, 16:53