Zorunlu stili düzgün çalışırken java lambda ifadem neden çalışamıyor?

0

Soru

Java 8 ve lambda konusunda uzun yıllara dayanan tecrübem var. Ama dünya çapında bir Kıvılcım programı geliştirdiğimde çılgınca bir sorunla karşılaştım.

Burada, Veri ek açıklamasının Lombok'tan olduğu bir Java sınıfım var:

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

Ve sonra nesneleri içeren bir java listesi oluşturdum Persion sınıf:

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

iyi şimdilik. Ve sonra listeyi kullanarak bir Spark Veri Kümesi oluşturmaya çalıştım:

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

Blok 1'in java'daki blok 2'ye eşdeğer olduğuna ve blok 2'nin IntelliJ IDEA tarafından blok 1'den basitleştirildiğine dikkat edin. Tek fark, blok 2'nin lambda ifadesini kullanmasıdır.

Ancak, programı yürüttüğümde, blok 2 istisnada çalışırken blok 1 iyi bitiyor: enter image description here

Ne... büyük dünya ve büyük evren mi? JVM veya Spark motoru neden böyle şeyler yapıyor?!

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

En iyi cevabı

7

Sistem için eşdeğer lambda ifadesinin ne olduğu açıklandığı gibi.out:: println, yöntem başvurusu System.out::println lambda ifadesiyle aynı değildir x -> System.out.println(x).

Yöntem başvurusu geçerli değeri yakalar System.out, çağırmak println üzerinde, işlev her çağrıldığında, değerlendirmek yerine System.out yine her seferinde lambda ifadesinin vücudunun yaptığı gibi.

Ayrıca söylendiği gibi, bu nadiren bir fark yaratıyor, ama burada, öyle. İşlevi seri hale getirmeye çalıştığınızda, yakalanan tüm değerleri de dahil olmak üzere seri hale getirmeye çalışır. PrintStream okunan örnek System.out örnek oluşturma sırasında. Bu PrintStream serileştirilebilir değildir ve serileştirilebilir bir uygulama yapmak oldukça zor olacaktır PrintStream beklentilerin karşılanması.

Ancak, lambda ifadesini seri hale getirirken bunu aklınızda bulundurmanız önemlidir x -> System.out.println(x) veya eşdeğer bir sınıf nesnesi ve onu farklı bir ortamda serileştirmek, System.out orada okuyacak, farklı bir şekilde değerlendirecek PrintStream orijinal ortamınızdan daha fazla. Dağıtılmış bilgi işlem çerçevesinin, standart çıktıya yazdırılan her şeyi yaratıcıya geri aktarmaya özen göstermesi önemli değildir.

Ancak şunu akılda tutmak önemlidir: static seri hale getirilmiş verilerin bir parçası olmayan alanlar, genel olarak farklı ortamlarda farklı içeriklere sahip olabilir.

2021-11-24 08:36:53

Sadece şununla gerçekleşiyormuş gibi geliyor System.out?Ve onu Log framework ve bang ile değiştiriyorum! Başardı. ForeachFunction<String> functionBody = log::info;
Sheldon Wei

Günlük çerçevesine bağlıdır. Eğer işe yarayacak log seri hale getirilebilir.
Holger

Bu çerçeve ile ilgili değil gibi görünüyor. Kullanıyorum java.util.logging.Logger seri hale getirilemez.
Sheldon Wei

Standart kurulum için değil: ideone.com/F5lQZF " NotSerializableException: java.util.günlük.Kaydedici”. Ancak, belirli bir ortamda, bir günlük yöneticisi bir alt sınıfı döndürebilir Logger ayrıca, seri hale getirme (veya RMI) desteği ile çerçeve, kaydedicileri özel bir şekilde işleyebilen genişletilmiş bir seri hale getirme kullanabilir.
Holger
1

Arayüz foreachfonksiyonu genişletir Serializable. Dataset.foreach(f) argümanı seri hale getiriyor olabilir f. Aşağıdaki testte, testBlock1 başarılı ve testBlcok2 başarısız (NotSerializableException). Ama neden bilmiyorum.

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

Davalarınızı ve gerçekten de olayı test ettim. functionBody = t -> System.out.println(t) başarılı olacaktır. Bu yüzden problem kaynağı yöntem referansıdır. Bana kocaman bir el verdin.
Sheldon Wei

Eğer test sınıfı AAA uygulamaz Serializable kodumda, testBlock1 ayrıca başarısız olur. Bu functionBody içinde testBlock1 test sınıfının anonim bir iç sınıfıdır AAA ve sınıfın bir örneği ile seri hale getirilmelidir AAA bu onu içine alır. Ancak, functionBody içinde testBlock2 sınıfın bir iç sınıfı değil mi AAA ve uygulamak için görünmüyor Serializable madde.
英語は苦手

Diğer dillerde

Bu sayfa diğer dillerde

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