Java Compare Two List's object values?

JavaListArraylist

Java Problem Overview


I have two list *ListA<MyData> listA = new ArrayList<MyData>()* and ListB<MyData> listB = new ArrayList<MyData>() both contain object of type MyData and MyData contain these variables.

MyData {
    String name;
    boolean check;
} 

ListA and ListB both contains MyData objects ,now I have to compare both the list's object values here name as well check variable like if ListA contains these object values

ListA = ["Ram",true],["Hariom",true],["Shiv",true];

and ListB also contain

ListB = ["Ram",true],["Hariom",true],["Shiv",true];

then i have to compare lists and return false because both list are same But if ListA contains

ListA = ["Ram",true],["Hariom",true],["Shiv",false];

and ListB Contain

 ListB = ["Ram",true],["Hariom",true],["Shiv",true];

then I have to compare lists and return true because both list are not same

or vice-versa so any slight change in the any list values I have to return true. One thing I have to mentioned here objects can be in any order.

Java Solutions


Solution 1 - Java

It's not the most efficient solution but the most terse code would be:

boolean equalLists = listA.size() == listB.size() && listA.containsAll(listB);

Update:

@WesleyPorter is right. The solution above will not work if duplicate objects are in the collection.
For a complete solution you need to iterate over a collection so duplicate objects are handled correctly.

private static boolean cmp( List<?> l1, List<?> l2 ) {
    // make a copy of the list so the original list is not changed, and remove() is supported
	ArrayList<?> cp = new ArrayList<>( l1 );
	for ( Object o : l2 ) {
		if ( !cp.remove( o ) ) {
			return false;
		}
	}
	return cp.isEmpty();
}

Update 28-Oct-2014:

@RoeeGavriel is right. The return statement needs to be conditional. The code above is updated.

Solution 2 - Java

ArrayList already have support for this, with the equals method. Quoting the docs

> ... > In other words, two lists are defined to be equal if they contain the same elements in the same order.

It does require you to properly implement equals in your MyData class.

Edit

You have updated the question stating that the lists could have different orders. In that case, sort your list first, and then apply equals.

Solution 3 - Java

I got this solution for above problem

public boolean compareLists(List<MyData> prevList, List<MyData> modelList) {
		if (prevList.size() == modelList.size()) {
			for (MyData modelListdata : modelList) {
				for (MyData prevListdata : prevList) {
					if (prevListdata.getName().equals(modelListdata.getName())
							&& prevListdata.isCheck() != modelListdata.isCheck()) {
						return  true;
						 
					}
				}
				 
			}
		}
		else{
			return true;
		}
		return false; 

	}

EDITED:-
How can we cover this... Imagine if you had two arrays "A",true "B",true "C",true and "A",true "B",true "D",true. Even though array one has C and array two has D there's no check that will catch that(Mentioned by @Patashu)..SO for that i have made below changes.

public boolean compareLists(List<MyData> prevList, List<MyData> modelList) {
   		if (prevList!= null && modelList!=null && prevList.size() == modelList.size()) {
   			boolean indicator = false;
   			for (MyData modelListdata : modelList) {
   				for (MyData prevListdata : prevList) {
   					if (prevListdata.getName().equals(modelListdata.getName())
   							&& prevListdata.isCheck() != modelListdata.isCheck()) {
   						return  true;
   						 
   					}
   					if (modelListdata.getName().equals(prevListdata.getName())) {
						indicator = false;
						break;
					} else
						indicator = true;
				}
   				}
   				 
   			}
   		if (indicator)
			return true;
	}
   		}
   		else{
   			return true;
   		}
   		return false; 
   
   	}

Solution 4 - Java

First, implement the MyData.equals(Object o) and MyData.hashCode() methods. Once you implemented the equals method, you can iterate over the lists as follows:

if(ListA == null && ListB == null)
    return false;
if(ListA == null && ListB != null)
    return true;
if(ListA != null && ListB == null)
    return true;
int max = ListA.size() > ListB.size() ? ListA.size() : ListB.size();
for(int i = 0; i < max; i++) {
    myData1 = ListA.get(i);
    myData2 = ListB.get(i);
    if(!myData1.equals(myData2)) {
        return true;
    }
}
return false;
    

Solution 5 - Java

I found a very basic example of List comparison at List Compare This example verifies the size first and then checks the availability of the particular element of one list in another.

Solution 6 - Java

Override the equals method in your class and use Collection#equals() method to check for equality.

Solution 7 - Java

You can subtract one list from the other using CollectionUtils.subtract, if the result is an empty collection, it means both lists are the same. Another approach is using CollectionUtils.isSubCollection or CollectionUtils.isProperSubCollection.

For any case you should implement equals and hashCode methods for your object.

Solution 8 - Java

Using java 8 removeIf to compare similar items

public int getSimilarItems(){
    List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
    List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
    int initial = two.size();

    two.removeIf(one::contains);
    return initial - two.size();
}

Solution 9 - Java

This can be done easily through Java8 using forEach and removeIf method.

