有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于筛选给定集合元素的java增量条件

我想知道一种可伸缩的通用方法,可以将增量filters应用于给定的集合,而不会丢失失败的原因,我的意思是,哪个过滤器不匹配

以下代码是对现有代码的简化(它有更多的条件和错误消息):

public class FailureCause {

  public static void main(String[] args) {
    validateAtRawWay(asList(201, 300, 450));
    validateAtRawWay(asList(20, 30, 40));
    validateAtRawWay(asList(400, 1600));
    validateAtRawWay(asList(10, 25, 36, 201, 1600));
  }

  public static void validateAtRawWay(List<Integer> sourceToCheck) {
    System.out.println("Initial elements: " + sourceToCheck);

    if (!sourceToCheck.stream()
            .filter(FailureCause.upTo100())
            .findAny()
            .isPresent()) {
        System.out.println("ERROR: no numbers less or equals than 100 were found");
        return;
    }
    if (!sourceToCheck.stream()
            .filter(FailureCause.isPerfectSquare())
            .findAny()
            .isPresent()) {
        System.out.println("ERROR: no perfect square numbers were found");
        return;
    }
    List<Integer> validResults = sourceToCheck.stream()
            .filter(FailureCause.upTo100())
            .filter(FailureCause.isPerfectSquare())
            .collect(toList());
    System.out.println("Valid data: " + validResults);
  }

  public static Predicate<Integer> upTo100() {
    return i -> i <= 100;
  }

  public static Predicate<Integer> isPerfectSquare() {
    return i -> {
        double sq = Math.sqrt(i);
        return (sq - Math.floor(sq)) == 0;
    };
  }
}

然而,使用这种方法,集合必须迭代数次,以了解错误,并最终获得验证所有条件的合适元素

作为上述方法的替代方法我开发了以下类来存储:过滤器、其重要性顺序、错误消息以及是否有验证它的元素

public class ConditionToMatch<E> implements Comparable<ConditionToMatch> {

  // To omit getter/setter
  public int order;
  public Predicate<E> condition;
  public boolean wasFound;
  public String errorMessage;

  public ConditionToMatch (int order, Predicate<E> condition, boolean wasFound, String errorMessage) {
    this.order = order;
    this.condition = condition;
    this.wasFound = wasFound;
    this.errorMessage = errorMessage;
  }

  @Override
  public int compareTo(ConditionToMatch o) {
    return ofNullable(o)
            .map(ext -> Integer.compare(order, ext.order))
            .orElse(-1);
  }
} 

将此用例添加到上一个FailureCause类:

public class FailureCause {

  public static void main(String[] args) {
    ...

    validateWithConditionClass(asList(201, 300, 450));
    validateWithConditionClass(asList(20, 30, 40));
    validateWithConditionClass(asList(400, 1600));
    validateWithConditionClass(asList(10, 25, 36, 201, 1600));
  }
  ...

  public static void validateWithConditionClass(List<Integer> sourceToCheck) {
    System.out.println("Initial elements: " + sourceToCheck);

    ConditionToMatch<Integer> isUpTo100Condition = isUpTo100ConditionToMatch();
    ConditionToMatch<Integer> isPerfectSquareCondition = isPerfectSquareConditionToMatch();

    // Used to get the "most important" filter has failed
    PriorityQueue<ConditionToMatch> priorizeValidations = new PriorityQueue<>(asList(isUpTo100Condition, isPerfectSquareCondition));

    List<Integer> validResults = sourceToCheck.stream()
            .map(s -> {
                if (isUpTo100Condition.condition.test(s)) {
                    isUpTo100Condition.wasFound = true;
                }
                if (isPerfectSquareCondition.condition.test(s)) {
                    isPerfectSquareCondition.wasFound = true;
                }
                return s;
            })
            .filter(isUpTo100Condition.condition)
            .filter(isPerfectSquareCondition.condition)
            .collect(toList());

    if (validResults.isEmpty()) {
        Iterator<ConditionToMatch> value = priorizeValidations.iterator();
        // To know the first "most important" filter that failed
        while (value.hasNext()) {
            ConditionToMatch current = value.next();
            if (!current.wasFound) {
                System.out.println(current.errorMessage);
                break;
            }
        }
    }
    else {
        System.out.println("Valid data: " + validResults);
    }
  }
  ...  

