如何有效地在双循环中执行条件检查?

时间:2016-04-06 15:13:46

标签: java oop java-8 break

我真的不知道如何制定这个问题的标题,所以我只是跳到一个例子中。

让我们说我想迭代一个元素列表,并根据某些条件,将所述元素添加到一个新列表中。

这里我创建了一个方法,基本上想要检查一个项是否是第一个列表的独占(第二个列表中不存在)。现在我知道,对于这个特别愚蠢的例子,你可以用套装来解决这个问题,但我只是想说明一个像这样的东西弹出的情况

public List<Item> newItems(List<Item> items, List<Item> otherItems) {
    List<Item> newItems = new ArrayList<>();

    for (Item i: items) {
        for (Item j: otherItems) {
            if (i.equals(j))
                //Missing code
        }
        newItems.add(i);
    }

    return newItems;
}

所以在这里我只想将Item i添加到newItems,如果它不等于otherItems中的单个项目。我的第一个冲动是将break;放在//Missing Code所在的位置,但这只会突破第一个循环而不会妨碍i添加到newItems

我知道一个正确的解决方案,你可以使用布尔变量来一致地检查if语句的真实性,然后根据它的真值将Item i添加到newItems在第二个循环结束时。它看起来像这样:

for (Item i: items) {
    boolean check = true;

    for (Item j: otherItems) {
        if (i.equals(j))
            check = false;
            break; //To avoid unnecessary iterations
    }

    if (check)
        newItems.add(i);
}

这看起来非常笨重,但也非常多余。有没有更有效和更优雅的方式来做到这一点?

7 个答案:

答案 0 :(得分:3)

如果我正确理解了您的问题,您需要创建一个列表,其中收集的项目来自t\d*.+?x\d*.([a-z]\d.){1,6} ,不包括itemsitems中的项目。如果是,您只需List#removeAll()

即可
otherItems

如果还有其他条件要排除项目,请使用流,过滤器和收集器,如下所示:

public List<Item> newItems(List<Item> items, List<Item> otherItems) {
    List<Item> res = new ArrayList<>(items);  // create a copy of items
    res.removeAll(otherItems);                // remove items presented in otherItems
    return res;
}

答案 1 :(得分:2)

正如WakachopoAchmadJP指出的那样,您可以使用containsbinarySearch执行您所描述的内容。现在您说,这些操作只是示例性的,您可能有不同的条件 - 没有什么能阻止您使用相同的模式,但现在您可能必须自己编写特定的方法:

for(Item i: items) {
    if(!hasMatchingCondition(i, otherItems) {
        newItems.add(i);
    }
}

static boolean hasMatchingCondition(Item i, List<Item> list) {
    for(Item j: list) {
        if(whatever condition regarding i and j) {
            return true;
        }
    }
    return false;
}

清洁和短路。

您可以使用标记语句在单一方法中执行相同操作,即

outer: for(Item i: items) {
    for(Item j: list) {
        if(whatever condition regarding i and j) {
            continue outer;
        }
    }
    newItems.add(i);
}

但是一些开发人员认为标记语句是一种沮丧的功能,也许更重要的是,您可能会在某处找到hasMatchingCondition方法的另一种用途。

答案 2 :(得分:1)

嗯,如果List已经排序了。我认为更快的解决方案是使用二进制搜索,因为它比顺序搜索更快。

for( Item i: items){
    if(Collections.binarySearch(otherItems, i) < 0){
        newItems.add(i);
    }
}

答案 3 :(得分:1)

如果必须,我会这样做:

for(Item i: items){
    if(!otherItems.contains(i)){
        newItems.add(i);
    }
}

答案 4 :(得分:1)

在这个和其他情况下,我认为你可以给他们一个颠倒的焦点,并假设所有项目都符合你的条件,然后删除那些没有。对于这个例子:

{{1}}

答案 5 :(得分:1)

作为嵌套循环的替代方法,在Java 8中,您可以使用Streams API执行以下操作:

public List<Item> newItems(List<Item> items, List<Item> otherItems) {
    return items.stream()
              .filter(i -> !otherItems.contains(i))
              .collect(Collectors.toList());
}

答案 6 :(得分:0)

嗯,你可以这样做;

CollectionUtils.removeAll(collection1, collections2);

此方法也会向您返回一个集合。

https://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/CollectionUtils.html