java源码之ArrayList.remove()&&removeAll()

java源码之ArrayList.remove&&removeAll

抛出问题

在使用ArrayList做一个发牌操作时,使用removeAll去删除已发的棋牌,比如已发【一万,二筒】,此时用removeALL去将剩余牌队列中的这两张牌删除,发现会将剩余牌中的所有【一万,二筒】全部删除,用remove去依次删除【一万】和【二筒】则只会删除一张【一万】和【二筒】;

查看问题

removeAll: 查看源码后发现removeAll会将所有eq的对象全部移除。

ArrayList.java
public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
     final Object[] elementData = this.elementData;
     int r = 0, w = 0;
     boolean modified = false;
     try {
         for (; r < size; r++)
             if (c.contains(elementData[r]) == complement)
                 elementData[w++] = elementData[r];
     } finally {
         // Preserve behavioral compatibility with AbstractCollection,
         // even if c.contains() throws.
         if (r != size) {
             System.arraycopy(elementData, r,
                              elementData, w,
                              size - r);
             w += size - r;
         }
         if (w != size) {
             // clear to let GC do its work
             for (int i = w; i < size; i++)
                 elementData[i] = null;
             modCount += size - w;
             size = w;
             modified = true;
         }
     }
     return modified;
 }
public boolean contains(Object o) {
     return indexOf(o) >= 0;
 }
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;
}

remove: 查看源码发现,会将list中第一个与删除对象eq的对象删除。

public boolean remove(Object o) {
      if (o == null) {
          for (int index = 0; index < size; index++)
              if (elementData[index] == null) {
                  fastRemove(index);
                  return true;
              }
      } else {
          for (int index = 0; index < size; index++)
              if (o.equals(elementData[index])) {
                  fastRemove(index);
                  return true;
              }
      }
      return false;
  }

结论

这里不能用removeAll的方式进行删除,因为我重写了实体的equals方法,【一筒@123】和【一筒@234】的equals值时相同的,所以用removeAll会同时删掉,这里可以用remove方式一个个删除,但是注意:此处因为是从list[0]开始发牌,所有可以用remove,如果是从末尾开始的,用remove则有问题,因为你要移除的是排在最后的【一筒】,但是你remove掉的是list中的第一个【一筒】;

发布了41 篇原创文章 · 获赞 22 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq1049545450/article/details/82865515