How can I return the difference between two lists?

JavaListObjectFiltering

Java Problem Overview


I have two array lists e.g.

List<Date> a;
contains : 10/10/2014, 10/11/2016

List<Date> b;
contains : 10/10/2016

How can i do a check between list a and b so the value that is missing in b is returned?e.g. 10/10/2014

Java Solutions


Solution 1 - Java

You can convert them to Set collections, and perform a set difference operation on them.

Like this:

Set<Date> ad = new HashSet<Date>(a);
Set<Date> bd = new HashSet<Date>(b);
ad.removeAll(bd);

Solution 2 - Java

If you only want find missing values in b, you can do:

List toReturn = new ArrayList(a);
toReturn.removeAll(b);

return toReturn;

If you want to find out values which are present in either list you can execute upper code twice. With changed lists.

Solution 3 - Java

I was looking similar but I wanted the difference in either list (uncommon elements between the 2 lists).

Let say I have:

List<String> oldKeys = Arrays.asList("key0","key1","key2","key5");
List<String> newKeys = Arrays.asList("key0","key2","key5", "key6");

And I wanted to know which key has been added and which key is removed i.e I wanted to get (key1, key6)

Using org.apache.commons.collections.CollectionUtils

List<String> list = new ArrayList<>(CollectionUtils.disjunction(newKeys, oldKeys));

Result

["key1", "key6"]

Solution 4 - Java

You can use filter in the Java 8 Stream library

List<String> aList = List.of("l","e","t","'","s");
List<String> bList = List.of("g","o","e","s","t");

List<String> difference = aList.stream()
    .filter(aObject -> {
        return ! bList.contains(aObject);
      })
    .collect(Collectors.toList());

//more reduced: no curly braces, no return
List<String> difference2 = aList.stream()
    .filter(aObject -> ! bList.contains(aObject))
    .collect(Collectors.toList());

Result of System.out.println(difference);:

>[e, t, s]

Solution 5 - Java

You can use CollectionUtils from Apache Commons Collections 4.0:

new ArrayList<>(CollectionUtils.subtract(a, b))

Solution 6 - Java

First convert list to sets.

// create an empty set 
Set<T> set = new HashSet<>(); 

// Add each element of list into the set 
for (T t : list) 
    set.add(t); 

You can use Sets.difference(Set1, Set2), which returns extra items present in Set1.
You can use Sets.difference(Set2, Set1), which returns extra items present in Set2.

Solution 7 - Java

With Stream API you can do something like this:

List<String> aWithoutB = a.stream()
    .filter(element -> !b.contains(element))
    .collect(Collectors.toList());

List<String> bWithoutA = b.stream()
    .filter(element -> !a.contains(element))
    .collect(Collectors.toList());

Solution 8 - Java

Here is a generic solution for this problem.

public <T> List<T> difference(List<T> first, List<T> second) {
    List<T> toReturn = new ArrayList<>(first);
    toReturn.removeAll(second);
    return toReturn;
}

Solution 9 - Java

You may call Underscore.difference(lists) method in underscore-java library. Live example

import com.github.underscore.Underscore;
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(1, 2, 3);
        List<Integer> list2 = Arrays.asList(1, 2);
        List<Integer> list3 = Underscore.difference(list1, list2);
        System.out.println(list3);
        // [3]
    }
}

Solution 10 - Java

List<String> l1 = new ArrayList<String>();
l1.add("apple");
l1.add("orange");
l1.add("banana");
l1.add("strawberry");

List<String> l2 = new ArrayList<String>();
l2.add("apple");
l2.add("orange");

System.out.println(l1);
System.out.println(l2);

for (String A: l2) {
  if (l1.contains(A))
    l1.remove(A);
}

System.out.println("output");
System.out.println(l1);

Output:

[apple, orange, banana, strawberry]
[apple, orange]
output
[banana, strawberry]

Solution 11 - Java

I was looking for a different problem and came across this, so I will add my solution to a related problem: comparing two Maps.

    // make a copy of the data
	Map<String,String> a = new HashMap<String,String>(actual);
	Map<String,String> e = new HashMap<String,String>(expected);
    // check *every* expected value
	for(Map.Entry<String, String> val : e.entrySet()){
        // check for presence
		if(!a.containsKey(val.getKey())){
			System.out.println(String.format("Did not find expected value: %s", val.getKey()));
		}
        // check for equality
		else{
            if(0 != a.get(val.getKey()).compareTo(val.getValue())){
                System.out.println(String.format("Value does not match expected: %s", val.getValue()));
            }
            // we have found the item, so remove it 
            // from future consideration. While it 
            // doesn't affect Java Maps, other types of sets
            // may contain duplicates, this will flag those
            // duplicates. 
			a.remove(val.getKey());
		}
	}
    // check to see that we did not receive extra values
	for(Map.Entry<String,String> val : a.entrySet()){
        System.out.println(String.format("Found unexpected value: %s", val.getKey()));
	}

It works on the same principle as the other solutions but also compares not only that values are present, but that they contain the same value. Mostly I've used this in accounting software when comparing data from two sources (Employee and Manager entered values match; Customer and Corporate transactions match; ... etc)

Solution 12 - Java

Set is a map underneath i was able to get the diff between two list over a million entries each wrapping it in a HashSet this is a simple code to do it.

private List<String>notPresentMethod(final List<String>left,final List<String>right){
    final Set<String>setIsFaster = new HashSet<>(right);
    return left.stream()
            .filter(((Predicate<String>)setIsFaster::contains).negate())
            .collect(Collectors.toList());
}

Using only list took over a hour and did not complete. And using this sample took Just seconds.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRory LesterView Question on Stackoverflow
Solution 1 - JavaPablo Santa CruzView Answer on Stackoverflow
Solution 2 - JavaDenis LukenichView Answer on Stackoverflow
Solution 3 - JavajustMeView Answer on Stackoverflow
Solution 4 - JavaMilton Jacomini NetoView Answer on Stackoverflow
Solution 5 - JavacontrapostView Answer on Stackoverflow
Solution 6 - Javags manishaView Answer on Stackoverflow
Solution 7 - JavaIskuskov AlexanderView Answer on Stackoverflow
Solution 8 - JavafuatView Answer on Stackoverflow
Solution 9 - JavaValentyn KolesnikovView Answer on Stackoverflow
Solution 10 - Javamadhu sairam gunnamView Answer on Stackoverflow
Solution 11 - JavaJefferey CaveView Answer on Stackoverflow
Solution 12 - JavachiperortizView Answer on Stackoverflow