I have this below code. Two sets of arraylist. How do I use streams to iterate and compare itemlist_a and itemlist_b to detect that c and d is missing in itemlist_b? Of course I can use the traditional for loop, but is there a different way to achieve using streams or something else?
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"));
}
}
CodePudding user response:
Java List API
copy of one list and then remove all the elements common with the other
List<Item> differences = new ArrayList<>(itemlist_b);
differences.removeAll(itemlist_a);
Streams API
List<Item> differences = itemlist_b.stream()
.filter(element -> !itemlist_a.contains(element))
.collect(Collectors.toList());
List<Item> differences = new ArrayList<>(Sets.difference(Sets.newHashSet(itemlist_a), Sets.newHashSet(itemlist_b)));
List<Item> differences = new ArrayList<>((CollectionUtils.removeAll(itemlist_b, itemlist_a)));
CodePudding user response:
I don't think this is a good application for streams, but you could do it like this:
itemlist_a.stream().filter(e -> !itemlist_b.contains(e)).collect(Collectors.toList());
This will give you a list of all items which are in itemlist_a but not in itemlist_b. However streams are designed for functional programming which means that they should not rely on variables outside the stream. In this case itemlist_b is not in the stream but does influence the outcome of the function. It will work however.
CodePudding user response:
The simplest approach is to override equals
and hashCode
in Item, then use removeAll
on the superset to retain the difference:
//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);
}
Then you can get the difference:
itemlist_b.removeAll(itemlist_a);
What will be left in itemlist_b
after that call will be the difference. If you want itemlist_b
to be unchanged, you can do the same thing using a copy
List<Item> diff = new ArrayList<>(itemlist_b);
diff.removeAll(itemlist_a);
And you have the difference in diff
.
Since you're using lists, you just need to pay attention to your business logic with respect to duplicates. removeAll
will remove all matching elements.