How can I calculate the difference between two ArrayLists?

JavaArraylist

Java Problem Overview


I have two ArrayLists.

ArrayList A contains:

['2009-05-18','2009-05-19','2009-05-21']
 

ArrayList B contains:

['2009-05-18','2009-05-18','2009-05-19','2009-05-19','2009-05-20','2009-05-21','2009-05-21','2009-05-22']

I have to compare ArrayList A and ArrayList B. The result ArrayList should contain the List which does not exist in ArrayList A.

ArrayList result should be:

['2009-05-20','2009-05-22']

how to compare ?

Java Solutions


Solution 1 - Java

In Java, you can use the Collection interface's removeAll method.

// Create a couple ArrayList objects and populate them
// with some delicious fruits.
Collection firstList = new ArrayList() {{
    add("apple");
    add("orange");
}};

Collection secondList = new ArrayList() {{
    add("apple");
    add("orange");
    add("banana");
    add("strawberry");
}};

// Show the "before" lists
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);

// Remove all elements in firstList from secondList
secondList.removeAll(firstList);

// Show the "after" list
System.out.println("Result: " + secondList);

The above code will produce the following output:

First List: [apple, orange]
Second List: [apple, orange, banana, strawberry]
Result: [banana, strawberry]

Solution 2 - Java

You already have the right answer. And if you want to make more complicated and interesting operations between Lists (collections) use apache commons collections (CollectionUtils) It allows you to make conjuction/disjunction, find intersection, check if one collection is a subset of another and other nice things.

Solution 3 - Java

In Java 8 with streams, it's pretty simple actually. EDIT: Can be efficient without streams, see lower.

List<String> listA = Arrays.asList("2009-05-18","2009-05-19","2009-05-21");
List<String> listB = Arrays.asList("2009-05-18","2009-05-18","2009-05-19","2009-05-19",
                                   "2009-05-20","2009-05-21","2009-05-21","2009-05-22");

List<String> result = listB.stream()
                           .filter(not(new HashSet<>(listA)::contains))
                           .collect(Collectors.toList());

Note that the hash set is only created once: The method reference is tied to its contains method. Doing the same with lambda would require having the set in a variable. Making a variable is not a bad idea, especially if you find it unsightly or harder to understand.

You can't easily negate the predicate without something like this utility method (or explicit cast), as you can't call the negate method reference directly (type inference is needed first).

private static <T> Predicate<T> not(Predicate<T> predicate) {
    return predicate.negate();
}

If streams had a filterOut method or something, it would look nicer.


Also, @Holger gave me an idea. ArrayList has its removeAll method optimized for multiple removals, it only rearranges its elements once. However, it uses the contains method provided by given collection, so we need to optimize that part if listA is anything but tiny.

With listA and listB declared previously, this solution doesn't need Java 8 and it's very efficient.

List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));

Solution 4 - Java

EDIT: Original question did not specify language. My answer is in C#.

You should instead use HashSet for this purpose. If you must use ArrayList, you could use the following extension methods:

var a = arrayListA.Cast<DateTime>();
var b = arrayListB.Cast<DateTime>();    
var c = b.Except(a);

var arrayListC = new ArrayList(c.ToArray());

using HashSet...

var a = new HashSet<DateTime>(); // ...and fill it
var b = new HashSet<DateTime>(); // ...and fill it
b.ExceptWith(a); // removes from b items that are in a

Solution 5 - Java

I have used Guava Sets.difference.

The parameters are sets and not general collections, but a handy way to create sets from any collection (with unique items) is Guava ImmutableSet.copyOf(Iterable).

