class A { int a_num; B b; }
class B{ int b_num; A a; }
如果改成下面这样怎么样?
class AB { int a_num; int b_num; }
某些Java应用程序当对象太多而垃圾回收器还没有来得及回收的时候,就可能会导致堆内存溢出,其实内存溢出是分为栈内存溢出和堆内存溢出的,关于堆和栈的区别,可以参考program-think的这篇文章,讲的通俗易懂。关于上面的这个例子,就是我在实际编码中发现的一个造成内存消耗严重的一个问题,你或许还会认为上面那种写法更技术,更××。如果A的实例和B的实例个数很少的时候还好,但是如果他们的实例个数达到上百万的级别的时候,你就会思考一下是不是要换成下面这种写法了。首先你要了解怎么去计算一个对象会占多少字节的内存,然后思考为什么下面的写法会比上面的占用更少的内存?
list.addAll(java.util.Arrays.asList(objct_array));
其实,如果不是在内核运算的地方,或者某个对性能要求很高的地方写这句话完全没有问题,但如果在某个关键的地方,比如在某个要调用极多次数的方法里写用这个方法,也许就会出现问题。在这种地方,最好还是不要偷懒,用最原始但很高效的数组来解决问题。
Object[] old_array = array; array = new Object[old_array.length + new_array.length]; System.arraycopy(old_array, 0, array, 0, old_array.length); System.arraycopy(new_array, 0, array, old_array.lengyh, new_array.length);
事实上:ce_list.addAll(java.util.Arrays.asList(ce_array));这句效率是非常慢的,它将
一个数组变成了一个list又变成一个数组又变成一个list,因为内部是这样实现的:
public static List asList(Object[] a) { return new ArrayList(a); // 新建了一个对象,同时数组变成一个list. } public boolean addAll(Collection c) { Object[] a = c.toArray(); // 看这里, list又变成了一个数组,绕了一圈啊 int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); // 这个跟修改后做的差不多 size += numNew; return numNew != 0; }
结果证明:修改后这部分消耗的临时内存没有了,速度也变快了。