我正在玩 Java 反射并学习更多关于 Stream.collect 的信息。
我有一个注释 MyTag,它有两个属性(id
和type
enum[Normal|Failure])。此外,我有一个带有 MyTag 的带注释的方法列表,我能够使用 Collectors.groupingBy 通过 MyTag 注释的 id 属性对这些方法进行分组:
List<Method> ml = getMethodsAnnotatedWith(anClass.getClass(),
MyTag.class);
Map<String, List<Method>> map = ml.stream().collect(groupingBy(m -> {
var ann = m.getDeclaredAnnotation(MyTag.class);
return ann.anId();
}, TreeMap::new, toList()));
Run Code Online (Sandbox Code Playgroud)
现在我需要将结果列表减少到一个对象,它只由两个相同 MyTag.id 的项目组成,一个带有 MyTag.type=Normal,另一个带有 MyTag.type=Failure。所以它会产生类似于 Map<String, Pair<Method, Method>> 的结果。如果出现两次以上,我必须只选择第一个,记录并忽略其余的。
我怎么能做到这一点?
您可以使用
Map<String, Map<Type, Method>> map = Arrays.stream(anClass.getClass().getMethods())
.filter(m -> m.isAnnotationPresent(MyTag.class))
.collect(groupingBy(m -> m.getDeclaredAnnotation(MyTag.class).anId(),
TreeMap::new,
toMap(m -> m.getDeclaredAnnotation(MyTag.class).aType(),
m -> m, (first, last) -> first,
() -> new EnumMap<>(Type.class))));
Run Code Online (Sandbox Code Playgroud)
结果将注释 ID 属性映射到Map
从Type
(枚举常量NORMAL
和FAILURE
)到具有匹配注释的第一个遇到的方法。虽然“first”在迭代反射发现的方法时没有实际意义,因为它不保证任何特定的顺序。
该() -> new EnumMap<>(Type.class)
地图工厂是没有必要的,它也将与默认情况下使用时,你不指定厂家通用地图工作。但是EnumMap
将以稍微更有效的方式处理只有两个常量要映射的情况,并且它的迭代顺序将匹配枚举常量的声明顺序。
我认为,这EnumMap
比Pair<Method, Method>
需要记住哪种方法与“正常”相关,哪种与“失败”相关联要好。适应两个以上的常量也更容易。此外,它EnumMap
是内置的,不需要第 3 方库。
归档时间: |
|
查看次数: |
116 次 |
最近记录: |