2

I would like to do a similar approach above in Java 8. I'm pythonist, here an example of what I need to do, but in Python.

def function1(x):
    return x * 1

def function2(x):
    return x * 2

def function3(x):
    return x * 3

status = {"BOOK": function1,
          "ISSUING": function2,
          "RETRYING": function3}

for k, v in status.items():
    print("status {0} call function {1}, \
     result: {2}".format(k, v, v(2)))

How have the same effect or approach in Java 8? Please?

After @Guilheme help me above [SOLVED], I got this similar approach:

import java.util.HashMap;
import java.util.Map;

public class ExampleCallDifferentFunction {

    public static int multiply1(int x) {
        return x * 1;
    }

    public static int multiply2(int x) {
        return x * 2;
    }

    public static int multiply3(int x) {
        return x * 3;
    }

    interface Function {
        int function(int x);
    }

    private static Map<String, Function> createMap() {
        Map<String,Function> myMap = new HashMap<String,Function>();
        myMap.put("BOOK", (x) -> multiply1(x));
        myMap.put("ISSUING", (x) -> multiply2(x));
        myMap.put("RETRYING",(x) -> multiply3(x));
        return myMap;
    }

    public static void main(String[] args) {

        Map<String, Function> status = createMap();
        int x = 2;

        for (Map.Entry<String, Function> entry : status.entrySet()) {
            Function f = entry.getValue();
            System.out.printf("status %s call %s result: %d\n", entry.getKey(), entry.getValue(), f.function(2));
        }
    }
}
duplode
  • 33,731
  • 7
  • 79
  • 150
Andre Araujo
  • 2,348
  • 2
  • 27
  • 41

2 Answers2

2

While you could use a map, it feels like an enum would be a more natural solution:

enum Status {
    BOOK(x -> x * 1),
    ISSUING(x -> x * 2),
    RETRYING(x -> x * 3);

    private final IntUnaryOperator operator;

    private Status(IntUnaryOperator operator) {
        this.operator = operator;
    }

    public int apply(int argument) {
        return operator.apply(argument);
    }
}

Then you can use valueOf to convert from String (this example uses Optional to catch the illegal value case):

Optional.ofNullable(Status.valueOf(status)).orElseThrow().apply(argument);

Or if you want to apply each value:

for (Status status: Status.values()) {
    System.out.println(status + ":" + status.apply(2));
}

In general, if you know the set of objects at compile time then consider an enum. It is clear documentation for the reader of your code that this is a fixed list that won't change at runtime.

As a matter of interest, in the openjdk implementation of Java valueOf actually uses a map from String to the constant internally so this is no less efficient.

sprinter
  • 27,148
  • 6
  • 47
  • 78
  • Thanks, but it's just an example of a method, my real (production) problem I have more complicated methods with ~4 parameters with the same signature but doing different things. So, I will not be using operators, because that @guilherme is a better approach in my specif case. – Andre Araujo Nov 20 '19 at 03:58
  • 1
    @AndreAraujo My use of operators was also just an example. It would work just as well with any interface. The important question is not the signature of the method but whether you have a fixed or variable number of implementations of the method. – sprinter Nov 20 '19 at 04:21
  • Ok, but supposing that the method arguments are not integers or strings, but objects or list of objects, your approach is more dependent of my example, but is real good too! Just that! Thanks. – Andre Araujo Nov 20 '19 at 04:26
  • @AndreAraujo really this approach is not at all dependent on the details - it will work just as well with any arguments including objects or lists of objects. – sprinter Nov 20 '19 at 21:15
1

here is the code:

import java.util.HashMap;
import java.util.Map;

public class Main {

    interface Function {
        int function(int x);
    }

    public static void main(String[] args) {

        Map<String, Function> status = new HashMap<>();

        status.put("BOOK", (x) -> x);
        status.put("ISSUING", (x) -> x * 2);
        status.put("RETRYING", (x) -> x * 3);

        for (Map.Entry<String, Function> entry : status.entrySet()) {
            Function f = entry.getValue();
            System.out.printf("status %s call %s result: %d\n", entry.getKey(), entry.getValue(), f.function(2));
        }

    }
}
Guilherme
  • 456
  • 4
  • 12