Java: Proper way of creating a list containing all not-in-intersect elements from two given lists based on a...
Given two Lists of Objects, I'd be able to tell which items are not in their intersect based on one of their attributes. Let's look at the following example:
I have a class Foo
that has two attributes: boo
and placeholder
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
}
Now I am creating two Lists from that (let's say this is my input)
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));
And now I'd like to say which Items are in list1
and not in list2
or in list2
and not in list1
based on their attribute boo
. So in the above example I want a List<Foo> notInIntersectList
that contains one Foo(0)
and one 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.
//...
Sadly I am getting Local variable inBothLists defined in an enclosing scope must be final or effectively final
as an error. How is this issue solved properly, since this seems not to be the "right" solution?
java
add a comment |
Given two Lists of Objects, I'd be able to tell which items are not in their intersect based on one of their attributes. Let's look at the following example:
I have a class Foo
that has two attributes: boo
and placeholder
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
}
Now I am creating two Lists from that (let's say this is my input)
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));
And now I'd like to say which Items are in list1
and not in list2
or in list2
and not in list1
based on their attribute boo
. So in the above example I want a List<Foo> notInIntersectList
that contains one Foo(0)
and one 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.
//...
Sadly I am getting Local variable inBothLists defined in an enclosing scope must be final or effectively final
as an error. How is this issue solved properly, since this seems not to be the "right" solution?
java
Try with a traditional for loop, instead of overusing a lambda, and you should be fine. Code isn't better just because it has a lambda expression!list2.forEach(li2foo -> {
is not more elegant thanfor(Foo li2foo : list2) {
, and you lose the ability tobreak
and modify local variables.
– Anony-Mousse
Jan 1 at 15:16
add a comment |
Given two Lists of Objects, I'd be able to tell which items are not in their intersect based on one of their attributes. Let's look at the following example:
I have a class Foo
that has two attributes: boo
and placeholder
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
}
Now I am creating two Lists from that (let's say this is my input)
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));
And now I'd like to say which Items are in list1
and not in list2
or in list2
and not in list1
based on their attribute boo
. So in the above example I want a List<Foo> notInIntersectList
that contains one Foo(0)
and one 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.
//...
Sadly I am getting Local variable inBothLists defined in an enclosing scope must be final or effectively final
as an error. How is this issue solved properly, since this seems not to be the "right" solution?
java
Given two Lists of Objects, I'd be able to tell which items are not in their intersect based on one of their attributes. Let's look at the following example:
I have a class Foo
that has two attributes: boo
and placeholder
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
}
Now I am creating two Lists from that (let's say this is my input)
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));
And now I'd like to say which Items are in list1
and not in list2
or in list2
and not in list1
based on their attribute boo
. So in the above example I want a List<Foo> notInIntersectList
that contains one Foo(0)
and one 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.
//...
Sadly I am getting Local variable inBothLists defined in an enclosing scope must be final or effectively final
as an error. How is this issue solved properly, since this seems not to be the "right" solution?
java
java
asked Jan 1 at 14:04
RüdigerRüdiger
221323
221323
Try with a traditional for loop, instead of overusing a lambda, and you should be fine. Code isn't better just because it has a lambda expression!list2.forEach(li2foo -> {
is not more elegant thanfor(Foo li2foo : list2) {
, and you lose the ability tobreak
and modify local variables.
– Anony-Mousse
Jan 1 at 15:16
add a comment |
Try with a traditional for loop, instead of overusing a lambda, and you should be fine. Code isn't better just because it has a lambda expression!list2.forEach(li2foo -> {
is not more elegant thanfor(Foo li2foo : list2) {
, and you lose the ability tobreak
and modify local variables.
– Anony-Mousse
Jan 1 at 15:16
Try with a traditional for loop, instead of overusing a lambda, and you should be fine. Code isn't better just because it has a lambda expression!
list2.forEach(li2foo -> {
is not more elegant than for(Foo li2foo : list2) {
, and you lose the ability to break
and modify local variables.– Anony-Mousse
Jan 1 at 15:16
Try with a traditional for loop, instead of overusing a lambda, and you should be fine. Code isn't better just because it has a lambda expression!
list2.forEach(li2foo -> {
is not more elegant than for(Foo li2foo : list2) {
, and you lose the ability to break
and modify local variables.– Anony-Mousse
Jan 1 at 15:16
add a comment |
6 Answers
6
active
oldest
votes
You cannot mutate variables inside a lambda expression (See: Variable used in lambda expression should be final or effectively final)
Here's a way to fix your code (fun with Streams)
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);
The complexity of this is O(n*m)
(where n
and m
are the number of elements in list1 and list2 respectively).
To do this in O(n+m)
, you can use a Set. For this, you need a equals
and hashcode
method on the Foo
class. This considers two Foo
instances as equal only based on the value of the instance variable 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;
}
}
And use a Set
for this as
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());
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override theequals()
-method, but why do I also need to override thehashCode
?
– Rüdiger
Jan 1 at 14:38
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
add a comment |
If you cannot create an equals
and hashCode
on your class (maybe they have them already but not based on boo
), what I would do is:
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 1. Call itset1
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 2. Call itset2
- Use
set1.retainAll(set2)
to get the intersection of the two sets.
Use the following to create my list:
Stream.concat(list1.stream(),list2.stream())
.filter(item-> ! set1.contains(item.getBoo()))
.collect(Collectors.toList);
This is O(m+n) and also ensures the order of the items in the original lists is maintained, as well as any duplicates (items having the same boo
).
add a comment |
First of all, you shall add the methods equals
and hashCode
to your class Foo
(see Why do I need to override the equals and hashCode methods in Java?)
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + boo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Foo))
return false;
Foo other = (Foo) obj;
return boo == other.boo;
}
}
Now you can use the removeAll
method of List
:
Removes all of this collection's elements that are also contained in
the specified collection (optional operation). After this call
returns, this collection will contain no elements in common with the
specified collection.
You will have to build a new List notInIntersectList
like that:
List<Foo> listIntersection = new ArrayList<>(list1);
listIntersection.removeAll(list2);
List<Foo> notInIntersectList = new ArrayList<>(list1);
notInIntersectList.addAll(list2);
notInIntersectList.removeAll(listIntersection);
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
add a comment |
avoid Lambda expressions
They make code harder to read, and less efficient.
If you simply use traditional for
loops, your code should work... plus, you can use break
to stop searching for a second match.
List<Foo> notInIntersectList = new ArrayList<Foo>();
for(Foo li1foo : list1) {
boolean inBothLists = false;
for(Foo li2foo : list2) {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
}
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
}
You probably still recognize your code there... Now here's the pro version with imperative coding:
List<Foo> notInIntersectList = new ArrayList<Foo>();
nextfoo: for(Foo li1foo : list1) {
for(Foo li2foo : list2)
if (li1foo.getBoo() == li2foo.getBoo())
continue nextfoo;
notInIntersectList.add(li1foo);
}
This actually has a very clear and explicit logic (and it will make functional fans puke because of the effective "goto"). It's still slow if list2 is huge though, I didn't want to change your algorithm.
add a comment |
There is already a library for that:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
// I can use intersection as a Set directly, but copying it can be more efficient if I use it a lot.
return intersection.immutableCopy();
If you use difference(Set<E> set1, Set<?> set2)
instead of intersection(Set<E> set1, Set<?> set2)
, you will get the difference of the two.
With ImmutableSet.copyOf(Collection<? extends E> elements)
you can create a Set.
It is called Guava and provides many collection operations:
https://github.com/google/guava/wiki/CollectionUtilitiesExplained
The API: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ImmutableSet.html
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
add a comment |
I see here four possible solutions:
1) Avoid lambda expression following @Anony-Mousse's response
2) Include the variable at the class level (not recommended because this boolean is meant for local use):
public class Testing {
boolean inBothLists = true;
public static void main(String args) {
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
inBothLists = false;
list2.forEach(li2foo -> {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
});
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
});
System.out.println("Intersected values:");
notInIntersectList.forEach(liInFoo -> {
System.out.println(liInFoo);
});
}
3) Using contains method from List (avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
if (!list2.contains(li1foo))
notInIntersectList.add(li1foo);
});
4) Java8 Stream API (already mentioned in another answer and avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
Foo result = list2.stream()
.filter(li2foo -> li1foo.getBoo() == li2foo.getBoo() )
.findAny()
.orElse(null);
if (result == null)
notInIntersectList.add(li1foo);
});
I would go for option 1), 3) or 4). I only kept 2.) to show an example using variables inside lambda functions.
UPDATE: I found 3) and 4) options in a recent Baeldung post on how to find an Element in a List
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53996101%2fjava-proper-way-of-creating-a-list-containing-all-not-in-intersect-elements-fro%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
You cannot mutate variables inside a lambda expression (See: Variable used in lambda expression should be final or effectively final)
Here's a way to fix your code (fun with Streams)
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);
The complexity of this is O(n*m)
(where n
and m
are the number of elements in list1 and list2 respectively).
To do this in O(n+m)
, you can use a Set. For this, you need a equals
and hashcode
method on the Foo
class. This considers two Foo
instances as equal only based on the value of the instance variable 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;
}
}
And use a Set
for this as
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());
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override theequals()
-method, but why do I also need to override thehashCode
?
– Rüdiger
Jan 1 at 14:38
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
add a comment |
You cannot mutate variables inside a lambda expression (See: Variable used in lambda expression should be final or effectively final)
Here's a way to fix your code (fun with Streams)
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);
The complexity of this is O(n*m)
(where n
and m
are the number of elements in list1 and list2 respectively).
To do this in O(n+m)
, you can use a Set. For this, you need a equals
and hashcode
method on the Foo
class. This considers two Foo
instances as equal only based on the value of the instance variable 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;
}
}
And use a Set
for this as
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());
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override theequals()
-method, but why do I also need to override thehashCode
?
– Rüdiger
Jan 1 at 14:38
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
add a comment |
You cannot mutate variables inside a lambda expression (See: Variable used in lambda expression should be final or effectively final)
Here's a way to fix your code (fun with Streams)
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);
The complexity of this is O(n*m)
(where n
and m
are the number of elements in list1 and list2 respectively).
To do this in O(n+m)
, you can use a Set. For this, you need a equals
and hashcode
method on the Foo
class. This considers two Foo
instances as equal only based on the value of the instance variable 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;
}
}
And use a Set
for this as
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());
You cannot mutate variables inside a lambda expression (See: Variable used in lambda expression should be final or effectively final)
Here's a way to fix your code (fun with Streams)
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);
The complexity of this is O(n*m)
(where n
and m
are the number of elements in list1 and list2 respectively).
To do this in O(n+m)
, you can use a Set. For this, you need a equals
and hashcode
method on the Foo
class. This considers two Foo
instances as equal only based on the value of the instance variable 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;
}
}
And use a Set
for this as
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());
edited Jan 1 at 14:28
answered Jan 1 at 14:11
user7user7
9,62932446
9,62932446
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override theequals()
-method, but why do I also need to override thehashCode
?
– Rüdiger
Jan 1 at 14:38
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
add a comment |
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override theequals()
-method, but why do I also need to override thehashCode
?
– Rüdiger
Jan 1 at 14:38
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override the
equals()
-method, but why do I also need to override the hashCode
?– Rüdiger
Jan 1 at 14:38
Assuming I'd have a non-numeric value as attribute I'm comparing (e.g. a string) would I still need to override the hashCode()? So I see it makes sense to simply override the
equals()
-method, but why do I also need to override the hashCode
?– Rüdiger
Jan 1 at 14:38
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
See this - [Why do I need to override the equals and hashCode methods in Java? ](stackoverflow.com/questions/2265503/…)
– user7
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
If you put this object in a hashmap, then you can find it with the correct hashCode function. If you do not override it, it will be lost.
– Charlie
Jan 1 at 14:39
add a comment |
If you cannot create an equals
and hashCode
on your class (maybe they have them already but not based on boo
), what I would do is:
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 1. Call itset1
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 2. Call itset2
- Use
set1.retainAll(set2)
to get the intersection of the two sets.
Use the following to create my list:
Stream.concat(list1.stream(),list2.stream())
.filter(item-> ! set1.contains(item.getBoo()))
.collect(Collectors.toList);
This is O(m+n) and also ensures the order of the items in the original lists is maintained, as well as any duplicates (items having the same boo
).
add a comment |
If you cannot create an equals
and hashCode
on your class (maybe they have them already but not based on boo
), what I would do is:
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 1. Call itset1
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 2. Call itset2
- Use
set1.retainAll(set2)
to get the intersection of the two sets.
Use the following to create my list:
Stream.concat(list1.stream(),list2.stream())
.filter(item-> ! set1.contains(item.getBoo()))
.collect(Collectors.toList);
This is O(m+n) and also ensures the order of the items in the original lists is maintained, as well as any duplicates (items having the same boo
).
add a comment |
If you cannot create an equals
and hashCode
on your class (maybe they have them already but not based on boo
), what I would do is:
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 1. Call itset1
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 2. Call itset2
- Use
set1.retainAll(set2)
to get the intersection of the two sets.
Use the following to create my list:
Stream.concat(list1.stream(),list2.stream())
.filter(item-> ! set1.contains(item.getBoo()))
.collect(Collectors.toList);
This is O(m+n) and also ensures the order of the items in the original lists is maintained, as well as any duplicates (items having the same boo
).
If you cannot create an equals
and hashCode
on your class (maybe they have them already but not based on boo
), what I would do is:
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 1. Call itset1
- Create a
Set<Integer>
(or aBitSet
) containing all theboo
values in list 2. Call itset2
- Use
set1.retainAll(set2)
to get the intersection of the two sets.
Use the following to create my list:
Stream.concat(list1.stream(),list2.stream())
.filter(item-> ! set1.contains(item.getBoo()))
.collect(Collectors.toList);
This is O(m+n) and also ensures the order of the items in the original lists is maintained, as well as any duplicates (items having the same boo
).
answered Jan 1 at 14:27


