Javaの:特定の属性に基づいて、2つの与えられたリストから、すべてではありません・イン・交差要素を含むリストを作成するための適切な方法はありますか?

リュディガー:

オブジェクトの二つのリストを考えると、私はそれらの属性のいずれかに基づいて、その交差にされていない項目伝えることができると思います。次の例で見てみましょう:

私はクラスの持つFoo2つの属性があります。booplaceholder

class Foo {
    private int boo;
    private int placeholder = 1;

    public Foo(int boo) {
        this.boo = boo;
    }

    public int getBoo() {
        return boo;
    }
}

今、私はそれから二つのリストを作成しています(のは、これは私の入力であるとしましょう)

    List<Foo> list1 = new ArrayList<Foo>();
    list1.add(new Foo(1));
    list1.add(new Foo(2));
    list1.add(new Foo(3));

    List<Foo> list2 = new ArrayList<Foo>();
    list2.add(new Foo(0));
    list2.add(new Foo(1));
    list2.add(new Foo(2));

そして今、私がしているどのアイテム言いたいlist1ではないlist2か、でlist2はないでlist1自分の属性に基づきますbooしたがって、上記の例では私がしたいList<Foo> notInIntersectListいずれかが含まれているFoo(0)と1をFoo(3)

    List<Foo> notInIntersectList = new ArrayList<Foo>();
    list1.forEach(li1foo -> {
        boolean inBothLists = false;
        list2.forEach(li2foo -> {
            if (li1foo.getBoo() == li2foo.getBoo()) {
                inBothLists = true;
            }
        });
        if (!inBothLists) {
            notInIntersectList.add(li1foo);
        }
    });
    //now I covered all items in list1 but not in list2. Now do this again with lists swapped, so I can also cover those.
    //...

悲しいことに、私は取得していますLocal variable inBothLists defined in an enclosing scope must be final or effectively finalエラーとして。これは「右」解決策ではないと思わので、どのようにこの問題は、適切に解決されますか?

user7:

ラムダ式内のあなたがすることはできませんのmutate変数(参照:ラムダ式で使用する変数は、最終的または効果的に最終でなければなりません

ここにあなたのコード(ストリームとの楽しみを)修正する方法です

List<Foo> notInIntersectList = list1.stream()
        .filter(fooElementFromList1 -> list2
                .stream()
                .noneMatch(fooElementFromList2 -> fooElementFromList2.getBoo() == fooElementFromList1.getBoo()))
        .collect(Collectors.toCollection(ArrayList::new));

list2.stream()
        .filter(fooElementFromList2 -> list1
            .stream()
            .noneMatch(fooElementFromList1 -> fooElementFromList1.getBoo() == fooElementFromList2.getBoo()))
        .forEach(notInIntersectList::add);

この複雑でありO(n*m)(ここで、n且つmそれぞれLIST1とLIST2内の要素の数です)。

この中を実行するにO(n+m)は、Setを使用することができます。このために、あなたが必要equalshashcodeのメソッドをFooクラス。これは、二つの考慮Fooのみインスタンス変数の値に基づいて、同じようにインスタンスboo

class Foo {
    ....

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Foo other = (Foo) obj;
        return boo == other.boo;
    }

    @Override
    public int hashCode() {
        return boo;
    }
}

そして使用しSetて、このために

Set<Foo> fooSet1 = new HashSet<>(list1);
Set<Foo> fooSet2 = new HashSet<>(list2);

fooSet1.removeAll(list2);
fooSet2.removeAll(list1);

List<Foo> notInIntersectList = Stream.concat(fooSet1.stream(), fooSet2.stream())
            .collect(Collectors.toList());

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=177532&siteId=1