从源码分析:java中怎样判断List是否相等(euqlas()方法)

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中,Listequals()方法,是根据list实例内的内容来进行判断的,而不是简单的”不是同一个引用对象即判false”。

解释

让我们看一下Listequals()方法的注释:

       /**
     * 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。在这里,是用这种方法比较两者的大小是否相等。

原文地址:https://www.cnblogs.com/liulaolaiu/p/11744401.html