  public static ConditionToMatch<Integer> isUpTo100ConditionToMatch() {
    return new ConditionToMatch<>(1, FailureCause.upTo100(), false, "ERROR: no numbers less or equals than 100 were found");
  }

  public static ConditionToMatch<Integer> isPerfectSquareConditionToMatch() {
    return new ConditionToMatch<>(2, FailureCause.isPerfectSquare(), false, "ERROR: no perfect square numbers were found");
  }
}

我的问题是:有没有更好的、可扩展的方法


共 (2) 个答案

  1. # 1 楼答案

    我会调整你的第一种方法,避免那里的溪流

    import static java.util.function.Predicate.not;
    ...
    
    public static void validateAtRawWay(List<Integer> sourceToCheck) {
        List<Integer> copy = new ArrayList<>(sourceToCheck);
        System.out.println("Initial elements: " + copy);
        
        copy.removeIf(not(upTo100()));
        if (copy.isEmpty()) {
            System.out.println("ERROR: no numbers less or equals than 100 were found");
            return;
        }
        
        copy.removeIf(not(isPerfectSquare()));
        if (copy.isEmpty()) {
            System.out.println("ERROR: no perfect square numbers were found");
            return;
        }
        
        List<Integer> validResults = copy;
        System.out.println("Valid data: " + validResults);
    }
    

    我不知道你要检查多少情况。即使你必须经常重复这个例子,我认为它更清晰。您还可以提取一个接受列表和谓词的方法,以减少重复的块

  2. # 2 楼答案

    通过直接在ConditionToMatch类中设置布尔值,可以更轻松地执行此操作:

    public class ConditionToMatch<E> implements Predicate<E> {
      public Predicate<E> condition;
      public boolean neverMatchedAnything = true;
      public String errorMessage;
    
      public ConditionToMatch (Predicate<E> condition, int order, String errorMessage) {
        this.order = order;
        this.condition = condition;
        this.errorMessage = errorMessage;
      }
    
      @Override
      public boolean test(E e) {
         boolean value = condition.test(e)
        if (value) {
          neverMatchedAnything = false;
        }
        return value;
      }
    }
    

    然后,您可以编写一个通用检查器:

    public static void validateWithConditionClass(List<Integer> sourceToCheck, List<ConditionToMatch<Integer>> conditions) {
        System.out.println("Initial elements: " + sourceToCheck);
        conditions.sort((c1, c2) -> c2.order - c1.order);
    
        Stream<Integer> stream sourceToCheck.stream();
        for (ConditionToMatch<Integer> condition : conditions) 
          stream = stream.filter(condition)
        }
        List<Integer> results = streams.collect();
    
        for (ConditionToMatch<Integer> condition : conditions) 
          if (condition.neverMatchedAnything) {
            System.out.println(current.errorMessage);
            break;
          }
        }
      }
    

    以及两个检查程序的具体实现:

    public static void validateWithConditionClass(List<Integer> sourceToCheck) {
        List<ConditionToMatch<Integer>> conditions = Arrays.toList({isUpTo100ConditionToMatch(), isPerfectSquareConditionToMatch()});
        validateWithConditionClass(sourceToCheck, conditions);
      }
    

    当然还有创造条件的功能:

      public static ConditionToMatch<Integer> isUpTo100ConditionToMatch() {
    return new ConditionToMatch<>(FailureCause.upTo100(), 1, "ERROR: no numbers less or equals than 100 were found");
      }
    
      public static ConditionToMatch<Integer> isPerfectSquareConditionToMatch() {
    return new ConditionToMatch<>( FailureCause.isPerfectSquare(), 2, "ERROR: no perfect square numbers were found");
      }