坑点
做题常用:
- 数组转变
Arraylist.asList() 实际上传的是一个可变长参数,调用了内部类,基础类型的数组由于
不是封装类(猜测java对封装类型的数组和变长参数有过转换处理,形如scala隐式抓换),导致基本类型数组,在<>中只能被定义为 数组类型;
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public int size() {
return a.length;
}
@Override
public Object[] toArray() {
return a.clone();
}
}
- remove
最好不要在循环体中使用remove效率极其低下,每次都会产生一个新的list,由于gc优先级很低,会导致潜在的内存溢出
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
推荐使用:
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;
}
这段代码只生成了一次数组,缺点是必须要转成set或者list,基本类型需要包装一次
缺点:如果是char(2byte)、int(4byte)等基本类型,包装过后需要一个引用4个字节,object对象8个字节,最小是12个字节还不包含内容;使得内存占用变大;