GhostCat敬礼モニカC.:
私の要件は:私だけのようなエントリを含まなければならないインタフェースを持っていますpublic final static short SOME_CONST = whatever
。キャッチ:短い定数である必要がユニーク。そして、重複がある場合には、私は主に競合の原因SOME_CONST_A、SOME_CONST_B、...名前を持つに興味があります。
私は反射を介してテストをすることを、以下のテストを書きました。それは動作しますが、私はそれが不格好ではなく非常にエレガント見つけます:
@Test
public void testIdsAreUnique() {
Map<Short, List<String>> fieldNamesById = new LinkedHashMap<>();
Arrays.stream(InterfaceWithIds.class.getDeclaredFields())
.filter(f -> f.getClass().equals(Short.class))
.forEach((f) -> {
Short key = null;
String name = null;
try {
key = f.getShort(null);
name = f.getName();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
fieldNamesById.computeIfAbsent(key, x -> new ArrayList<>()).add(name);
});
assertThat(fieldNamesById.entrySet().stream().filter(e -> e.getValue().size() > 1)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)), is(Collections.emptyMap()));
}
その中間のローカルマップのインスタンスを回避する方法はありますか?
(ボーナス質問:キー/値ペアでマップを埋めラムダを短くするよりよい方法はありますか?)
ernest_k:
ここでは、静的な値でフィールドをグループ化していますストリームです。その他の変更/修正に関するいくつかのコメントに注意してください。
Map<Short, List<String>> fieldNamesById =
Arrays.stream(InterfaceWithIds.class.getDeclaredFields())
//using short.class, not Short.class
.filter(f -> f.getType().equals(short.class))
//group by value, mapping fields to their names in a list
.collect(Collectors.groupingBy(f -> getValue(f),
Collectors.mapping(Field::getName, Collectors.toList())));
値を読み取るために呼び出されるメソッドは、(主にストリームに避けるのtry / catchブロックに意味)以下であります:
private static Short getValue(Field f) {
try {
return f.getShort(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}