es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué mi expresión lambda de Java no puede funcionar mientras que su estilo imperativo funciona correctamente?

Tengo años de experiencia en Java 8 y sus lambdas. Sin embargo, me encontré con un problema insano cuando desarrollaba un programa Hello World utilizando Spark.

Aquí tengo una clase Java, en la cual la anotación Data viene de Lombok:
java
@Data
public class Person implements Serializable {
private String name;
private Long age;
}

Luego construí una lista Java que contenía objetos de la clase Person:
java
Person p1 = new Person("alguien", 1L);
Person p2 = new Person("otro alguien", null);
List<Person> list = new ArrayList<>(2);
list.add(p1);
list.add(p2);

hasta aquí todo bien. Luego intenté generar un conjunto de datos Spark a través de la lista:
java
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

Tenga en cuenta que el bloque 1 es equivalente al bloque 2 en Java y el bloque 2 está simplificado a partir del bloque 1 por IntelliJ IDEA. La única diferencia es que el bloque 2 está utilizando una expresión lambda.

Sin embargo, cuando ejecuto el programa, el bloque 1 termina bien, mientras que el bloque 2 se ejecuta con una excepción:
enter image description here

¿Qué demonios está pasando? ¿Por qué la JVM o el motor Spark hacen cosas como esta?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema aquí está relacionado con la manera en que se compilan las lambdas en Java. Cuando se utiliza una expresión lambda, el compilador genera una clase anónima para encapsular el cuerpo de la lambda. Esta clase anónima es lo que se pasa al motor de Spark para su ejecución. Sin embargo, en este caso, el método println en la expresión lambda requiere un tipo de retorno void, mientras que el método call en la clase anónima generada por el compilador tiene un tipo de retorno void. Esto crea una discrepancia entre los tipos de retorno esperados y reales, lo que resulta en la excepción.

    Para resolver este problema, puedes seguir usando el bucle foreach en el bloque 1, o modificar la expresión lambda en el bloque 2 para incluir una sentencia return:

    dataset1.foreach((ForeachFunction<person>) person -> {
        System.out.println(person);
        return;
    });
    

    Al incluir una sentencia return, estás especificando explícitamente el tipo de retorno void esperado por el método call en la clase anónima. Esto debería permitir que la expresión lambda se ejecute sin problemas.

Comments are closed.