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

Java 如何在双循环中高效地执行条件检查?,java,oop,java-8,break,Java,Oop,Java 8,Break,我真的不知道如何表述这个问题的标题,所以我将跳进一个例子 假设我想迭代元素列表,并根据特定条件,将所述元素添加到新列表中 在这里,我创建了一个方法,该方法基本上希望检查一个项是否是第一个列表的专有项(在第二个列表中不存在)。现在我知道,对于这个特别愚蠢的例子,你可以用集合来解决这个问题,但我只是想说明一个例子,在这个例子中,类似这样的东西会突然出现 public List<Item> newItems(List<Item> items, List<Item>

我真的不知道如何表述这个问题的标题,所以我将跳进一个例子

假设我想迭代元素列表,并根据特定条件,将所述元素添加到新列表中

在这里,我创建了一个方法,该方法基本上希望检查一个项是否是第一个列表的专有项(在第二个列表中不存在)。现在我知道,对于这个特别愚蠢的例子,你可以用集合来解决这个问题,但我只是想说明一个例子,在这个例子中,类似这样的东西会突然出现

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;
}

这似乎是难以置信的庞大,但也相当多余。有没有一种更有效、更优雅的方法来实现这一点?

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

for( Item i: items){
    if(Collections.binarySearch(otherItems, i) < 0){
        newItems.add(i);
    }
}
用于(项目i:项目){
if(Collections.binarySearch(otherItems,i)<0){
新增项目。添加(i);
}
}

如果有必要,我会这样做:

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

如果我正确理解了您的问题,您需要创建一个列表,其中包含从
项目中收集的项目,不包括
项目和
其他项目中存在的项目。如果是,您可以通过以下方式完成:


嗯,你可以这样做

CollectionUtils.removeAll(collection1, collections2);
此方法还将向您返回一个集合


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

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

 for (Item i: items) {
     for (Item j: otherItems) {
         if (i.equals(j)){
             newItems.remove(i)
             break;
     }
 }
 return newItems;
}
公共列表新项目(列表项目,列表其他项目){
List newItems=新数组列表(items);
用于(项目i:项目){
对于(项目j:其他项目){
如果(i等于(j)){
newItems.remove(i)
打破
}
}
返回新项目;
}

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

public List<Item> newItems(List<Item> items, List<Item> otherItems) {
    return items.stream()
              .filter(i -> !otherItems.contains(i))
              .collect(Collectors.toList());
}
公共列表新项目(列表项目,列表其他项目){
returnitems.stream()
.filter(i->!otherItems.contains(i))
.collect(Collectors.toList());
}
正如和所指出的,您可以使用
contains
binarySearch
执行您所描述的操作。现在您说,这些操作只是示例性的,您可能有不同的条件,没有什么可以阻止您使用相同的模式,但现在您可能必须自己编写特定的方法:

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;
}

但是一些开发人员认为带标签的语句是一个不受欢迎的特性,也许更重要的是,您可能会在某个地方找到
hasMatchingCondition
方法的另一个用途。

@AchmadJP它是一个ArrayList,因此每个元素在列表中都有一个不同的位置,是的,但是
可以在ArrayList上使用
在官方文档中可以看到,这是SETS上唯一有效的语法:在这个示例中,这确实是我正在做的,但我只是在寻找一种基于特定条件执行操作的通用方法。您提出的解决方案与此示例相关
public List<Item> newItems(List<Item> items, List<Item> otherItems) {
 List<Item> newItems = new ArrayList<>(items);

 for (Item i: items) {
     for (Item j: otherItems) {
         if (i.equals(j)){
             newItems.remove(i)
             break;
     }
 }
 return newItems;
}
public List<Item> newItems(List<Item> items, List<Item> otherItems) {
    return items.stream()
              .filter(i -> !otherItems.contains(i))
              .collect(Collectors.toList());
}
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);
}