オブジェクトの二つのリストを考えると、私はそれらの属性のいずれかに基づいて、その交差にされていない項目伝えることができると思います。次の例で見てみましょう:
私はクラスの持つFoo
2つの属性があります。boo
とplaceholder
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
エラーとして。これは「右」解決策ではないと思わので、どのようにこの問題は、適切に解決されますか?
ラムダ式内のあなたがすることはできませんの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を使用することができます。このために、あなたが必要equals
とhashcode
のメソッドを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());