Java中两个基本类型,比如说两个整型非常容易判断其是否相等,那么如果是两个List的实例呢?
测试代码
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
List<Integer> list3 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list2.add(1);
list2.add(2);
list2.add(3);
list3.add(4);
list3.add(5);
System.out.println(list1.equals(list2));
System.out.println(list1.equals(list3));
代码中创建了3个List的实例:list1、list2、list3,其中前两者的内部的内容是相同的,且都与list3不同。初始化完几个list实例后,判断list1与list2和list1与list3分别是否相等。
输出:
true
false
说明,在Java中,List
的equals()
方法,是根据list实例内的内容来进行判断的,而不是简单的”不是同一个引用对象即判false”。
解释
让我们看一下List
的equals()
方法的注释:
/**
* Compares the specified object with this list for equality. Returns
* <tt>true</tt> if and only if the specified object is also a list, both
* lists have the same size, and all corresponding pairs of elements in
* the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and
* <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
* e1.equals(e2))</tt>.) In other words, two lists are defined to be
* equal if they contain the same elements in the same order. This
* definition ensures that the equals method works properly across
* different implementations of the <tt>List</tt> interface.
*
* @param o the object to be compared for equality with this list
* @return <tt>true</tt> if the specified object is equal to this list
*/
boolean equals(Object o);
从注释里可以看到,判断两个List实例相等,当且仅当:
- 两个list的
size()
相同,即大小相同 - 在两个list中,每一个对应元素都要相等(注:这里判断两个元素e1和e2相等的方法为:
e1==null ? e2==null : e1.equals(e2)
,即两个元素要么同为null,要么调用e1.equals(e2)
判断两者相等)
换句话说,总结起来就是,两个列表必须按相同顺序储存了同样的元素。
源码
由于List是一个接口,其实现代码不会在List.java中,而继承List接口的类又有很多,所以equals
方法的具体实现放在了抽象类AbstractList.java
中,而其它具体的类,如ArrayList、LinkedList等,便继承这个AbstractList类,来使用其中定义的方法。
在AbstractList中的equals
方法的定义如下:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
在源码中,我们可以看到,首先判断输入的参数Object o中的o是否是一个实现了List接口的类的实例,若不是,则直接返回false。
然后,对于两个List的实例,获取其迭代器e1、e2,之后,利用迭代器,每次取两个迭代器的下一个元素,并递归地调用元素的equals
方法判断这两个元素是否相等,若不相等,则返回false。
最后,看两个迭代器是否同时遍历完,若同时遍历完,则返回true,否则,返回false。在这里,是用这种方法比较两者的大小是否相等。