如何创建一个 ArrayPredicate<A extends Object[]>?

How to create a ArrayPredicate<A extends Object[]>?

我不是要 create an array of a generic type (such as E[]). What I'm trying to do is create a predicate 分析(非原始)数组,例如

public class ArrayPredicate<A extends Object[]> implements Predicate<A> {    

   public boolean test(A a) {
      if(a == null) return false;
      if(a.length == 0) return false;
      for(Object o: a) {
         if(o == null) return false;
      } 
      return true;
   }    

   ...
}

但是Predicate<Object[]>明显是编译错误

更新:我需要将其扩展到 StringArrayPredicateIntegerArrayPredicate,等等,以验证每个元素的具体值。因此,class 本身必须被泛化。

如何为数组创建泛型谓词?

如果您想要 Predicate<Object[]>,则无需使实现 class 本身通用。

这样编译:

public class ArrayPredicate implements Predicate<Object[]> {    

    public boolean test(Object[] a) {
       if(a == null) return false;
       if(a.length == 0) return false;
       for(Object o: a) {
          if(o == null) return false;
       } 
       return true;
    }    
 }

如果您想要参数化您的class:

public class ArrayPredicate<T> implements Predicate<T[]> {
    public boolean test(T[] a) {
        return a != null && a.length > 0 && !Arrays.stream(a).filter(o -> o == null).findAny().isPresent();
    }
}

如果愿意,请注意方法主体的 java-8 重构。

目前还不是很清楚你到底想达到什么目的。我假设您想创建一些通用解决方案来以相同的方式验证所有数组元素,然后针对各种元素类型专门化它。

为了解决这个问题,我推荐以下内容。使 ArrayPredicate<T> 不是 class,而是扩展 Predicate<T[]> 的另一个接口,并提供验证数组元素的单个抽象方法。整个界面可能是这样的:

import java.util.Arrays;
import java.util.function.Predicate;

@FunctionalInterface
public interface ArrayPredicate<T> extends Predicate<T[]> {
    public boolean testElement(T t);

    default public boolean test(T[] a) {
        if (a == null || a.length == 0)
            return false;
        return Arrays.stream(a).allMatch(this::testElement);
    }
}

之后你可以像这样定义特定的谓词:

public class NonNullArrayPredicate implements ArrayPredicate<Object> {
    @Override
    public boolean testElement(Object obj) {
        return obj != null;
    }
}

public class NonEmptyStringArrayPredicate implements ArrayPredicate<String> {
    @Override
    public boolean testElement(String str) {
        return str != null && !str.isEmpty();
    }
}

等等。尽管 Java-8 方法可能是完全删除这些 classes 并使用 lambdas:

ArrayPredicate<Object> nonNullObjectArrayPredicate = Objects::nonNull;
ArrayPredicate<String> nonEmptyStringArrayPredicate = str -> str != null && str.isEmpty();

另一种更实用的解决方案是完全摆脱 ArrayPredicate 并创建单个高阶函数,而不是将元素谓词转换为数组谓词:

// In any suitable class
public static <T> Predicate<T[]> forArray(Predicate<T> elementPredicate) {
    return a -> a != null && a.length != 0 &&
                Arrays.stream(a).allMatch(elementPredicate);
    };
}

这样您就可以像这样创建特定的谓词:

Predicate<Object[]> nonNullObjectArrayPredicate = forArray(Objects::nonNull);
Predicate<String[]> nonEmptyStringArrayPredicate = forArray(
                                     str -> str != null && str.isEmpty());

因此您无需声明任何新的 classes,只需声明函数即可。