ArrayList的indexOf方法与重写equals方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList的indexOf方法与重写equals方法相关的知识,希望对你有一定的参考价值。

参考技术A 如上,每次调用heros.indexOf(h)都返回0索引,怀疑人生??
然后看heros是用List接口进行多态调用的,所以,indexOf是在子类或实现类 即 ArrayList中实现:

看到这里还是没反应过来,然后百度了一下,猛地想起了Hero类中好像重写了equals方法:

这个equals确实写的有问题。
而heros.indexOf(h) 这一句,涉及到两个多态调用:
1.heros调用了 ArrayList 实现了接口 List 中的indexOf()方法
2.在调用indexOf()时,又调用了 Hero 类自己的 equals 方法

另外:
it.remove(); 这一句:
it.next() 方法中首先调用了checkForComodification方法,该方法会判断modCount是否等于
expectedModCount,不等于就会抛出java.util.ConcurrentModificationExcepiton异常
modCount是ArrayList的一个属性,继承自抽象类AbstractList,用于表示ArrayList对象
被修改次数在iterator.remove()方法中,同样调用了ArrayList自身的remove方法,但是调用完之后
并非就return了,而是expectedModCount = modCount重置了expectedModCount值,使二
者的值继续保持相等。
针对forEach循环并没有修复方案,因此在遍历过程中同时需要修改ArrayList对象,则需
要采用iterator遍历
上面提出的解决方案调用的是iterator.remove()方法,如果不仅仅是想调用remove方法
移除元素,还想增加元素,或者替换元素,是否可以呢?浏览Iterator源码可以发现这是
不行的,Iterator只提供了remove方法。
但是ArrayList实现了ListIterator接口,ListIterator类继承了Iter,这些操作都是可以实现的
ListIterator<Integer> iterator = myArrayList.listIterator();

Arraylist中contains方法底层实现解读与HashSet自定义类型去重效果的简述(接上一篇)

Arraylist中contains方法底层实现解读(接上一篇)

上一篇最后提到Arraylist中contains方法里面有用到equals方法的地方,而且在自定义类中,如果不重写equals方法会导致就算一样也会false,所以这次我们来解决这个问题。首先我们现看Arraylist中contains方法里面有用到equals方法的地方:

int indexOfRange(Object o, int start, int end) {//o为传进来要比较的元素或自定义对象,start为0,end为Arraylist元素个数
    Object[] es = elementData;
    if (o == null) {							//不为空不进入
        for (int i = start; i < end; i++) {
            if (es[i] == null) {
                return i;
            }
        }
    } else {									//进入
        for (int i = start; i < end; i++) {		//进入
            if (o.equals(es[i])) {				//传进的元素或对象与es数组中各个元素或者对象比较,若为String类型则调用												  String中equals方法进行判断,若为自定类型,则调用Object中equals方													  法进行判断,下面将详细介绍比较原理。
                return i;						//若通过判断则返回下标。也就是最后返回true,表示含有改元素或对象。
            }
        }
    }
    return -1;
}
String类型equals比较原理:
String a = "aa";				
String str = new String("aa");
"a".equals("a");
System.out.println(a==str);
public boolean equals(Object anObject) {
    if (this == anObject) {//一个String类型元素调用,则this就为该元素,传进来的参数是后边"a",首先比较两个元素的内存地址,相等就返回true,一般不像str那样new对象的话,一般都会指向常量池统一内存地址,直接返回true,若new了新对象,则不进入本语句,进入下一个下一个判断语句
        return true;
    }
    if (anObject instanceof String) {//判断类型是否为String类型若是则进入,不是则返回false,不用比了,类型不同,根本不会想等。
        String aString = (String)anObject;//下转型转为String类型
        if (!COMPACT_STRINGS || this.coder == aString.coder) {//常量COMPACT_STRINGS为flase,短路语句直接进入语句体
            return StringLatin1.equals(value, aString.value);//此时返回一个东西,这时我们要点进这个equals看具体方法。在下一个代码块内介绍
        }
    }
    return false;
}
public static boolean equals(byte[] value, byte[] other) {//里面两个形参 传进两个要比较的元素,放到byte数组里
    if (value.length == other.length) {//先比较两个数组的长度 如果长度不同 就不会进入 
        for (int i = 0; i < value.length; i++) {//进入循环
            if (value[i] != other[i]) {//“aa”被拆分放到byte数组里一个一个字母比较,不像等返回false,否则返回true。
                return false;
            }
        }
        return true;
    }
    return false;
}

至此String中equals比较结束,在例子中返回true。

自定义类中的equals方法
	List<Student> list = new ArrayList<Student>();

Arraylist中contains中equals方法,

因为自定义类Student中没重写Object中equals方法,则调用Object中equals方法:

public boolean equals(Object obj) {
    return (this == obj);
}

没次都比较地址值,因为Student存入都要新的对象,所以,每次都不想等,所以每次都会返回false,所以会干扰到我们正常比较所以我们就需要重写equals方法:

public boolean equals(Object obj) {
	if(obj instanceof Student) {//可以首先判断是否为同一个自定类型,不同返回false
		Student student = (Student)obj;//转为Student类型
		return this.id.equals(student.id);//这里为自定类型中某一元素比较是否相同,相同为false,所以这样可以解决总是为false的问题。
	}
	return false;
	
}

以上可以用到set的add中,原理相同,不重写的话没有去重效果,HashSet真想实现自定义类型去重效果,还需要重写HashCode,就可以实现判断自定义类型中判断某位元素相同,从而达到去重效果,不像不重写之前都会添加进去的漏洞。

以上是关于ArrayList的indexOf方法与重写equals方法的主要内容,如果未能解决你的问题,请参考以下文章

List 的主要实现类:ArrayList

list.contains方法既然是调用equ 方法 还用重写 hashcod吗

重载和重写

java中的equals() 问题 help!!!!!!!!!!!!!!!!!

我的对象的 ArrayList,indexOf 问题

Java,重写Comparable比较方法,重写equals方法, Long 与 Long equals,Long 与 Long == ,Long 与 long ==