क्यों मेरे जावा लैम्ब्डा अभिव्यक्ति काम नहीं कर सकता है, जबकि इसकी पहल शैली ठीक से काम करता है?

0

सवाल

मैं वर्षों के अनुभव के जावा 8 और अपने लैम्ब्डा. लेकिन मैं एक समस्या है जब मैं विकसित एक नमस्ते विश्व-आकार चिंगारी कार्यक्रम है ।

यहाँ मैं एक जावा वर्ग है, जो डेटा एनोटेशन से Lombok:

@Data
public class Person implements Serializable {
  private String name;
  private Long age;
}

और फिर मैं बनाया एक जावा सूची की वस्तुओं से युक्त Persion वर्ग:

        Person p1 = new Person("sb", 1L);
        Person p2 = new Person("sth", null);
        List<Person> list = new ArrayList<>(2);
        list.add(p1);
        list.add(p2);

तो अच्छा है अब तक । और फिर मैं करने की कोशिश की एक चिंगारी उत्पन्न डेटासेट का उपयोग कर सूची:

SparkSession session = SparkSession.builder().master("local[1]").appName("SparkSqlApp").getOrCreate();
Encoder<Person> personEncoder = Encoders.bean(Person.class);
Dataset<Person> dataset1 = session.createDataset(list, personEncoder);
dataset1.foreach(new ForeachFunction<Person>() { // 1
            @Override
            public void call(Person person) throws Exception {
                System.out.println(person);
            }
});
dataset1.foreach((ForeachFunction<Person>) System.out::println); //2

है कि नोटिस, ब्लॉक 1 करने के लिए बराबर है 2 ब्लॉक में जावा और ब्लॉक 2 सरल है से ब्लॉक 1 से IntelliJ विचार है. फर्क सिर्फ इतना है 2 ब्लॉक का उपयोग कर रहा है लैम्ब्डा अभिव्यक्ति है ।

हालांकि, जब मैं कार्यक्रम पर अमल, 1 ब्लॉक अच्छी तरह से समाप्त होता है, जबकि ब्लॉक 2 में चलाने के लिए अपवाद: enter image description here

क्या... बड़े पृथ्वी और ब्रह्मांड? क्यों जेवीएम या स्पार्क इंजन बातें करता है की तरह इस?!

apache-spark-sql java java-8 jvm
2021-11-24 03:11:05
2

सबसे अच्छा जवाब

7

के रूप में समझाया गया है क्या के बराबर लैम्ब्डा अभिव्यक्ति के लिए प्रणाली.बाहर::println, विधि संदर्भ System.out::println समान नहीं है करने के लिए लैम्ब्डा अभिव्यक्ति x -> System.out.println(x).

विधि संदर्भ कब्जा के वर्तमान मूल्य System.outआह्वान करने के लिए println पर यह हर बार के समारोह में लागू है, का मूल्यांकन करने के बजाय System.out फिर से हर बार के रूप में लैम्ब्डा अभिव्यक्ति के शरीर में करता है.

के रूप में यह भी कहा, यह शायद ही कभी एक फर्क पड़ता है, लेकिन यहाँ, यह करता है । जब आप serialize करने की कोशिश के समारोह में, यह कोशिश करेंगे serialize करने के लिए सभी पर कब्जा कर लिया मूल्यों सहित, PrintStream उदाहरण पढ़ने से System.out के दौरान प्रारंभ. के PrintStream नहीं है serializable और यह हो जाएगा काफी चुनौतीपूर्ण लागू करने के लिए एक serializable PrintStream को पूरा करने के लिए उम्मीदों ।

