Je me demande s'il est possible de stocker des lambdas dans un conteneur, par exemple. ArrayList ou HashMap ..__ Je veux changer ce 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);
}
}
À quelque chose comme:
List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>(){
((x, y) -> y),
((x, y) -> ++x)
};
etc.
et l'utiliser comme ça:
opcodes[0].apply(a, b);
C'est même possible?
Vous pouvez certainement créer une liste telle que:
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
Ou redresser la façon dont vous avez essayé d'initialiser la liste
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);
}};
Dans l'excellente réponse de @ nullpointer supplémentaire, vous pouvez également envisager d'utiliser une clé Map
pour conserver l'intention OPCODE
d'origine des fonctions, qui serait lst dans le tableau, par exemple. en utilisant Enum
comme clé:
public enum OPCODES {
MOV, ADD, XOR
}
Qui peut être amorcé:
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);
Et utilisé:
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));
Vous pourriez stocker des lambdas dans un conteneur, mais la vraie question est pourquoi voudriez-vous faire cela? Il est facile de les stocker dans une List
. Qu'en est-il d'un Set/Map
par exemple? Vous ne pouvez pas remplacer equals/hashcode
pour lambdas? Vous ne pouvez donc pas savoir ce qui se produirait.
Puisque vous avez déjà une Enum
, pourquoi ne pas utiliser la méthode la plus simple:
Set<OPCODE> set = EnumSet.allOf(OPCODE.class);
Vous avez donc défini votre opérateur une fois que vous pouvez faire quelque chose comme ceci:
List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>() {{
add(OPCODE.ADD);
add(OPCODE.DEC);
}};
pour tester cela dans votre méthode principale:
opcodes.forEach(Elm -> System.out.println(Elm.apply(1,2)));
Oui, vous pouvez mettre des lambdas dans une liste ou les valeurs d’une carte sans problème. Rappelez-vous que les lambdas ne sont qu’un moyen sophistiqué d’écrire des classes anonymes, qui ne sont qu’un cas particulier de l’opérateur new
. En d'autres termes, operators.add((x, y) -> x + y)
est simplement un raccourci pour
final BinaryOperator<Integer> ADD = new BinaryOperator<Integer>() {
@Override
public Integer apply(final Integer x, final Integer y) {
return x + y;
}
};
operators.add(ADD);
Dans la même logique, operatorMap.put("add", (x, y) -> x + y);
ferait également exactement ce que vous attendez.
Cependant , le fait de placer les lambdas dans un ensemble - ce qui inclut leur utilisation en tant que clés de carte - risque de ne pas répondre à vos attentes. Généralement, le comportement d'un ensemble dépend de la définition de equals
et hashCode
par son type d'élément. Le langage ne donne aucune garantie pour ces méthodes au-delà de ce qui est requis par la définition de Object
. Par conséquent, l'assertion suivante peut échouer:
final Function<Object, String> func1 = Object::toString;
final Function<Object, String> func2 = Object::toString;
assert func1.equals(func2);
De même les suivantes:
final Function<Object, String> func = Object::toString;
final Set<Object> set = new HashSet<>();
set.add(func);
assert set.contains(Object::toString);
Veillez donc à placer les lambdas dans des conteneurs basés sur Set
, y compris leur utilisation en tant que clés Map
, mais ils peuvent être placés dans List
s et utilisés comme valeurs Map
.