Java比较两个List的对象值?
Posted
技术标签:
【中文标题】Java比较两个List的对象值?【英文标题】:Java Compare Two List's object values? 【发布时间】:2013-04-18 22:22:50 【问题描述】:我有两个列表 **ListA<MyData> listA = new ArrayList<MyData>()
** 和 ListB<MyData> listB = new ArrayList<MyData>()
都包含 MyData 类型的对象,而 MyData 包含这些变量。
MyData
String name;
boolean check;
ListA 和 ListB 都包含 MyData 对象,现在我必须在这里比较列表的对象值 name 以及 check 变量,例如 if ListA 包含这些对象值
ListA = ["Ram",true],["Hariom",true],["Shiv",true];
和 ListB 也包含
ListB = ["Ram",true],["Hariom",true],["Shiv",true];
然后我必须比较列表并返回 false,因为两个列表相同 但如果 ListA 包含
ListA = ["Ram",true],["Hariom",true],["Shiv",false];
和ListB包含
ListB = ["Ram",true],["Hariom",true],["Shiv",true];
然后我必须比较列表并返回 true,因为两个列表不相同
或反之亦然,因此任何列表值的任何细微变化都必须返回 true。 我必须在这里提到的一件事,对象可以按任何顺序排列。
【问题讨论】:
我无法区分上述任何一个列表。 对象值被改变一个对象包含真另一个假 @askkuber 你是否关心两个列表的顺序,例如应该迭代它们总是给出相同的结果吗?如果没有,只需使用Set<MyData>
,例如HashSet
, implement equals()
and hashCode()
on MyData
并将两组与 setA.equals(setB)
进行比较。
@Philipp 列表包含任何顺序的对象,我必须比较它们并在发现任何单个更改时返回 true
我建议通过一个好的 hashCode()
实现对它们进行排序,然后比较成对的元素,看看它们是否相等。
【参考方案1】:
这不是最有效的解决方案,但最简洁的代码是:
boolean equalLists = listA.size() == listB.size() && listA.containsAll(listB);
更新:
@WesleyPorter 是对的。如果集合中有重复的对象,上述解决方案将不起作用。 要获得完整的解决方案,您需要对集合进行迭代,以便正确处理重复的对象。
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();
2014 年 10 月 28 日更新:
@RoeeGavriel 是对的。 return 语句必须是有条件的。以上代码已更新。
【讨论】:
此解决方案不适用于某些极端情况。例如,如果 listA = ["1", "blah", "1", "4"] 和 listB = ["1", "blah", "blah", "4"],则该方法将返回 true,当这两个列表确实不同。 如果 L1 拥有 L2 的所有项目以及更多项目(L1="1","2","3" & L2="1","2"),则更新将失败并返回 true .如果您将最后一条语句更改为return (cp.size()==0);
,它将起作用
时间复杂度:O(n^2) !
对于更复杂的 java 对象,我们是否需要覆盖 hashcode()
才能使其工作?【参考方案2】:
ArrayList
已经支持此功能,使用 equals
方法。引用the docs
... 换句话说,如果两个列表以相同的顺序包含相同的元素,则它们被定义为相等。
它确实需要您在 MyData
类中正确实现 equals
。
编辑
您已更新问题,指出列表可能有不同的顺序。在这种情况下,请先对列表进行排序,然后应用等于。
【讨论】:
他的一个要求是对象可以是任意顺序。 是的,它现在这么说。但不是当我写答案时。 这是最好的答案! 这在我overwrite
对象中的equals方法之后起作用【参考方案3】:
我得到了解决上述问题的方法
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;
已编辑:- 我们怎么能覆盖这个... 想象一下,如果你有两个数组“A”,真“B”,真“C”,真和“A”,真“B”,真“D”,真。即使数组 1 有 C 并且数组 2 有 D 也没有检查会发现(@Patashu 提到)..所以我做了以下更改。
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;
【讨论】:
如果列表具有相同的对象但无序,这将不起作用。 @Patashu 未测试,但它会工作,因为我有两个 for 循环 只要列表始终具有相同的名称,您的算法就应该没问题。没有检查他们是否有不同的名字,只是名字的数量不同。 但它对我有用,你能详细说明它不适用的标准吗? 想象一下如果你有两个数组"A",true "B",true "C",true and "A",true "B",true "D",true
。即使数组 1 有 C 并且数组 2 有 D 也没有检查可以捕捉到它。如果这种情况永远不会发生,那么您的代码就可以,如果可以,您的代码就不行。【参考方案4】:
首先,实现MyData.equals(Object o)
和MyData.hashCode()
方法。
实现 equals
方法后,您可以按如下方式遍历列表:
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;
【讨论】:
始终实现equals()
和 hashCode()
-- 只实现其中一个可能会丢失集合中的元素或完全破坏集合。【参考方案5】:
我在List Compare 找到了一个非常基本的列表比较示例 此示例首先验证大小,然后检查一个列表的特定元素在另一个列表中的可用性。
【讨论】:
【参考方案6】:覆盖类中的equals 方法并使用Collection#equals() 方法检查是否相等。
【讨论】:
始终实现equals()
和 hashCode()
-- 只实现其中一个可能会丢失集合中的元素或完全破坏集合。【参考方案7】:
您可以使用 CollectionUtils.subtract 从另一个列表中减去一个列表,如果结果是一个空集合,则意味着两个列表相同。另一种方法是使用 CollectionUtils.isSubCollection 或 CollectionUtils.isProperSubCollection。
在任何情况下,您都应该为您的对象实现 equals 和 hashCode 方法。
【讨论】:
【参考方案8】:使用java 8 removeIf比较相似的项目
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();
【讨论】:
【参考方案9】:这可以通过 Java8 使用 forEach 和 removeIf 方法轻松完成。
取两个列表。从 listA 迭代并比较 listB
中的元素在 removeIf 方法中写入任何条件。
希望这会有所帮助
listToCompareFrom.forEach(entity -> listToRemoveFrom.removeIf(x -> x.contains(entity)));
【讨论】:
【参考方案10】:逻辑应该是这样的:
第一步:对于MyData类实现Comparable接口,根据每个对象的要求重写compareTo方法。
第二步:列表比较时(检查空值后), 2.1 检查两个列表的大小,如果相等返回true,否则返回false,继续对象迭代 2.2 如果步骤 2.1 返回 true,则遍历两个列表中的元素并调用类似的东西,
listA.get(i).compareTo(listB.get(i))
这将按照步骤 1 中提到的代码。
【讨论】:
【参考方案11】:看看这是否有效。
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;
【讨论】:
【参考方案12】:从那时起已经过去了大约 5 年,幸运的是我们现在有了 Kotlin。 现在比较两个列表看起来很简单:
fun areListsEqual(list1 : List<Any>, list2 : List<Any>) : Boolean
return list1 == list2
或者完全忽略它并使用相等运算符。
【讨论】:
【参考方案13】:我知道这是个老问题,但以防万一有人需要。我在我的应用程序中使用它并且效果很好。我用它来检查购物车是否已更改。
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;
【讨论】:
【参考方案14】:String myData1 = list1.toString();
String myData2 = list2.toString()
return myData1.equals(myData2);
where :
list1 - List<MyData>
list2 - List<MyData>
比较字符串对我有用。另请注意,我在 MyData 类中重写了 toString() 方法。
【讨论】:
【参考方案15】:如果其中一些是 HashSet 集合,我认为您可以对这两个列表进行排序并转换为 List。
java.utils.Collections 包让您可以做到。
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
【讨论】:
以上是关于Java比较两个List的对象值?的主要内容,如果未能解决你的问题,请参考以下文章
java反射反射实现判断发生了修改操作,判断两个对象是否发生属性值的变更,判断两个List集合内对象的属性值是否发生变更