RealSkepticRealSkeptic
28.2k63463
28.2k63463
add a comment |
add a comment |
First of all, you shall add the methods equals
and hashCode
to your class Foo
(see Why do I need to override the equals and hashCode methods in Java?)
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + boo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Foo))
return false;
Foo other = (Foo) obj;
return boo == other.boo;
}
}
Now you can use the removeAll
method of List
:
Removes all of this collection's elements that are also contained in
the specified collection (optional operation). After this call
returns, this collection will contain no elements in common with the
specified collection.
You will have to build a new List notInIntersectList
like that:
List<Foo> listIntersection = new ArrayList<>(list1);
listIntersection.removeAll(list2);
List<Foo> notInIntersectList = new ArrayList<>(list1);
notInIntersectList.addAll(list2);
notInIntersectList.removeAll(listIntersection);
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
add a comment |
First of all, you shall add the methods equals
and hashCode
to your class Foo
(see Why do I need to override the equals and hashCode methods in Java?)
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + boo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Foo))
return false;
Foo other = (Foo) obj;
return boo == other.boo;
}
}
Now you can use the removeAll
method of List
:
Removes all of this collection's elements that are also contained in
the specified collection (optional operation). After this call
returns, this collection will contain no elements in common with the
specified collection.
You will have to build a new List notInIntersectList
like that:
List<Foo> listIntersection = new ArrayList<>(list1);
listIntersection.removeAll(list2);
List<Foo> notInIntersectList = new ArrayList<>(list1);
notInIntersectList.addAll(list2);
notInIntersectList.removeAll(listIntersection);
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
add a comment |
First of all, you shall add the methods equals
and hashCode
to your class Foo
(see Why do I need to override the equals and hashCode methods in Java?)
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + boo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Foo))
return false;
Foo other = (Foo) obj;
return boo == other.boo;
}
}
Now you can use the removeAll
method of List
:
Removes all of this collection's elements that are also contained in
the specified collection (optional operation). After this call
returns, this collection will contain no elements in common with the
specified collection.
You will have to build a new List notInIntersectList
like that:
List<Foo> listIntersection = new ArrayList<>(list1);
listIntersection.removeAll(list2);
List<Foo> notInIntersectList = new ArrayList<>(list1);
notInIntersectList.addAll(list2);
notInIntersectList.removeAll(listIntersection);
First of all, you shall add the methods equals
and hashCode
to your class Foo
(see Why do I need to override the equals and hashCode methods in Java?)
class Foo {
private int boo;
private int placeholder = 1;
public Foo(int boo) {
this.boo = boo;
}
public int getBoo() {
return boo;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + boo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Foo))
return false;
Foo other = (Foo) obj;
return boo == other.boo;
}
}
Now you can use the removeAll
method of List
:
Removes all of this collection's elements that are also contained in
the specified collection (optional operation). After this call
returns, this collection will contain no elements in common with the
specified collection.
You will have to build a new List notInIntersectList
like that:
List<Foo> listIntersection = new ArrayList<>(list1);
listIntersection.removeAll(list2);
List<Foo> notInIntersectList = new ArrayList<>(list1);
notInIntersectList.addAll(list2);
notInIntersectList.removeAll(listIntersection);
edited Jan 1 at 14:50
answered Jan 1 at 14:30


