带你从源码理解List的equals方法
提出问题
我们希望创建List<List<intger>> lists
,不断往lists
中添加list
,但我们不希望出现重复的list
如何解决这个问题?
- 利用
List
中的contain
方法 - 利用
list
的equals
方法是元素逐一比较,而不是比较引用地址
源码解释
首先我们查看ArrayList
实现list接口
有contain
方法
里面调用了indexOf
方法,并且返回值大于等于0时,返回true
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
接着查看indexOf
方法
- 如果
o
为null
时,并在List
中找到同样为null
的数据,返回该坐标 - 如果
o
不为null时,并且利用对象o
的equals()
方法,找到相同的数据,返回该坐标 - 否则返回-1
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
这要看我们的类o
的equals
方法的是如何实现的:
- 根据引用地址
- 根据属性值
- 其他
List<List<intger>> lists
,所以我们要查看ArrayList
的equals
方法,是否是根据每个元素值来判断
- 如果是,对于
lists
,我们便可以利用contain
方法进行去重 - 如果不是,则不可以
通过查看源码我们发现在ArrayList
中并没有找到equals
方法,而是在继承的父类AbstractList
中实现
其源码为
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());
}
发现该类确实重写了equals方法,就是使用迭代器遍历两个List每个元素是否相等。 那么ArrayList调用equals方法就是元素进行比较了。
实现
我们创建两个list
对象,但是每个list
对象都存放相同的集合
public static void main(String[] args) {
List<List<Integer>> lists=new ArrayList<>();
List<Integer> list1=new ArrayList<>();
List<Integer> list2=new ArrayList<>();
list1.add(1);
list1.add(2);
list2.add(1);
list2.add(2);
lists.add(list1);
if(lists.contains(list2)){
System.out.println("已经存在该list");
}else {
lists.add(list2);
}
System.out.println(lists);
}
输出:
已经存在该list
[[1, 2]]