首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >然后筛选器从流和其他Java 8 hiccups映射实例

然后筛选器从流和其他Java 8 hiccups映射实例
EN

Code Review用户
提问于 2015-08-03 22:52:43
回答 1查看 3K关注 0票数 3

我很难把这个方法改写成更易读、更容易理解的东西。

代码语言:javascript
复制
static Stream<Class<? extends MyType>> collectMyTypes(Object o) {
  return Reflection.lineage(o.getClass())
      .flatMap(c -> Arrays.stream(c.getDeclaredFields()))
      .map(Field::getGenericType)
      .filter(t -> t instanceof ParameterizedType)
      .map(t -> (ParameterizedType) t)
      .filter(t -> t.getRawType() == MyTypeWrapper.class)
      .map(t -> t.getActualTypeArguments()[0]) //MyTypeWrapper is final and has only 1 type argument.
      .filter(t -> t instanceof Class)
      .map(t -> (Class<? extends MyType>) t);
}

下面是我使用的工具/类:

  • Reflection.lineage(Class<T>)遍历T的所有父类;
  • MyTypeWrapper定义为final class MyTypeWrapper<T extends MyType>
  • MyType被定义为abstract class MyType

这段代码让我感到烦恼的是,它很难读懂,主要是因为在实例上有一系列的过滤器,然后映射。我试图在Java 8中找到类似于番石榴的Iterables.filter(Iterable,Class)的东西,但是还没有找到任何类似的方法(虽然我实现了类似的方法,但是代码看起来像Lisp)。另外,打给Arrays.stream的电话也让我感到不安。是的,我可以把它分成.map(Class::getDeclaredFields).flatten(Arrays::stream),但是这会增加一些不必要的复杂性,不是吗?

无论如何,任何意见都是欢迎的。

给定下面的示例,此方法将保留/跳过各种字段。

代码语言:javascript
复制
class GoodExample extends MyType {}
class BadExample extends MyType {}
class Example {

  // GoodExample will be returned.
  MyTypeWrapper<GoodExample> object1; 

  // BadExample will be skipped because the type is a wildcard
  MyTypeWrapper<? extends BadExample> object2;

  // There is no type to return so this field is skipped.
  MyTypeWrapper object3;

  // This is not an instance of MyTypeWrapper so it's skipped.
  Object object4;

  // This is generic, but still not a MyTypeWrapper, so it's skipped.
  List<BadExample> object5;
}

编辑:

最初的方法是:

代码语言:javascript
复制
  List<Class<? extends MyType>> types = new ArrayList<>();
  Reflection.lineage(o.getClass())
      .forEach((c) -> {
        for (Field f: c.getDeclaredFields()) {
          Type type = f.getGenericType();
          if (!(type instanceof ParameterizedType)) {
            continue;
          }
          ParameterizedType pType = (ParameterizedType)type;
          if (pType.getRawType() != MyTypeWrapper.class) {
            continue;
          }
          // length is 1.
          Type argType = pType.getActualTypeArguments()[0];
          if (!(argType instanceof Class)) {
            continue;
          }
          Class<? extends MyType> argClass = (Class<? extends MyType>)argType;
          types.add(argClass);
        }
      });
return types;
EN

回答 1

Code Review用户

回答已采纳

发布于 2015-08-04 01:14:12

我可以建议的是将后续的filter()/map()步骤放入某种提取方法中:

代码语言:javascript
复制
@SuppressWarnings("rawtypes")
private static Optional<Type> extractMyType(Field field) {
    return Optional.of(field.getGenericType())...;
}

您还可以将filter()/map()步骤作为一个方法:

代码语言:javascript
复制
private static <T, R> Optional<R> filterAndMap(T obj, Predicate<? super T> filter,
        Function<? super T, ? extends R> mapper) {
    return Optional.of(obj).filter(filter).map(mapper);
}

为了方便起见,您可以创建一个cast()方法,该方法调用filterAndMap()来处理安全转换:

代码语言:javascript
复制
private static <T, R> Optional<R> cast(T obj, Class<R> clazz) {
    return filterAndMap(obj, clazz::isInstance, v -> (R) obj);
}

然后,extractMyType()的核心实际上变成了三个flatMap()操作:

代码语言:javascript
复制
@SuppressWarnings("rawtypes")
private static Optional<Class> extractMyType(Field field) {
    return Optional.of(field.getGenericType())
            .flatMap(v -> cast(v, ParameterizedType.class))
            .flatMap(v -> filterAndMap(v,
                            v1 -> v1.getRawType() == MyTypeWrapper.class,
                            v1 -> v1.getActualTypeArguments()[0]))
            .flatMap(v -> cast(v, Class.class));
}

最后,collectMyTypes()方法只对结果的Optional包装器实例执行一个简单的筛选:

代码语言:javascript
复制
@SuppressWarnings("unchecked")
static Stream<Class<? extends MyType>> collectMyTypes(Object o) {
    return Reflection.lineage(o.getClass())
            .flatMap(c -> Arrays.stream(c.getDeclaredFields()))
            .map(YourClass::extractMyType).filter(Optional::isPresent)
            .map(Optional::get);
}
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/98952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档