Dorian GrayDorian Gray
1,511517
1,511517
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
add a comment |
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
It seems you are keeping the intersection rather than the items not in the intersection.
– RealSkeptic
Jan 1 at 14:32
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
Oh, sorry, that's true. I'll fix it, thanks!
– Dorian Gray
Jan 1 at 14:33
add a comment |
avoid Lambda expressions
They make code harder to read, and less efficient.
If you simply use traditional for
loops, your code should work... plus, you can use break
to stop searching for a second match.
List<Foo> notInIntersectList = new ArrayList<Foo>();
for(Foo li1foo : list1) {
boolean inBothLists = false;
for(Foo li2foo : list2) {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
}
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
}
You probably still recognize your code there... Now here's the pro version with imperative coding:
List<Foo> notInIntersectList = new ArrayList<Foo>();
nextfoo: for(Foo li1foo : list1) {
for(Foo li2foo : list2)
if (li1foo.getBoo() == li2foo.getBoo())
continue nextfoo;
notInIntersectList.add(li1foo);
}
This actually has a very clear and explicit logic (and it will make functional fans puke because of the effective "goto"). It's still slow if list2 is huge though, I didn't want to change your algorithm.
add a comment |
avoid Lambda expressions
They make code harder to read, and less efficient.
If you simply use traditional for
loops, your code should work... plus, you can use break
to stop searching for a second match.
List<Foo> notInIntersectList = new ArrayList<Foo>();
for(Foo li1foo : list1) {
boolean inBothLists = false;
for(Foo li2foo : list2) {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
}
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
}
You probably still recognize your code there... Now here's the pro version with imperative coding:
List<Foo> notInIntersectList = new ArrayList<Foo>();
nextfoo: for(Foo li1foo : list1) {
for(Foo li2foo : list2)
if (li1foo.getBoo() == li2foo.getBoo())
continue nextfoo;
notInIntersectList.add(li1foo);
}
This actually has a very clear and explicit logic (and it will make functional fans puke because of the effective "goto"). It's still slow if list2 is huge though, I didn't want to change your algorithm.
add a comment |
avoid Lambda expressions
They make code harder to read, and less efficient.
If you simply use traditional for
loops, your code should work... plus, you can use break
to stop searching for a second match.
List<Foo> notInIntersectList = new ArrayList<Foo>();
for(Foo li1foo : list1) {
boolean inBothLists = false;
for(Foo li2foo : list2) {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
}
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
}
You probably still recognize your code there... Now here's the pro version with imperative coding:
List<Foo> notInIntersectList = new ArrayList<Foo>();
nextfoo: for(Foo li1foo : list1) {
for(Foo li2foo : list2)
if (li1foo.getBoo() == li2foo.getBoo())
continue nextfoo;
notInIntersectList.add(li1foo);
}
This actually has a very clear and explicit logic (and it will make functional fans puke because of the effective "goto"). It's still slow if list2 is huge though, I didn't want to change your algorithm.
avoid Lambda expressions
They make code harder to read, and less efficient.
If you simply use traditional for
loops, your code should work... plus, you can use break
to stop searching for a second match.
List<Foo> notInIntersectList = new ArrayList<Foo>();
for(Foo li1foo : list1) {
boolean inBothLists = false;
for(Foo li2foo : list2) {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
}
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
}
You probably still recognize your code there... Now here's the pro version with imperative coding:
List<Foo> notInIntersectList = new ArrayList<Foo>();
nextfoo: for(Foo li1foo : list1) {
for(Foo li2foo : list2)
if (li1foo.getBoo() == li2foo.getBoo())
continue nextfoo;
notInIntersectList.add(li1foo);
}
This actually has a very clear and explicit logic (and it will make functional fans puke because of the effective "goto"). It's still slow if list2 is huge though, I didn't want to change your algorithm.
answered Jan 1 at 15:29


