たとえば、ラムダをいくつかのコンテナに格納することは可能かどうか疑問に思います。 ArrayListまたはHashMap。そのコードを変更したい:
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);
}
}
次のようなものに:
List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>(){
((x, y) -> y),
((x, y) -> ++x)
};
等.
そしてそれをそのように使用します:
opcodes[0].apply(a, b);
それも可能ですか?
あなたは確かに次のようなリストを作成することができます:
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
または、リストを初期化しようとしていた方法を修正します
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);
}};
追加の@nullpointerのすばらしい答えでは、Map
キーを使用して、関数の元のOPCODE
意図を保持することも検討できます。これは、配列の最初になります。キーとしてEnum
を使用する:
public enum OPCODES {
MOV, ADD, XOR
}
ブートストラップできるもの:
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);
そして使用される:
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));
あなたcouldラムダをコンテナ内に保存しますが、本当の問題はなぜそれをしたいのかということです。それらをList
に格納するのは簡単です。たとえば、Set/Map
はどうでしょうか。ラムダの場合はequals/hashcode
をオーバーライドできないため、何が起こるかわかりません。
すでにEnum
があるので、もっと簡単な方法を使ってみませんか。
Set<OPCODE> set = EnumSet.allOf(OPCODE.class);
したがって、次のようなことができるようになったら、演算子を定義しました。
List<BinaryOperator<Integer>> opcodes = new ArrayList<BinaryOperator<Integer>>() {{
add(OPCODE.ADD);
add(OPCODE.DEC);
}};
あなたのメインメソッドでそれをテストするには:
opcodes.forEach(Elm -> System.out.println(Elm.apply(1,2)));
はい、マップのリストまたは値にラムダをうまく配置できます。ラムダは匿名クラスを作成するための優れた方法であり、これはnew
演算子の特殊なケースにすぎないことを忘れないでください。言い換えれば、operators.add((x, y) -> x + y)
は単なる省略形です
_final BinaryOperator<Integer> ADD = new BinaryOperator<Integer>() {
@Override
public Integer apply(final Integer x, final Integer y) {
return x + y;
}
};
operators.add(ADD);
_
同じロジックで、operatorMap.put("add", (x, y) -> x + y);
も期待どおりの動作をします。
ただし、ラムダをセットに入れると(マップキーとして使用することも含まれます)、期待どおりに動作しない可能性があります。一般に、セットの動作は、要素タイプによるequals
およびhashCode
の定義に依存し、言語は、Object
の定義で義務付けられている以上のメソッドを保証しません。したがって、次のアサートは失敗する可能性があります:
_final Function<Object, String> func1 = Object::toString;
final Function<Object, String> func2 = Object::toString;
assert func1.equals(func2);
_
同様に次のとおりです。
_final Function<Object, String> func = Object::toString;
final Set<Object> set = new HashSet<>();
set.add(func);
assert set.contains(Object::toString);
_
したがって、ラムダをSet
ベースのコンテナに入れる場合は注意が必要です。これには、Map
キーとしての使用も含まれますが、List
sに入れて、Map
値として使用することもできます。