美文网首页
ArrayList的indexOf方法与重写equals方法

ArrayList的indexOf方法与重写equals方法

作者: 勇者与王者 | 来源:发表于2019-09-28 15:09 被阅读0次
package generic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import objectAndClass.Hero;

/**
* 
* @author q06285:
* @version 创建时间:2019年9月28日 上午11:11:20
* 
*/
public class DeleteCollection {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        List<Hero> heros = new ArrayList<>();
        
        for (int i = 0 ; i < 100; i++) {
            heros.add(new Hero("hero "+ i));
        }
        
//      System.out.println(heros.get(0).equals(heros.get(1)));
        
        Iterator<Hero> it = heros.iterator();
        
//      while (it.hasNext()) {
//          Hero h = it.next();
//          String [] s = h.getName().split(" ");
//          System.out.println(Arrays.toString(s)+" "+s[1]);
////            System.out.println(Integer.parseInt(s[1]) % 8);
//          
//          if ( Integer.parseInt(s[1]) % 8 == 0 ) {
//              System.out.println(h);
////                System.out.println(heros.indexOf(h));
////                System.out.println(heros.get(8));
//              
//              System.out.println(heros.get(0).equals(h));
//              
//              System.out.println("移除第 "+heros.indexOf(h)+"个元素");
//              it.remove();
//              System.out.println(heros);
//              
//          }
//          
//      }
        
        List<Hero> deleteHeros = new ArrayList<>();
        for (int i = 0 ; i<100; i+=8) {
            
            
            //写到这一句就觉得不对了
//          remove之后整个list的索引都变了,再按照for循环中的模式去移除,肯定不行
//          第一个反应是,把所有的要删除的元素都记下来存一个新列表,最后一起删,但是这个实现起来,
//          最终还是不能用索引来删除,只能想到用remove(Object o)方法:
//          或者是 将所有的索引为8倍数的位置进行标记,或者赋值为null?
//          又或者是  将原数组除了 符合 8 倍数的元素都复制到一个新列表,这个好像也挺麻烦的。。
//          所以,如果一定要用 i+=8 这种遍历方式,就只有将  将所有的索引为8倍数的位置赋值为null,
//          然后统一删
            
//          heros.remove(i);
            
//          heros.get(i) = null;
            
            heros.set(i, null);
            
//          deleteHeros.add(heros.get(i));
            
            //syso 输出 一个整数+Object对象 会报错,需要在中间加一个 “ ”就自动转成字符串
            System.out.println(i+" "+heros.get(i));
            
//          System.out.println(heros);
        }
        
        System.out.println(heros);
        
        // 已经没有99个元素了。。越界异常
//      好呆。。直接 i< heros.size() 不就行了吗。。。服了我自己
        //就应该统一的用自己的length或 size()这些!!
        
        for (int i = 0 ; i< heros.size() ;i++) {
            if (heros.get(i) == null) {
                System.out.println("移除第 "+i+"个元素");
                heros.remove(i);
            }
        }
        
//      for(Hero h :heros) {
//          if (h == null) {
//              System.out.println("移除第 "+heros.indexOf(h)+"个元素");
//              //增强for本质还是 Iterator 
//              遍历的同时进行删除抛出异常 ConcurrentModificationException
//              heros.remove(h);
//          }
//      }
        
        //上面的方法也不行,试下把要删除的元素 保存到新列表
//      for ( int i = 0 ; i< heros.size() ; i++) {
//          for ( int j = 0 ;j < deleteHeros.size();j++) {
//              if (heros.get(i) == deleteHeros.get(j)) {
//                  heros.remove(i);
//              }
//          }
//      }
//更好的办法:
//      for (Hero h : deleteHeros) {
//            heros.remove(h);
//        }
//      heros.removeAll(deletingHeros); //直接通过removeAll删除多个Hero对象
        
        
        System.out.println(heros);
        
        
        
    }

}


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

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;
    }

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

public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o instanceof Hero) {
            Hero h = (Hero)o;
            return this.hp == h.hp;
        }
        return false;
    }

这个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的indexOf方法与重写equals方法

      本文链接:https://www.haomeiwen.com/subject/ufqtpctx.html