Home > Back-end >  Java arraylist find missing fields using streams
Java arraylist find missing fields using streams

Time:03-01

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());

Google Guava

List<Item> differences = new ArrayList<>(Sets.difference(Sets.newHashSet(itemlist_a), Sets.newHashSet(itemlist_b)));

Apache Commons Collections

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.

  • Related