Take two lists. Iterate from listA and compare elements inside listB

Write any condition inside removeIf method.

Hope this will help

listToCompareFrom.forEach(entity -> listToRemoveFrom.removeIf(x -> x.contains(entity)));
 

Solution 10 - Java

Logic should be something like:

  1. First step: For class MyData implements Comparable interface, override the compareTo method as per the per object requirement.

  2. Second step: When it comes to list comparison (after checking for nulls), 2.1 Check the size of both lists, if equal returns true else return false, continue to object iteration 2.2 If step 2.1 returns true, iterate over elements from both lists and invoke something like,

    listA.get(i).compareTo(listB.get(i))

This will be as per the code mentioned in step-1.

Solution 11 - Java

See if this works.

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


public class ArrayListComparison {

	public static void main(String[] args) {
		List<MyData> list1 = new ArrayList<MyData>();
		list1.add(new MyData("Ram", true));
		list1.add(new MyData("Hariom", true));
		list1.add(new MyData("Shiv", true));
//		list1.add(new MyData("Shiv", false));
		List<MyData> list2 = new ArrayList<MyData>();
		list2.add(new MyData("Ram", true));
		list2.add(new MyData("Hariom", true));
		list2.add(new MyData("Shiv", true));
		
		System.out.println("Lists are equal:" + listEquals(list1, list2));
	}

	private static boolean listEquals(List<MyData> list1, List<MyData> list2) {
		if(list1.size() != list2.size())
			return true;
		for (MyData myData : list1) {
			if(!list2.contains(myData))
				return true;
		}
		return false;
	}
}

class MyData{
	String name;
	boolean check;
	
	
	public MyData(String name, boolean check) {
		super();
		this.name = name;
		this.check = check;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (check ? 1231 : 1237);
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MyData other = (MyData) obj;
		if (check != other.check)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
} 

Solution 12 - Java

It's been about 5 years since then and luckily we have Kotlin now.
Comparing of two lists now looks is as simple as:

fun areListsEqual(list1 : List<Any>, list2 : List<Any>) : Boolean {
        return list1 == list2
}

Or just feel free to omit it at all and use equality operator.

Solution 13 - Java

I know it's old question but in case anyone needs it. I use this in my application and it works well. i used it to check if the cart has been changed or not.

private boolean validateOrderProducts(Cart cart) {
    boolean doesProductsChanged = false;
    if (originalProductsList.size() == cart.getCartItemsList().size()) {
        for (Product originalProduct : originalProductsList) {
            if (!doesProductsChanged) {
                for (Product cartProduct : cart.getCartProducts()) {
                    if (originalProduct.getId() == cartProduct.getId()) {
                        if (originalProduct.getPivot().getProductCount() != cartProduct.getCount()) {
                            doesProductsChanged = true;
                            // cart has been changed -> break from inner loop
                            break;
                        }
                    } else {
                        doesProductsChanged = false;
                    }
                }
            } else {
                // cart is already changed -> break from first loop
                break;
            }
        }
    } else {
        // some products has been added or removed (simplest case of Change)
        return true;
    }
    return doesProductsChanged;
}

Solution 14 - Java

String myData1 = list1.toString();
String myData2 = list2.toString()

return myData1.equals(myData2);

where :
list1 - List<MyData>
list2 - List<MyData>

Comparing the String worked for me. Also NOTE I had overridden toString() method in MyData class.

Solution 15 - Java

I think you can sort both lists and convert to List if some of them was a HashSet colleciton.

java.utils.Collections package lets you do it.

List<Category> categoriesList = new ArrayList<>();
Set<Category> setList = new HashSet<>();
Collections.sort(categoriesList);
List<Category> fileCategories = new ArrayList<>(setList);
Collections.sort(fileCategories);
	
if(categoriesList.size() == fileCategories.size() && categoriesList.containsAll(fileCategories)) {
	//Do something
}

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
Questionuser2309806View Question on Stackoverflow
Solution 1 - JavaOded PeerView Answer on Stackoverflow
Solution 2 - JavaNilsHView Answer on Stackoverflow
Solution 3 - Javauser2309806View Answer on Stackoverflow
Solution 4 - JavaAmir KostView Answer on Stackoverflow
Solution 5 - JavaManoj KumarView Answer on Stackoverflow
Solution 6 - JavaAllTooSirView Answer on Stackoverflow
Solution 7 - JavaLuiz Feijão VeronesiView Answer on Stackoverflow
Solution 8 - JavaAsanka SiriwardenaView Answer on Stackoverflow
Solution 9 - JavaShubham ChaudharyView Answer on Stackoverflow
Solution 10 - JavaHimanshu BhardwajView Answer on Stackoverflow
Solution 11 - JavakrishnakumarpView Answer on Stackoverflow
Solution 12 - JavaLeonid UstenkoView Answer on Stackoverflow
Solution 13 - JavaMohamed NagehView Answer on Stackoverflow
Solution 14 - Javaabc123View Answer on Stackoverflow
Solution 15 - JavaSky Games IncView Answer on Stackoverflow