Java arraylist 使用流查找缺失的字段

Java arraylist find missing fields using streams

我有下面的代码。 两组arraylist。 如何使用流来迭代和比较 itemlist_a 和 itemlist_b 以检测 itemlist_b 中是否缺少 c 和 d? 当然我可以使用传统的 for 循环,但是有没有其他方法可以使用流或其他方式来实现?

import java.util.ArrayList;
import java.util.List;

    class item {
        String name;

    public item(String name) {
        this.name = name;
    }
}

public class Test {
    public static void main(String[] args) {
        List<item> itemlist_a = new ArrayList<item>();
        itemlist_a.add(new item("a"));
        itemlist_a.add(new item("b"));

        List<item> itemlist_b = new ArrayList<item>();
        itemlist_b.add(new item("a"));
        itemlist_b.add(new item("b"));
        itemlist_b.add(new item("c"));
        itemlist_b.add(new item("d"));
    }
}

我认为这不是一个很好的流应用程序,但您可以这样做:

itemlist_a.stream().filter(e -> !itemlist_b.contains(e)).collect(Collectors.toList());

这将为您提供 itemlist_a 但不在 itemlist_b 中的所有项目的列表。 然而,流是为函数式编程而设计的,这意味着它们不应该依赖于流之外的变量。在这种情况下 itemlist_b 不在流中,但会影响函数的结果。但是它会起作用。

最简单的方法是覆盖Item中的equalshashCode,然后在超集上使用removeAll来保留差异:

//the Item class
@Override
public int hashCode() {
    // TODO
    return Objects.hashCode(name);
}

@Override
public boolean equals(Object obj) {
    // TODO: implement
    return this.name.equals(((item) obj).name);
}

然后就可以得到差值:

itemlist_b.removeAll(itemlist_a);

调用后 itemlist_b 中剩下的就是差值。如果你想让itemlist_b不变,你可以用一个copy

做同样的事情
List<Item> diff = new ArrayList<>(itemlist_b);
diff.removeAll(itemlist_a);

而你在 diff 中有差异。


由于您使用的是列表,因此您只需要注意与重复项相关的业务逻辑。 removeAll 将删除所有匹配元素。

Java 列表 API
一个列表的副本,然后删除与另一个相同的所有元素

List<Item> differences = new ArrayList<>(itemlist_b);
differences.removeAll(itemlist_a);

流 API

List<Item> differences = itemlist_b.stream()
            .filter(element -> !itemlist_a.contains(element))
            .collect(Collectors.toList());

Google Guava

List<Item> differences = new ArrayList<>(Sets.difference(Sets.newHashSet(itemlist_a), Sets.newHashSet(itemlist_b)));

Apache Commons Collections

List<Item> differences = new ArrayList<>((CollectionUtils.removeAll(itemlist_b, itemlist_a)));