लेकिन यह महत्वपूर्ण है मन में रखने के लिए है कि जब आप serialize लैम्ब्डा अभिव्यक्ति x -> System.out.println(x) या समकक्ष वर्ग वस्तु और deserialize यह एक अलग वातावरण में, के System.out यह पढ़ा होगा, वहाँ होगा का मूल्यांकन करने के लिए एक अलग PrintStream की तुलना में अपने मूल वातावरण. यह कोई फर्क नहीं पड़ता जब वितरित अभिकलन ढांचे लेता है देखभाल करने के लिए पाइप सब कुछ करने के लिए मुद्रित मानक आउटपुट करने के लिए वापस प्रवर्तक.

लेकिन यह करने के लिए महत्वपूर्ण है कि मन में रखो static फ़ील्ड, जो का हिस्सा नहीं हैं श्रृंखलाबद्ध डेटा हो सकता है अलग अलग सामग्री अलग वातावरण में सामान्य रूप में.

2021-11-24 08:36:53

लगता है जैसे यह केवल तब होता है के साथ System.out?और मैं इसे बदलने के साथ लॉग ढांचे और चोदना! यह सफल रहा है । ForeachFunction<String> functionBody = log::info;
Sheldon Wei

पर निर्भर करता है, प्रवेश के ढांचे. अगर यह काम करेगा log है serializable.
Holger

यह लगता है कि नहीं करता है से संबंधित ढांचे के साथ. मैं का उपयोग करें java.util.logging.Logger जो नहीं है serializable.
Sheldon Wei

नहीं मानक के लिए सेटअप: ideone.com/F5lQZF "NotSerializableException: जावा.util.लॉगिंग.लकड़हारा". हालांकि, एक विशिष्ट वातावरण में, लॉग प्रबंधक वापस कर सकते हैं एक उपवर्ग के Logger के साथ क्रमबद्धता (या RMI) का समर्थन है, इसके अलावा, इस ढांचे का उपयोग कर सकता है एक विस्तारित क्रमबद्धता संभाल कर सकते हैं जो करने वालों में एक विशेष तरीका है ।
Holger
1

इंटरफ़ेस ForeachFunction फैली हुई है Serializable. Dataset.foreach(f) हो सकता है वेग अनुक्रम एनीमेशन तर्क f. निम्नलिखित में परीक्षण, testBlock1 सफल होता है और testBlcok2 विफल रहता है (NotSerializableException). लेकिन मैं क्यों नहीं पता है.

public class AAA implements Serializable {

    @FunctionalInterface
    public interface ForeachFunction<T> extends Serializable {
        void call(T t) throws Exception;
    }

    @Test
    public void testBlock1() throws FileNotFoundException, IOException {
        ForeachFunction<String> functionBody = new ForeachFunction<String>() {
            public void call(String t) throws Exception {
                System.out.println(t);
            }
        };
        try (FileOutputStream fos = new FileOutputStream("data/block1.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(functionBody);  // success
        }
    }

    @Test
    public void testBlock2() throws FileNotFoundException, IOException {
        ForeachFunction<String> functionBody = System.out::println;
        try (FileOutputStream fos = new FileOutputStream("data/block2.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(functionBody);  // fail (NotSerializableException)
        }
    }
}
2021-11-24 06:44:55

मैं परीक्षण में अपने मामलों और वास्तव में, घटना functionBody = t -> System.out.println(t) सफल होगा. इसलिए इस समस्या का स्रोत मुझे लगता है विधि संदर्भ. आप मुझे एक बहुत बड़ा हाथ है ।
Sheldon Wei

यदि परीक्षण वर्ग AAA लागू नहीं करता है Serializable मेरे कोड में, testBlock1 भी विफल रहेगा. के functionBody में testBlock1 एक गुमनाम अंदरूनी वर्ग के वर्ग परीक्षण AAA और किया जाना चाहिए धारावाहिक के साथ वर्ग का एक उदाहरण AAA कि encloses । हालांकि, functionBody में testBlock2 नहीं है एक आंतरिक वर्ग के वर्ग AAA और प्रतीत नहीं होता है को लागू करने के लिए Serializable पदार्थ में.
英語は苦手

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में