如何过滤java流直到只有一个匹配?

p8ekf7hl  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(104)

我有一个对象列表,我需要选择一个在大多数条件下都匹配的对象。这意味着我需要不断过滤,直到只剩下一个元素,或者直到没有元素-在这种情况下我抛出。我现在只有3级过滤,所以如果到最后一个过滤器有0个或多个匹配,我也会抛出。是的,过滤的顺序很重要。
我写的东西,工程,但我想知道是否有任何方法,使它更漂亮或更有效。任何帮助感谢!

List<Object> listOfObjects = getAllObjects();

List<Object> filteredObjects1 =
    emptyIfNull(listOfObjects).stream()
        .filter(filter1())
        .collect(Collectors.toList());

if (filteredObjects1.size() == 1) {
    return filteredObjects1.get(0);
}

if (filteredObjects1.size() == 0) {
    throw new Exception();
}

List<Object> filteredObjects2 =
    emptyIfNull(filteredObjects1).stream()
        .filter(filter2())
        .collect(Collectors.toList());

if (filteredObjects2.size() == 1) {
    return filteredObjects2.get(0);
}

if (filteredObjects2.size() == 0) {
    throw new Exception();
}

List<Object> filteredObjects3 =
    emptyIfNull(filteredObjects1).stream()
        .filter(filter3())
        .collect(Collectors.toList());

if (filteredObjects3.size() == 1) {
    return filteredObjects3.get(0);
} 

throw new Exception();
sf6xfgos

sf6xfgos1#

这需要一个递归风格的实现。

public Object lastRemaining(List<Object> listOfObjects, List< Predicate<Object> > filters, int depth) {
    List<Object> filteredObjects = 
        emptyIfNull(listOfObjects).stream()
            .filter(filters.get(depth) // may get index out of bounds if not enough filters
            .collect(Collectors.toList());

    if (filteredObjects.size() == 1) {
        return filteredObjects.get(0);
    } else if (filteredObjects.isEmpty()) {
        throw new Exception();
    } else {
        return lastRemaining(filteredObjects, filters, ++depth);
    }
}

然后这样称呼它:

Predicate<Object> filter1 = o -> o.hashCode() > 5;
Predicate<Object> filter2 = o -> o.hashCode() < 10;
    
filters.add(filter1);
filters.add(filter2);
lastRemaining(getAllObjects(), filters, 0);
bq3bfh9z

bq3bfh9z2#

你可以通过不检查size() == 0来简化代码,并在过滤器上循环。一个简单的方法调用如下:

static Object findOne(List<Object> listOfObjects, Predicate<Object> ... filters) {
    // Ideally use:  Objects.requireNonNull(listOfObjects);
    listOfObjects = emptyIfNull(listOfObjects);
    for (Predicate<Object> filter : filters) {
        listOfObjects = listOfObjects.stream().filter(filter)
                    .collect(Collectors.toList()); // later JDKs: .toList()
        if (listOfObjects.size() == 1) {
            return listOfObjects.get(0);
        }
    }
    throw new RuntimeException("Not found match");
}

电话:

Object match = findOne(getAllObjects(), filter1(), filter2(), filter3() /** , ETC */);

相关问题