List removeAll详解
list.removeAll 会随着数量的增加,性能变得很差,原因为: list.contains 需要进行两次遍历
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;
}
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
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;
}
解法:使用HashSet 和LinkedList 进行替换(HashSet保证元素唯一性,LinkedList提升插入删除性能)
public List<T> removeAll(List<T> source, List<T> destination) {
List<T> result = new LinkedList<T>();
Set<T> destinationSet = new HashSet<T>(destination);
for(T t : source) {
if (!destinationSet.contains(t)) {
result.add(t);
}
}
return result;
}
评述:主要是使用HashSet具有散列性质的contains 替换 需要进行两次遍历的contains
浙公网安备 33010602011771号