Search code examples
javalambda

How to "bake" value in lambda


Let's say I have code like this


@FunctionalInterface
interface Callable {
    Integer multiply(Integer by);
}

class Builder {
    private Integer multiplier;

    public Builder multiplyBy(Integer multiplier) {
        this.multiplier= multiplier;
        return this;
    }

    public Callable build() {
        return (value) -> value * multiplier; //how to "bake" hever value
    }
}

// calling

Builder builder;
Callable multiplierBy3 = builder.multiplyBy(3);
Callable multiplierBy6 = builder.multiply(6);

multiplierBy3.multiply(10); //should return 30, returns 60
multiplierBy6.multiply(10); // return 60, ok, propably because of new multipier value

Behavior happens because calling second time multiplyBy sets new value in builder. How I can manage to create each lambda own multiplier function?


Solution

  • Like @Kayaman said:

    Use two builders, that's where you're keeping the lambda state.

    So the solution will be this way:

    Builder builderBy3 = new Builder();
    Builder builderBy6 = new Builder();
    
    Callable multiplierBy3 = builderBy3.multiplyBy(3).build();
    Callable multiplierBy6 = builderBy6.multiplyBy(6).build();
    
    System.out.println(multiplierBy3.multiply(10)); // Returns 30
    System.out.println(multiplierBy6.multiply(10)); // Returns 60
    

    But you can also do it modifying the Builder:

    class Builder {
        private Integer multiplier;
    
        public Builder multiplyBy(Integer multiplier) {
            this.multiplier = multiplier;
            return this;
        }
    
        public Callable build() {
            int currentMultiplier = this.multiplier; // Current multiplier value
            return (value) -> value * currentMultiplier; // Use it in the lambda
        }
    }
    

    Then you can do:

    Builder builder = new Builder();
    
    Callable multiplierBy3 = builder.multiplyBy(3).build();
    Callable multiplierBy6 = builder.multiplyBy(6).build();
    
    System.out.println(multiplierBy3.multiply(10)); // Returns 30
    System.out.println(multiplierBy6.multiply(10)); // Returns 60