ทำไมของฉันจาวา lambda สำนวนไม่สามารถทำงานในขณะที่ของมันหลีกเลี่ยงไม่ได้รูปแบบทำงานเหมาะสม?

0

คำถาม

ฉันต้องปีประสบการณ์ของจาวา 8 และมัน lambda. แต่ฉันเจอบ้านปัญหาตอนที่ฉันพัฒนาเป็นหวัดดี-โลกขนาดจุโปรแกรม

ตอนนี้ฉันมีงานจาวาองเรียนซึ่งข้อมูลหมายเหตุประกอบ annotation tool มาจาก 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 ประยุกต์@item text character set จากบล็อก 1 โดย IntelliJ รู้หรอก ความแตกต่างเพียงอย่างเดียวคือบล็อค 2 ใช้ lambda การแสดงออก

อย่างไรก็ตามเมื่อฉันประมวลผลโปรแกรมบล็อก 1 จบลงงั้นตอนบล็อค 2 อยู่ยกเว้น: enter image description here

อะไร?อ้าวว่าไงเพื่อนใหญ่บนโลกและใหญ่กจักรวาลใช่ไหม? ทำไม JVM ออลสปาร์คหรือเครื่องยนต์ทำแบบนี้?!

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

คำตอบที่ดีที่สุด

7

เหมือธิบายใน สิ่งที่เป็นมพล่ามคำเชยๆออกมาไม่หยุด lambda สำนวนสำหรับระบบออกไป::printlnที่วิธีการอ้างอิง System.out::println มันไม่เหมือนที่ lambda รแสดง x -> System.out.println(x).

จากวิธีการอ้างอิงถึง จับภาพ ปัจจุบันค่าของ System.outเพื่อเรียกร้อง println บนมันแต่ละครั้งฟังก์ชันเป็น invoked มากกว่าการประเมิน System.out อีกครั้งกันและเวลาที่ lambda สำนวนศพนะ

เป็นยังบอกว่านี่ไม่ค่อยจะทำให้ต่างกันแต่นี่มันเป็นอย่างนั้น ตอนที่คุณพยายามที่จะ serialize ฟังก์ชันมันจะพยายามที่จะ serialize ทุกจับตัวค่ารวมถึง PrintStream ตัวอย่างเช่นอ่านมาจาก System.out ระหว่าง instantiation. คน PrintStream ไม่ serializable และมันคงจะค่อนข้างท้าทายต้องเตรียมกำหนด serializable PrintStream การทำความคาดหมาย.

แต่มันสำคัญที่ต้องเก็บไว้ในใจนั่นตอนที่คุณ serialize ที่ lambda รแสดง x -> System.out.println(x) หรือเป็นมพล่ามคำเชยๆออกมาไม่หยุดเรียนวัตถุและ deserialize มันในมุมมองที่ต่างออกภาพแวดล้อมที่ System.out มันจะอ่านมันจะประเมินผลที่แตกต่าง PrintStream ว่าในของคุณดั้งเดิมสภาพแวดล้อม. มันไม่สำคัญหรอตรงๆจะถูกกระจายออกเป็น computing เฟรมเวิร์กต้องสนใจที่จะท่องทุกอย่างพิมพ์ต้องมาตรฐานส่งผลกลับไปที่ originator.

แต่มันสำคัญที่ต้องเก็บไว้ในใจนั่น static ช่องข้อมูลที่ไม่ใช่ส่วนหนึ่งของ serialized ข้อมูลอาจจะแตกต่างเนื้อหาของในต่างกันสภาพแวดล้อมทั่วไปก็ลำบากพอแล้ว

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 กับ serialization(หรือ RMI)สนับสนุนคำที่ส่วนเฟรมเวิร์กอาจต้องการกำลังเพิ่มเติม serialization ซึ่งสามารถจัดการ loggers ในพิเศษทาง
Holger
1

ส่วนติดต่อ ForeachFunction เพิ่มพูน Serializable. Dataset.foreach(f) อาจจะเป็น serializing แย้ง 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 และควรจะ serialized กับตัวอย่างของชั้น AAA นั่น encloses มัน ยังไงก็ตา functionBody ใน testBlock2 ไม่ใช่ในชั้นเรียนของชั้นเรียน AAA และดูเหมือนจะไม่ได้รับคำสั่งเข้าใจ Serializable อยู่ในสาร.
英語は苦手

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

ดังอยู่ในนี้หมวดหมู่

ดังคำถามอยู่ในนี้หมวดหมู่