Anony-MousseAnony-Mousse
58.6k797162
58.6k797162
add a comment |
add a comment |
There is already a library for that:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
// I can use intersection as a Set directly, but copying it can be more efficient if I use it a lot.
return intersection.immutableCopy();
If you use difference(Set<E> set1, Set<?> set2)
instead of intersection(Set<E> set1, Set<?> set2)
, you will get the difference of the two.
With ImmutableSet.copyOf(Collection<? extends E> elements)
you can create a Set.
It is called Guava and provides many collection operations:
https://github.com/google/guava/wiki/CollectionUtilitiesExplained
The API: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ImmutableSet.html
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
add a comment |
There is already a library for that:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
// I can use intersection as a Set directly, but copying it can be more efficient if I use it a lot.
return intersection.immutableCopy();
If you use difference(Set<E> set1, Set<?> set2)
instead of intersection(Set<E> set1, Set<?> set2)
, you will get the difference of the two.
With ImmutableSet.copyOf(Collection<? extends E> elements)
you can create a Set.
It is called Guava and provides many collection operations:
https://github.com/google/guava/wiki/CollectionUtilitiesExplained
The API: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ImmutableSet.html
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
add a comment |
There is already a library for that:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
// I can use intersection as a Set directly, but copying it can be more efficient if I use it a lot.
return intersection.immutableCopy();
If you use difference(Set<E> set1, Set<?> set2)
instead of intersection(Set<E> set1, Set<?> set2)
, you will get the difference of the two.
With ImmutableSet.copyOf(Collection<? extends E> elements)
you can create a Set.
It is called Guava and provides many collection operations:
https://github.com/google/guava/wiki/CollectionUtilitiesExplained
The API: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ImmutableSet.html
There is already a library for that:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
// I can use intersection as a Set directly, but copying it can be more efficient if I use it a lot.
return intersection.immutableCopy();
If you use difference(Set<E> set1, Set<?> set2)
instead of intersection(Set<E> set1, Set<?> set2)
, you will get the difference of the two.
With ImmutableSet.copyOf(Collection<? extends E> elements)
you can create a Set.
It is called Guava and provides many collection operations:
https://github.com/google/guava/wiki/CollectionUtilitiesExplained
The API: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ImmutableSet.html
edited Jan 1 at 14:44
answered Jan 1 at 14:37
CharlieCharlie
6172926
6172926
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
add a comment |
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
Op wants to have the non-intersected values!
– Seelenvirtuose
Jan 1 at 14:40
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
I corrected my answer. Thanks.
– Charlie
Jan 1 at 14:45
add a comment |
I see here four possible solutions:
1) Avoid lambda expression following @Anony-Mousse's response
2) Include the variable at the class level (not recommended because this boolean is meant for local use):
public class Testing {
boolean inBothLists = true;
public static void main(String args) {
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
inBothLists = false;
list2.forEach(li2foo -> {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
});
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
});
System.out.println("Intersected values:");
notInIntersectList.forEach(liInFoo -> {
System.out.println(liInFoo);
});
}
3) Using contains method from List (avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
if (!list2.contains(li1foo))
notInIntersectList.add(li1foo);
});
4) Java8 Stream API (already mentioned in another answer and avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
Foo result = list2.stream()
.filter(li2foo -> li1foo.getBoo() == li2foo.getBoo() )
.findAny()
.orElse(null);
if (result == null)
notInIntersectList.add(li1foo);
});
I would go for option 1), 3) or 4). I only kept 2.) to show an example using variables inside lambda functions.
UPDATE: I found 3) and 4) options in a recent Baeldung post on how to find an Element in a List
add a comment |
I see here four possible solutions:
1) Avoid lambda expression following @Anony-Mousse's response
2) Include the variable at the class level (not recommended because this boolean is meant for local use):
public class Testing {
boolean inBothLists = true;
public static void main(String args) {
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
inBothLists = false;
list2.forEach(li2foo -> {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
});
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
});
System.out.println("Intersected values:");
notInIntersectList.forEach(liInFoo -> {
System.out.println(liInFoo);
});
}
3) Using contains method from List (avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
if (!list2.contains(li1foo))
notInIntersectList.add(li1foo);
});
4) Java8 Stream API (already mentioned in another answer and avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
Foo result = list2.stream()
.filter(li2foo -> li1foo.getBoo() == li2foo.getBoo() )
.findAny()
.orElse(null);
if (result == null)
notInIntersectList.add(li1foo);
});
I would go for option 1), 3) or 4). I only kept 2.) to show an example using variables inside lambda functions.
UPDATE: I found 3) and 4) options in a recent Baeldung post on how to find an Element in a List
add a comment |
I see here four possible solutions:
1) Avoid lambda expression following @Anony-Mousse's response
2) Include the variable at the class level (not recommended because this boolean is meant for local use):
public class Testing {
boolean inBothLists = true;
public static void main(String args) {
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
inBothLists = false;
list2.forEach(li2foo -> {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
});
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
});
System.out.println("Intersected values:");
notInIntersectList.forEach(liInFoo -> {
System.out.println(liInFoo);
});
}
3) Using contains method from List (avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
if (!list2.contains(li1foo))
notInIntersectList.add(li1foo);
});
4) Java8 Stream API (already mentioned in another answer and avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
Foo result = list2.stream()
.filter(li2foo -> li1foo.getBoo() == li2foo.getBoo() )
.findAny()
.orElse(null);
if (result == null)
notInIntersectList.add(li1foo);
});
I would go for option 1), 3) or 4). I only kept 2.) to show an example using variables inside lambda functions.
UPDATE: I found 3) and 4) options in a recent Baeldung post on how to find an Element in a List
I see here four possible solutions:
1) Avoid lambda expression following @Anony-Mousse's response
2) Include the variable at the class level (not recommended because this boolean is meant for local use):
public class Testing {
boolean inBothLists = true;
public static void main(String args) {
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
inBothLists = false;
list2.forEach(li2foo -> {
if (li1foo.getBoo() == li2foo.getBoo()) {
inBothLists = true;
}
});
if (!inBothLists) {
notInIntersectList.add(li1foo);
}
});
System.out.println("Intersected values:");
notInIntersectList.forEach(liInFoo -> {
System.out.println(liInFoo);
});
}
3) Using contains method from List (avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
if (!list2.contains(li1foo))
notInIntersectList.add(li1foo);
});
4) Java8 Stream API (already mentioned in another answer and avoiding boolean):
List<Foo> notInIntersectList = new ArrayList<Foo>();
list1.forEach(li1foo -> {
Foo result = list2.stream()
.filter(li2foo -> li1foo.getBoo() == li2foo.getBoo() )
.findAny()
.orElse(null);
if (result == null)
notInIntersectList.add(li1foo);
});
I would go for option 1), 3) or 4). I only kept 2.) to show an example using variables inside lambda functions.
UPDATE: I found 3) and 4) options in a recent Baeldung post on how to find an Element in a List
edited Jan 1 at 20:31
answered Jan 1 at 15:44


Carlos CaveroCarlos Cavero
1,0621619
1,0621619
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53996101%2fjava-proper-way-of-creating-a-list-containing-all-not-in-intersect-elements-fro%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Try with a traditional for loop, instead of overusing a lambda, and you should be fine. Code isn't better just because it has a lambda expression!
list2.forEach(li2foo -> {
is not more elegant thanfor(Foo li2foo : list2) {
, and you lose the ability tobreak
and modify local variables.– Anony-Mousse
Jan 1 at 15:16