如果先前的过滤器导致空流,则过滤流 JAVA

Filtering a stream if the previous filter resulted in an empty stream JAVA

我花了几个小时试图找到更简单的解决方案,但我一直无法想出最佳答案。

我的问题是我有两个 Set<String> 和一个 List<> 我必须根据集合对列表<>应用第一个过滤器,以防结果为空或只有 1元素,我必须用缺失的 Set<String>.

再次过滤 List<>

我有这个逻辑,虽然它有效,但在我看来有点难看。

  private static final Set<String> ALLOWED_PATH =
      Set.of("/anto", "chachi");
  private static final Set<String> SECOD_ALLOWED_PATH =
      Set.of("/jose", "chuchu");


  public void valid(final List<itemObject> itemList) {

    List<itemObject> itemFiltered = filterPath(itemList, ALLOWED_PATH);

    if (itemFiltered.size() < 2) {
      itemFiltered = filterPath(itemList, SECOND_ALLOWED_PATH);
    }

    //Continue code
  }


  private List<itemObject> filterPath(
      final List<itemObject> itemList, final Set<String> allowedPath) {

    return itemList
        .stream()
        .filter(
            item ->
                allowedPath
                    .stream()
                    .anyMatch(
                        path ->
                            item.getPath().contains(path) && item.getValue().equals(Boolean.TRUE)))
        .collect(Collectors.toList());
  }

在我的示例中,它可以工作,但我不喜欢必须检查列表的大小是否小于 2 才能知道它没有找到第一个的 2 路径的想法,我必须做第二个过滤器。

我不是 lambda 专家,有什么办法让它更优化吗?

谢谢!

考虑根据两者
过滤和收集匹配项 同时设置路径并支付拥有
的成本 另一个(有时是多余的)列表。

添加以下 import 声明:

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;

假设未指定的 ItemObject 类型大致为:

interface ItemObject
{
    String getPath();
    boolean getValue();
}

执行filterPath如下:

private static List<ItemObject> filterPath(
                final List<ItemObject> itemList)
{
    class PairCollector<T, U>
    {
        private final Predicate<T> primaryFilter;
        private final Predicate<T> secondaryFilter;
        private final Predicate<List<T>> selectFilter;
        private final List<T> primaryList;
        private final List<T> secondaryList;

        PairCollector(Function<Set<U>, Predicate<T>> pairFilter,
                    Predicate<List<T>> selectFilter,
                    Set<U> primarySet,
                    Set<U> secondarySet,
                    int listCapacity)
        {
            this.primaryFilter = pairFilter.apply(
                            primarySet);
            this.secondaryFilter = pairFilter.apply(
                            secondarySet);
            this.selectFilter = selectFilter;
            this.primaryList = new ArrayList<>(
                            listCapacity);
            this.secondaryList = new ArrayList<>(
                            listCapacity);
        }

        PairCollector<T, U> filter(T item)
        {
            if (primaryFilter.test(item))
                primaryList.add(item);

            if (selectFilter.test(primaryList)
                    && secondaryFilter.test(item))
                secondaryList.add(item);

            return this;
        }

        List<T> selectPrimaryElseSecondary()
        {
            return selectFilter.test(primaryList)
                ? secondaryList
                : primaryList;
        }
    }

    return Collections.unmodifiableList(itemList
        .stream()
        .reduce(new PairCollector<>((Set<String> paths) ->
                        (ItemObject item) ->
                                paths
                        .stream()
                        .anyMatch(path -> item
                                .getPath()
                                .contains(path)
                            && item.getValue()),
                    list -> list.size() < 2,
                    ALLOWED_PATH,
                    SECOND_ALLOWED_PATH,
                    itemList.size()),
            PairCollector::filter,
            (left, right) -> {
                throw new UnsupportedOperationException();
            })
        .selectPrimaryElseSecondary());
}

具有仅绑定变量 lambda 的变体实现
表达式。 (Item 在谓词参数
中自由出现 anyMatch 在上面的实现中。)

private static List<ItemObject> filterPath(
                final List<ItemObject> itemList)
{
    class PairCollector<T, U>
    {
        private final Predicate<Predicate<U>> primaryFilter;
        private final Predicate<Predicate<U>> secondaryFilter;
        private final Function<T, Predicate<U>> matcher;
        private final Predicate<List<T>> selectFilter;
        private final List<T> primaryList;
        private final List<T> secondaryList;

        PairCollector(Function<Set<U>, Predicate<Predicate<U>>>
                            pairFilter,
                Function<T, Predicate<U>> matcher,
                Predicate<List<T>> selectFilter,
                Set<U> primarySet,
                Set<U> secondarySet,
                int listCapacity)
        {
            this.primaryFilter = pairFilter.apply(
                            primarySet);
            this.secondaryFilter = pairFilter.apply(
                            secondarySet);
            this.matcher = matcher;
            this.selectFilter = selectFilter;
            this.primaryList = new ArrayList<>(
                            listCapacity);
            this.secondaryList = new ArrayList<>(
                            listCapacity);
        }

        PairCollector<T, U> filter(T item)
        {
            final Predicate<U> matcher_ = matcher.apply(item);

            if (primaryFilter.test(matcher_))
                primaryList.add(item);

            if (selectFilter.test(primaryList)
                    && secondaryFilter.test(matcher_))
                secondaryList.add(item);

            return this;
        }

        List<T> selectPrimaryElseSecondary()
        {
            return selectFilter.test(primaryList)
                ? secondaryList
                : primaryList;
        }
    }

    return Collections.unmodifiableList(itemList
        .stream()
        .reduce(new PairCollector<>(
                paths -> paths.stream()::anyMatch,
                (ItemObject item) ->
                    (String path) -> item
                        .getPath()
                        .contains(path)
                    && item.getValue(),
                list -> list.size() < 2,
                ALLOWED_PATH,
                SECOND_ALLOWED_PATH,
                itemList.size()),
            PairCollector::filter,
            (left, right) -> {
                throw new UnsupportedOperationException();
            })
        .selectPrimaryElseSecondary());
}