Aplicación de Operadores con Clases Genéricas en Java

Este ejemplo demuestra cómo aplicar una cadena de operadores a un dato almacenado dentro de una caja (clase Box). Los operadores se agregan a una lista en la clase Stream y se aplican de forma secuencial cuando se llama al método compute().


La clase Box es una clase genérica que almacena un único dato y provee el método stream() para iniciar la cadena de operaciones en dicho dato. Esto facilita el proceso de transformación al permitir que los usuarios inicien una secuencia de operaciones desde cualquier instancia de Box.


class Box<A> {
    A data;
    public Box(A data) {
        this.data = data;
    }
    public Stream<A> stream() {
        return new Stream<A>(data);
    }
}
        

La clase Stream define una estructura para almacenar una lista de operadores y aplicarlos en secuencia al dato proporcionado por la instancia de Box. Los métodos importantes son:

  • map(UnaryOperator<A> op): Agrega un operador a la lista de funciones. Cada operador en esta lista se aplicará secuencialmente al dato en el método compute().
  • compute(): Ejecuta cada operador en el orden en que fueron agregados y devuelve el resultado final.

class Stream<A> {
    ArrayList<UnaryOperator<A>> functions = new ArrayList<>();
    A data;
    public Stream(A data) {
        this.data = data;
    }
    
    public Stream<A> map(UnaryOperator<A> op) {
        functions.add(op);
        return this;
    }
    public A compute() {
        A a = this.data;
        for (UnaryOperator<A> operator : functions) {
            a = operator.apply(a);
        }
        return a;
    }
}
        

Clase Principal HelloWorld

En el método main de la clase HelloWorld, se crea una instancia de Box con un Double y se aplica una serie de operadores que modifican el valor. El método compute() devuelve el valor final después de aplicar todas las transformaciones.


public class HelloWorld {
    public static void main(String[] args) {
        Box<Double> box = new Box<>(5.0);
        Double z = box.stream()
                    .map(x -> 2 * x)
                    .map(x -> 2 * x + 2)
                    .map(x -> x + 1)
                    .map(x -> x)
                    .compute();
        System.out.println(z);
    }
}
        

La salida de este código es 43.0, resultado de aplicar las transformaciones en el siguiente orden:

  1. 2 * x: duplica el valor inicial 5.0, dando 10.0.
  2. 2 * x + 2: multiplica 10.0 por 2 y suma 2, obteniendo 22.0.
  3. x + 1: suma 1 a 22.0, resultando en 23.0.
  4. x: no cambia el valor final, que permanece en 43.0.