Ich frage mich, ob es möglich ist, Lambdas beispielsweise in einem Container zu lagern. ArrayList oder HashMap. Ich möchte diesen Code ändern:
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);
}
}
Zu etwas wie:
List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>(){
((x, y) -> y),
((x, y) -> ++x)
};
usw.
und benutze es wie folgt:
opcodes[0].apply(a, b);
Es ist sogar möglich
Sie können sicherlich eine solche Liste erstellen als:
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
Oder die Art und Weise, wie Sie die Liste initialisieren wollten, korrigieren
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);
}};
In der großen Antwort von @ nullpointer können Sie auch die Verwendung einer Map
-Taste in Betracht ziehen, um die ursprüngliche OPCODE
-Intention der Funktionen beizubehalten, die sich als lst im Array befinden würde, z. mit einer Enum
als Schlüssel:
public enum OPCODES {
MOV, ADD, XOR
}
Welche können bootstrapped werden:
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);
Und verwendet:
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));
Sie könnten Lambdas in einem Behälter aufbewahren, aber die eigentliche Frage ist, warum sollten Sie das tun? Das Speichern in einem List
ist einfach. Wie wäre es beispielsweise mit einem Set/Map
- Sie können equals/hashcode
Für Lambdas nicht überschreiben - Sie können also nicht sagen, was passieren würde.
Da Sie dort bereits ein Enum
haben, können Sie die einfachere Methode verwenden:
Set<OPCODE> set = EnumSet.allOf(OPCODE.class);
Daher haben Sie Ihren Operator definiert, sobald Sie Folgendes tun können:
List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>() {{
add(OPCODE.ADD);
add(OPCODE.DEC);
}};
um das in deiner Hauptmethode zu testen:
opcodes.forEach(Elm -> System.out.println(Elm.apply(1,2)));
Ja, Sie können Lambdas in eine Liste oder in Werte einer Karte einfügen. Denken Sie daran, dass Lambdas nur eine ausgefallene Möglichkeit sind, anonyme Klassen zu schreiben, die wiederum nur ein Sonderfall des Operators new
sind. Anders ausgedrückt, operators.add((x, y) -> x + y)
ist nur eine Abkürzung für
final BinaryOperator<Integer> ADD = new BinaryOperator<Integer>() {
@Override
public Integer apply(final Integer x, final Integer y) {
return x + y;
}
};
operators.add(ADD);
Nach derselben Logik würde operatorMap.put("add", (x, y) -> x + y);
auch genau das tun, was Sie erwarten.
Allerdings das Einfügen von Lambdas in einen Satz - was die Verwendung als Landkartenschlüssel beinhaltet - macht möglicherweise nicht das, was Sie erwarten. Im Allgemeinen hängt das Verhalten einer Menge von der Definition von equals
und hashCode
nach ihrem Elementtyp ab, und die Sprache übernimmt keine Garantie für diese Methoden, die über das hinausgehen, was durch die Definition von Object
vorgeschrieben ist. Daher kann die folgende Zusicherung fehlschlagen:
final Function<Object, String> func1 = Object::toString;
final Function<Object, String> func2 = Object::toString;
assert func1.equals(func2);
Ebenso das Folgende:
final Function<Object, String> func = Object::toString;
final Set<Object> set = new HashSet<>();
set.add(func);
assert set.contains(Object::toString);
Seien Sie also vorsichtig, wenn Sie Lambdas in Set
-basierte Container setzen, einschließlich der Verwendung als Map
-Schlüssel. Sie können jedoch in List
s eingegeben und als Map
-Werte verwendet werden.