Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 - store lambdas in List

I wonder if it's possible to store lambdas in some container, for ex. ArrayList or HashMap. I want to change that code:

public enum OPCODE implements BinaryOperator<Integer> {
    MOV((x, y) -> y),
    INC((x, y) -> ++x),
    DEC((x, y) -> --x),
    ADD((x, y) -> x + y),
    SUB((x, y) -> x - y);

    private final BinaryOperator<Integer> binaryOperator;

    OPCODE(BinaryOperator<Integer> binaryOperator) {
        this.binaryOperator = binaryOperator;
    }  

    @Override
    public Integer apply(Integer integer, Integer integer2) {
        return binaryOperator.apply(integer, integer2);
    }
}

To something like:

List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>(){
    ((x, y) -> y),
    ((x, y) -> ++x)
};

etc.

and use it like so:

opcodes[0].apply(a, b);

It is even possible?

like image 723
Jump3r Avatar asked Oct 28 '17 08:10

Jump3r


4 Answers

You can certainly create such a list as:

List<BinaryOperator<Integer>> opcodes = Arrays.asList((x, y) -> y, (x, y) -> ++x);

// sample
int a=14,b=16;
System.out.println(opcodes.get(0).apply(a, b)); // prints 16
System.out.println(opcodes.get(1).apply(a, b)); // prints 15

Or redressing the way you were trying to initializing the list

List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>() {{
    add((x, y) -> y);
    add((x, y) -> ++x);
    add((x, y) -> --x);
    add((x, y) -> x + y);
    add((x, y) -> x - y);
}};
like image 66
Naman Avatar answered Sep 30 '22 12:09

Naman


In additional @nullpointer's great answer, you can also consider using a Map key to retain the original OPCODE intention of the functions, which would be lst in the array, e.g. using an Enum as a key:

public enum OPCODES {
    MOV, ADD, XOR
}

Which can be bootstrapped:

Map<OPCODES, BinaryOperator<Integer>> opcodeMap = 
  new EnumMap<OPCODES, BinaryOperator<Integer>>(OPCODES.class);
opcodeMap.put(OPCODES.ADD, (x, y)-> x + y);
opcodeMap.put(OPCODES.MOV, (x, y) -> y);
opcodeMap.put(OPCODES.XOR, (x, y) -> x ^ y);

And used:

System.out.println(opcodeMap.get(OPCODES.ADD).apply(1, 2));
System.out.println(opcodeMap.get(OPCODES.MOV).apply(1, 2));
System.out.println(opcodeMap.get(OPCODES.XOR).apply(1, 2));
like image 35
StuartLC Avatar answered Sep 30 '22 12:09

StuartLC


You could store lambdas inside a container, but the real question is why would you want to do that? Storing them in a List is easy, what about a Set/Map for example - you can't override equals/hashcode for lambdas - so you can't tell what would happen.

Since you already have an Enum there, why not use the simpler method:

Set<OPCODE> set = EnumSet.allOf(OPCODE.class);
like image 41
Eugene Avatar answered Sep 30 '22 12:09

Eugene


Hence you have defined your operator once you can do some thing like this:

List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>() {{
    add(OPCODE.ADD);
    add(OPCODE.DEC);
}};

to test that in your main method:

opcodes.forEach(elm -> System.out.println(elm.apply(1,2)));
like image 25
Maytham Avatar answered Sep 30 '22 12:09

Maytham