【问题标题】:Handle differences between two arraylists处理两个数组列表之间的差异
【发布时间】:2014-11-20 16:25:52
【问题描述】:

我的问题是我要比较 Java 中的两个数组列表

例如

String prop1 = "String"
String prop2 = "OtherString"
MyObject obj1 = new MyObject(prop1,prop2);
MyObject obj2 = new MyObject(prop1,prop2);
MyObject obj3= new MyObject(prop1,prop2);

ArrayList<MyObject> array1 = new Arraylist<>();
ArrayList<MyObject> array2 = new Arraylist<>();
//array 1 has 3 objects
array1.add(obj1);array1.add(obj2);array1.add(obj3);
//array 2 has 2 objects
array2.add(obj1);array2.add(obj2);

通过比较方法我知道这些数组是不同的

(如果数组具有相同的元素,即使它们的顺序不同,我的方法返回false,如果它们具有相同的元素,则返回true)

所以,该方法将返回 FALSE

我的问题是:

if(!methodToCompareArrays(array1,array2)){
    //HOW TO GET THE DIFFERENT objects (IN THIS CASE, obj3 is the different object)
    //this is the question :)
}else{
    //If there is no difference, well, it doesn't matter too much

请注意,我将在这些数组列表中添加多个对象,并且方法效率也很重要(不是关键,但至少很重要)。我已经看到了答案here 但我不确定哪个更好或更差

提前致谢。

【问题讨论】:

  • methodToCompareArrays 至少已经为你做了一些吗?
  • 在我看来,Symmetric Difference 就是您正在寻找的...看看 Apache Commons CollectionUtil disjunction function
  • 它首先比较arraylists的大小,所以在这种情况下它会返回false。我的方法是基于 DiddiZ 的回答 here
  • (array1,array2)的答案应该是什么,与(array2,array1)的答案应该是什么?两个集合中都可以有不同的对象(即,一个对象存在于另一个对象中);在这种情况下,您到底在寻找什么?
  • 在这两种情况下,答案都应该是“object3”,并且可能是(存在于一个中的对象不在另一个中),但更有可能是一个数组具有所有objects,另一个数组包含除三个或五个之外的所有对象。

标签: java arraylist


【解决方案1】:

您可能应该为此使用 java 的 set interfaces

现在,一件很重要的事情是在MyObject 上拥有一个好的equals 方法,以便能够比较两个MyObjects 是否相同。

然后您可以使用上面的文档链接来检查两组的交集。如果两组中的项目与一组中的项目数量相同,则它们是同一组(不考虑顺序)。

HashSet<MyObject> set1 = new HashSet<MyObject>(array1);
HashSet<MyObject> set2 = new HashSet<MyObject>(array2);

Set<MyObject> intersection = new HashSet<MyObject>(set1);
intersection.retainAll(set2);

if(intersection.size() == set2.size()) { 
    // They're the same.
} else { 
    HashSet<MyObject> itemsOnlyInSet1 = intersection;
    HashSet<MyObject> itemsOnlyInSet2 = set2.retainAll(set1);
} 

【讨论】:

  • 如果 OP 已经有 ArrayLists,我不确定是否值得从每个创建 Sets 来进行比较。如果有很多项目(数千?数万或数十万?我不确定),那将是值得的,但这听起来不像基于 OP 描述的规模......
  • 如果我应该将“Type”替换为“MyObject”,我不太明白(也许这个评论很无聊)。 @Tim 好吧,我不希望有数千,也许一百或更少。
  • 对于一百个或更少的集合,使用这种方法(Sets)应该就可以了。 @Tim 是对的,如果项目的数量真的很大,这可能不是最好的方法,但少于一百并不是真的很大。此外,集合具有去重的优点;数组列表可让您将多个相同项目填充到数组中。采用这些数组:{1, 2, 2, 3} 和 {1, 3}。左侧列表中不在右侧的项目应该是 {2},而不是 {2, 2}。这是为您设置的,而不是列表。
  • 哦,还有 OP——是的,我更新了答案。我对 Type 的使用是错误的。应该是 MyObject。
  • 我实际上是在说相反的:找到两个 HashSet 的析取将比找到两个 ArrayList 的析取更有效(N log N 与 N^2),因此 FrobberOfBits 的建议成为更好的选择元素数量增加。但是 N 需要相对较大才能真正看到实践中的差异,并且从每个 ArrayList 创建一个新的 HashSet 只是为了获得一个小的改进是不值得的,因为制作新的 HashSet 然后进行垃圾收集是有成本的他们。但是对于非常大的 N 来说,这是值得的......
【解决方案2】:

我不确定我是否理解您的问题,但如果您尝试比较和排序对象列表,最好的选择是从 Collections API 中查找 TreeMaps。试试这个:

Difference between HashMap, LinkedHashMap and TreeMap

【讨论】:

  • 我在 OP 的帖子中没有看到任何关于排序的参考,也没有看到任何需要 Map 而不是简单的元素集合的东西......
  • 我从来没有说过提到“排序”。请再读一遍我写的。我猜想是因为他想比较一个对象列表,他可能有兴趣对它们进行排序。我认为我的帖子中没有任何内容可以反对。
  • 另外,他似乎有两个字段'prop1'和'prop2'。如果他通过比较其中一个字段来实现他的比较方法,那么他不妨研究使用键值对的映射。然后他可以使用他的比较字段作为地图中的键。
【解决方案3】:

如果这些列表中的对象对您来说并不重要,您可以执行以下操作:

array1.removeAll(array2);

这将从array1中删除array2中存在的所有元素。

所以如果 array1 = [obj1, obj2, obj3] 并且 array2 = [obj1, obj2]

removeAll 之后:

array1 = [obj3] 和 array2 = [obj1, obj2]

如果您无法从任一列表中删除对象,则创建一个临时列表并从那里删除以获得额外的对象。

【讨论】:

  • 使用 OP 的新信息,即希望收集一个中的所有元素而不是另一个中的所有元素,您需要更新您的答案以说明 array2 中不在 array1 中的任何内容。而且您将无法再就地执行此操作...
猜你喜欢
  • 2016-06-03
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 2020-05-30
  • 2016-07-21
  • 1970-01-01
相关资源
最近更新 更多