(I first posted this on a related/dupe question, but I'm copying it here too since I feel it is a good option that is so far missing.)

Solution 6 - Java

Although this is a very old question in Java 8 you could do something like

 List<String> a1 = Arrays.asList("2009-05-18", "2009-05-19", "2009-05-21");
 List<String> a2 = Arrays.asList("2009-05-18", "2009-05-18", "2009-05-19", "2009-05-19", "2009-05-20", "2009-05-21","2009-05-21", "2009-05-22");

 List<String> result = a2.stream().filter(elem -> !a1.contains(elem)).collect(Collectors.toList());

Solution 7 - Java

I guess you're talking about C#. If so, you can try this

    ArrayList CompareArrayList(ArrayList a, ArrayList b)
    {
        ArrayList output = new ArrayList();
        for (int i = 0; i < a.Count; i++)
        {
            string str = (string)a[i];
            if (!b.Contains(str))
            {
                if(!output.Contains(str)) // check for dupes
                    output.Add(str);
            }
        }
        return output;
    }

Solution 8 - Java

You are just comparing strings.

Put the values in ArrayList A as keys in HashTable A.
Put the values in ArrayList B as keys in HashTable B.

Then, for each key in HashTable A, remove it from HashTable B if it exists.

What you are left with in HashTable B are the strings (keys) that were not values in ArrayList A.

C# (3.0) example added in response to request for code:

List<string> listA = new List<string>{"2009-05-18","2009-05-19","2009-05-21'"};
List<string> listB = new List<string>{"2009-05-18","2009-05-18","2009-05-19","2009-05-19","2009-05-20","2009-05-21","2009-05-21","2009-05-22"};

HashSet<string> hashA = new HashSet<string>();
HashSet<string> hashB = new HashSet<string>();

foreach (string dateStrA in listA) hashA.Add(dateStrA);
foreach (string dateStrB in listB) hashB.Add(dateStrB);

foreach (string dateStrA in hashA)
{
    if (hashB.Contains(dateStrA)) hashB.Remove(dateStrA);
}

List<string> result = hashB.ToList<string>();

Solution 9 - Java

Hi use this class this will compare both lists and shows exactly the mismatch b/w both lists.

import java.util.ArrayList;
import java.util.List;


public class ListCompare {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List<String> dbVinList;
		dbVinList = new ArrayList<String>();
		List<String> ediVinList;
		ediVinList = new ArrayList<String>();			
						
		dbVinList.add("A");
		dbVinList.add("B");
		dbVinList.add("C");
		dbVinList.add("D");
		
		ediVinList.add("A");
		ediVinList.add("C");
		ediVinList.add("E");
		ediVinList.add("F");
		/*ediVinList.add("G");
		ediVinList.add("H");
		ediVinList.add("I");
		ediVinList.add("J");*/	
		
		List<String> dbVinListClone = dbVinList;
		List<String> ediVinListClone = ediVinList;
		
		boolean flag;
		String mismatchVins = null;
		if(dbVinListClone.containsAll(ediVinListClone)){
			flag = dbVinListClone.removeAll(ediVinListClone);	
			if(flag){
				mismatchVins = getMismatchVins(dbVinListClone);
			}
		}else{
			flag = ediVinListClone.removeAll(dbVinListClone);
			if(flag){
				mismatchVins = getMismatchVins(ediVinListClone);
			}
		}
		if(mismatchVins != null){
			System.out.println("mismatch vins : "+mismatchVins);
		}		

	}
	
	private static String getMismatchVins(List<String> mismatchList){
		StringBuilder mismatchVins = new StringBuilder();
		int i = 0;
		for(String mismatch : mismatchList){
			i++;
			if(i < mismatchList.size() && i!=5){
				mismatchVins.append(mismatch).append(",");	
			}else{
				mismatchVins.append(mismatch);
			}
			if(i==5){				
				break;
			}
		}
		String mismatch1;
		if(mismatchVins.length() > 100){
			mismatch1 = mismatchVins.substring(0, 99);
		}else{
			mismatch1 = mismatchVins.toString();
		}		
		return mismatch1;
	}

}

Solution 10 - Java

THIS WORK ALSO WITH Arraylist

	// Create a couple ArrayList objects and populate them
	// with some delicious fruits.
	ArrayList<String> firstList = new ArrayList<String>() {/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

	{
	    add("apple");
	    add("orange");
	    add("pea");
	}};

	ArrayList<String> secondList = new ArrayList<String>() {

	/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

	{
	    add("apple");
	    add("orange");
	    add("banana");
	    add("strawberry");
	}};

	// Show the "before" lists
	System.out.println("First List: " + firstList);
	System.out.println("Second List: " + secondList);

	// Remove all elements in firstList from secondList
	secondList.removeAll(firstList);

	// Show the "after" list
	System.out.println("Result: " + secondList);

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
QuestionnaveenView Question on Stackoverflow
Solution 1 - JavaWilliam BrendelView Answer on Stackoverflow
Solution 2 - JavaandriiView Answer on Stackoverflow
Solution 3 - JavaVlasecView Answer on Stackoverflow
Solution 4 - JavaJoshView Answer on Stackoverflow
Solution 5 - JavaPeter LambergView Answer on Stackoverflow
Solution 6 - JavajesantanaView Answer on Stackoverflow
Solution 7 - JavaPavelsView Answer on Stackoverflow
Solution 8 - JavaDemiView Answer on Stackoverflow
Solution 9 - JavaRaj MohamadView Answer on Stackoverflow
Solution 10 - JavapsychoView Answer on Stackoverflow