比较数组并获得差异

时间:2010-08-01 01:03:14

标签: java arrays compare

我如何比较两个可能具有不同长度的数组并获得每个数组之间的差异?

例如:

Cat cat = new Cat();
Dog dog = new Dog();
Alligator alligator = new Alligator();

Animal animals[] = { cat, dog };
Animal animals2[] = { cat, dog, alligator };

我如何将它们与两个数组进行比较并使其返回Alligator的实例?

5 个答案:

答案 0 :(得分:5)

我建议您的问题需要澄清。目前,每个人都在猜测你实际要问的是什么。

  • 数组是否用于表示集合,列表或其中的某些内容?换句话说,元素顺序是否重要,并且可能存在重复吗?
  • “平等”是什么意思? new Cat()“等于”new Cat()吗?你的例子暗示它确实!!
  • “差异”是什么意思?你的意思是设定差异吗?
  • 如果两个数组的长度相同,您希望发生什么?
  • 这是一次性比较还是对同一个数组重复出现?
  • 阵列中有多少个元素(平均)?
  • 你为什么要使用数组呢?

假设这些数组是真正的集合,那么您可能应该使用HashSet而不是数组,并使用addAllretainAll等集合操作来计算设定差异。

另一方面,如果数组用于表示列表,那么“差异”意味着什么并不清楚。

如果代码运行速度很快,那么您肯定需要重新考虑数据结构。如果你总是从数组开始,你将无法快速计算“差异”...至少在一般情况下。

最后,如果你打算使用任何依赖于equals(Object)方法的东西(包括任何Java集合类型,你真的需要清楚地理解“equals”应该是什么意思在你的应用程序中。所有Cat实例是否相等?它们是否都不同?某些Cat实例是否相等而其他实例是否相同?如果你没有想到这一点,那就实现equals和因此,hashCode方法会让您感到困惑。

答案 1 :(得分:1)

好吧,您可以改用Set并使用removeAll()方法。

或者您可以使用以下简单和慢速算法:

List<Animal> differences = new ArrayList<Animal>();

    for (Animal a1 : animals) {
       boolean isInSecondArray = false;
       for (Animal a2 : animals2) {
           if (a1 == a2)  {
                isInSecondArray = true;
                break;
           }
       } 

       if (!isInSecondArray)
           differences.add(a1)
    }

然后differences将包含animals数组中但不在animals2数组中的所有对象。以类似的方式,您可以执行相反的操作(获取animals2但不在animals中的所有对象。)

答案 2 :(得分:1)

我建议您将对象放入集合中,然后使用集合的交集:

// Considering you put your objects in setA and setB

Set<Object> intersection = new HashSet<Object>(setA);
intersection.retainAll(setB);

之后,你可以使用removeAll来改变两组中的任何一组:

setA.removeAll(intersection);
setB.removeAll(intersection);

灵感来自:http://hype-free.blogspot.com/2008/11/calculating-intersection-of-two-java.html

答案 3 :(得分:1)

您可能需要查看此文章以获取更多信息:

http://download-llnw.oracle.com/javase/tutorial/collections/interfaces/set.html

正如前面提到的那样,removeAll()就是这样做的,但是你需要做两次,这样你就可以创建两者中所有缺失的列表,然后你可以将这两个结果组合起来列出所有差异。

但是,这是一种破坏性操作,因此如果您不想丢失信息,请复制Set并对其进行操作。

<强>更新

看来我对数组中的内容的假设是错误的,所以removeAll()不起作用,但是要求5ms,依赖于要搜索的项目数可能是个问题。

因此,HashMap<String, Animal>似乎是最佳选择,因为搜索速度很快。

Animal是一个至少包含一个属性String name的接口。对于为AnimalEquals实现hashCode实现List<Object>的每个类。你可以在这里找到一些讨论:http://www.ibm.com/developerworks/java/library/j-jtp05273.html。这样,如果您希望哈希值是动物类型和名称的组合,那么就可以了。

因此,基本算法是将所有内容保存在哈希映射中,然后搜索差异,只获取一组键,然后搜索以查看该键是否包含在另一个列表中,如果它不是把它放入{{1}},将值存储在那里。 你会想要这样做两次,所以,如果你至少有一个双核处理器,你可以从两个搜索在不同的线程中完成获得一些好处,但是你会想要使用添加的并发数据类型之一在JDK5中,您不必担心组合差异列表中的同步。

所以,我会先把它作为单线程和测试来编写,以获得一些关于速度有多快的想法,同时将它与原始的implmemntation进行比较。 然后,如果您需要更快,请尝试使用线程,再次比较以查看是否有速度增加。

在进行任何优化之前,请确保您已经掌握了已有的指标,以便比较并查看一次更改是否会提高速度。

如果您一次进行太多更改,可能会在速度方面有很大改进,但其他可能导致性能下降,而且不会看到,这就是为什么每次更改应该是一次一个

不要丢失其他实现,通过使用单元测试和测试每次100次,您可以了解每个更改给您带来的改进。

答案 4 :(得分:0)

我不关心我的用法性能(你也不应该,除非你有充分的理由,并且你通过你的分析器发现这个代码是瓶颈)。

我所做的与功能性答案类似。我使用LINQ set运算符来获取每个列表的异常:

http://msdn.microsoft.com/en-us/library/bb397894.aspx

修改

抱歉,我没注意到这是Java。对不起,我在C#la-la的土地上,他们看起来非常相似:)