Prečo moje java lambda výraz nemôže pracovať, zatiaľ čo jeho imperatív štýl funguje správne?

0

Otázka

Mám ročné skúsenosti s Java 8 a jeho lambda. Ale stretol som šialený problém, keď som vyvinul hello-world-veľkosť Iskra program.

Tu som si Java triedy, v ktorých sa Údaje anotácia z Lombok:

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

A potom som sa postavil java zoznam obsahuje objekty Persion trieda:

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

tak dobre, tak ďaleko. A potom som sa snažil vytvoriť Iskra Dataset pomocou zoznamu:

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

Oznámenie, že bloku 1 je ekvivalentná blok 2 java a bloku 2 je zjednodušené z bloku 1 IntelliJ IDEA. Jediný rozdiel je v bloku 2 je pomocou lambda výraz.

Avšak, keď som sa spustite program, blok 1 končí dobre, zatiaľ čo blok 2 spustiť v výnimka: enter image description here

Čo... veľké zemi a veľký vesmír? Prečo JVM alebo Iskra motora robí veci, ako je tento?!

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

Najlepšiu odpoveď

7

Ako vysvetľuje , Čo je ekvivalent lambda výraz pre Systém.out::println, spôsob odkaz System.out::println nie je zhodná s lambda výraz x -> System.out.println(x).

Metóda odkaz zachytáva aktuálnu hodnotu System.outna vyvolanie println na to vždy, keď je funkcia volaná, skôr ako hodnotení System.out znovu zakaždým, ako lambda výraz je telo robí.

Ako tiež povedal, toto málokedy robí rozdiel, ale tu to nemá. Pri pokuse o serialize funkciu, bude sa snažiť, zoradenie všetky nasnímané hodnoty, vrátane PrintStream stupňa čítať z System.out počas procesmi.. Na PrintStream nie je serializable a to by bolo dosť náročné na realizáciu serializable PrintStream plní očakávania.

Ale je dôležité mať na pamäti, že ak ste serialize lambda výraz x -> System.out.println(x) alebo rovnocenný trieda objektu a deserialize to v inom prostredí, System.out to bude čítať bude hodnotiť na inú PrintStream ako v pôvodnom prostredí. To nevadí, keď distribuované výpočty rámec stará rúry všetko vytlačené na štandardný výstup späť na pôvodcu.

Ale je dôležité mať na pamäti, že static polia, ktoré nie sú súčasťou pokračovanie údajov môže mať iný obsah v rôznych prostrediach vo všeobecnosti.

2021-11-24 08:36:53

Znie ako by sa vyskytuje len s System.out?A ja som ho nahradiť Denník rámec a bang! To sa podarilo. ForeachFunction<String> functionBody = log::info;
Sheldon Wei

Záleží na zapisovanie rámec. Bude to fungovať, ak log je serializable.
Holger

Zdá sa nevzťahuje s rámcom. Používam java.util.logging.Logger čo nie je serializable.
Sheldon Wei

Nie je za štandardné nastavenie: ideone.com/F5lQZF "NotSerializableException: java.util.zapisovanie do denníka.Logger". Avšak, v konkrétnom prostredí, denník správca môže vrátiť podtriedy Logger s mód (alebo RMI) podporu, ďalej rámec by mohol použiť rozšírenú mód, ktorý zvládne záznamníky zvláštnym spôsobom.
Holger
1

Rozhranie ForeachFunction rozširuje Serializable. Dataset.foreach(f) môže byť serializing argument f. V nasledujúcom teste, testBlock1 uspeje a testBlcok2 nepodarí (NotSerializableException). Ale neviem, prečo.

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

Testoval som váš prípadoch a skutočne, akcie functionBody = t -> System.out.println(t) by byť úspešné. Takže problém zdroj myslím, že je metóda odkaz. Dali ste mi obrovskú ruku.
Sheldon Wei

Ak test triedy AAA mocnejšiu Serializable v mojom kóde, testBlock1 bude tiež zlyhať. Na functionBody v testBlock1 je anonymný vnútorné triedy skúšky trieda AAA a mali by byť na pokračovanie s inštanciou triedy AAA ktorý ohraničuje ho. Avšak, functionBody v testBlock2 nie je vnútorné triedy triedy AAA a nezdá sa realizovať Serializable v podstate.
英語は苦手

V iných jazykoch

Táto stránka je v iných jazykoch

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