简体   繁体   English

如何优化 Java 中的列表过滤

[英]How to optimise this filtering of list in Java

I have the following code:我有以下代码:

private List<String> validate(StartValue start, List<String> colors, Entity entity) {
    if (!CollectionUtils.isEmpty(colors)) {
        return colors.stream()
                     .filter(color -> ValidationUtil.getColorfulValues(start, color.getRGBValue()).isEmpty() ||
                                      (!ValidationUtil.getColorfulValues(start, color.getRGBValue()).isEmpty() &&
                                       ValidationUtil.getColorfulValues(start, color.getRGBValue()).contains(entity.getColor())))
                     .collect(Collectors.toList());
    }
    return colors;
}

Here ValidationUtil.getColorfulValues is getting called thrice for each value in the list.这里ValidationUtil.getColorfulValues为列表中的每个值调用三次。 Is there a way to optimize the filter so that we can save the value of the call?有没有办法优化过滤器以便我们可以保存调用的值?

If you would have not represented the code as a lambda expression, but as a block statement you would have been able to simplify it further.如果您没有将代码表示为 lambda 表达式,但作为块语句,您将能够进一步简化它。

.filter(color -> {
    List<String> colourFulValues = ValidationUtil.getColorfulValues(start,
                    color.getRGBValue());
    return colourFulValues.isEmpty() || colourFulValues.contains(entity.getColor())
}

Of course, you could abstract the block as a Predicate of its own depending on its usage.当然,您可以根据使用情况将块抽象为它自己的Predicate The type of the Predicate would be the type you have chosen to represent the color.谓词的类型将是您选择代表颜色的类型。 Currently, in your question, for example, if it's a java.lang.String , where is the method color.getRGBValue() associated from?目前,在您的问题中,例如,如果它是java.lang.String ,则关联的方法color.getRGBValue()来自哪里?

You can use a method reference :您可以使用方法参考

private List<String> validate(StartValue start, List<String> colors, Entity entity) {
    if (!CollectionUtils.isEmpty(colors)) {
        return colors.stream()
                     .filter(this::filter)
                     .collect(Collectors.toList());
    }
    return colors;
}

private boolean filter(String color) {
    var rgbVal = color.getRGBValue();
    var cv = ValidationUtil.getColorfulValues(start, rgbVal);
    boolean empty = cv.isEmpty();
    return empty || (!empty && cv.contains(entity.getColor()));
}

Note that I use var since it is not clear to me what color.getRGBValue() returns and also what ValidationUtil.getColorfulValues() returns.请注意,我使用var因为我不清楚color.getRGBValue()返回什么以及ValidationUtil.getColorfulValues()返回什么。

  • Guessing that CollectionUtils.isEmpty considers null elements non-existing.猜测CollectionUtils.isEmpty认为 null 元素不存在。
  • For the filter condition evaluating ValidationUtil.getColorfulValues(start, color.getRGBValue())) only once requires mapping to it.对于评估ValidationUtil.getColorfulValues(start, color.getRGBValue()))的过滤条件,仅需要映射一次。 But one needs to conserve the color too, to collect it in a list.但是也需要保存颜色,将其收集在一个列表中。 So I introduced a record ColorWithValues .所以我介绍了一个record ColorWithValues The record class is intended for such kind of uses. record class 旨在用于此类用途。
  • || is a short-circuit operator and does not need a negation of its first argument.是短路运算符,不需要对其第一个参数进行否定。

So:所以:

private List<String> validate(StartValue start, List<String> colors, Entity entity) {
    record ColorWithValues(String color, Set<String> values) {}
    return colors.stream()
                .filter(Objects::nonNull)
                .map(c ->
                     new ColorWithValues(c,
                         ValidationUtil.getColorfulValues(start, c.getRGBValue())))
                .filter(cv -> cv.values.isEmpty() ||
                              cv.values.contains(entity.getColor()))
                .map(cv -> cv.color)
                .collect(Collectors.toList());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM