为什么我java lambda表达不能工作的同时,其必须风格的作品吗?

0

的问题

我拥有多年经验的Java8和lambda。 但我遇到一个疯狂的问题时,我制定了一个你好世界大小的火花的程序。

在这里我有一个Java类,其中的数据注释是从龙目:

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

然后我建立了一个java列表,其中包含的对象 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的简化从方框1IDEA. 唯一的区别是,框2是使用氧表达。

然而,当我执行的程序,方框1结束的同时,方框2中运行的情况例外: enter image description here

什么...大地球和大宇宙? 为什么JVM或火花引擎不会像这样的事情?!

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

最好的答案

7

解释 什么是相当于lambda表达系统。出::释放的方法,该方法参考 System.out::println 是不是完全相同的lambda表达 x -> System.out.println(x).

该方法参考 捕获 的当前值 System.out援引 println 在每次的功能是援引,而不是评估 System.out 再次,每次为lambda表达的尸体。

也正如所述,这个很少有差别,但是在这里,它不会。 当你尝试列化功能,它将尽量列化所有捕获的价值观,包括 PrintStream 实例,从中读取 System.out 在该实例。 的 PrintStream 不序列化和这将是很大的挑战,实现一个序列化 PrintStream 履行期望。

但重要的是要记住,当你serialize lambda表达 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 是序列化。
Holger

这似乎不涉及与框架。 我用 java.util.logging.Logger 这是不序列化。
Sheldon Wei

不用于标准的安装: ideone.com/F5lQZF "NotSerializableException:java。工具.记录。记录器". 然而,在一个特定的环境,日志管理可能返回的一个子类 Logger 与化(或马绍尔群岛共和国)支持,另外,该框架可以使用延长的序列,它可以处理记录在一个特殊的方式。
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 也会失败。 的 functionBodytestBlock1 是个匿名内部流的试验课 AAA 应化一类的实例 AAA 包围。 但是, functionBodytestBlock2 是不是一个内部类分类 AAA 似乎并没有实现 Serializable 在实质内容。
英語は苦手

其他语言

此页面有其他语言版本

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