我正在玩 Java 反射并学习更多关于 Stream.collect 的信息。
我有一个注释 MyTag,它有两个属性(id和typeenum[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 次  |  
        
|   最近记录:  |