두 개체 목록을 감안할 때, 나는 항목은 그 속성 중 하나를 기반으로 자신의 교차에없는 어떤 말할 수있을 것입니다. 다음 예제를 살펴 보자 :
나는 수업이 Foo
두 가지 속성이 있습니다 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)
하나를 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
는 각각리스트 1과리스트 2의 요소 수이다).
이에서 작업을 수행하려면 O(n+m)
, 당신은 설정을 사용할 수 있습니다. 이를 위해, 당신은 필요 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());