数组陷阱

        由于需求变更,以前静态显示的值现在需要动态显示,用户能在配置文件或是在某些页面上面手工指定哪些东西需要显示,哪些需要隐藏。还有一个前提是,改后后设定了10个组件能显示,不过这也是考虑到页面到时候放不下而设置的,程序里面并没有做控制,既然是手工指定,那就应该能显示任意多个。背景介绍完毕。

        刚开始被通知这方面需要改的时候,内心是崩溃的、反对的,因为前期代码写的不够灵活,改动量确实比较大,但是工程说这是客户要求的,没办法。于是动手开始改,一步步来,先从页面上感觉最难改的地方开始改,有点扯远了,还是说一下遇到的这个数组陷阱。由于需要动态显示,那么查询出来的记录需要判断,删掉不符合要求的,然后问题就是出在删除上面,

int flag = 0;		//判断有多少个列未显示
for (int i=0;i<pList.size();i++) {
	T p =pList.get(i);
	if(p.getColumn().equals("he")){
		flag++;
		continue;
	}
	p.setColumn(p.getColumn()-flag);				
}   //  命名上面已经做了处理

 这是修改之后没有问题的代码,但是之前也有些问题,之前改好的第一版代码是:

//			for (T property : pList) {
//				if(p.getColumn().equals("he")){
//					continue;
//				}

这两段代码只是相差一个p.setColumn(p.getColumn()-flag);之前没有做这个处理,因为涉及到表格索引问题,然后直接就抛出超出索引异常。

    这只是我说的一处,修改另外一个地方也有点问题,那里直接将传一个List过去,然后我就直接在循环里面使用pList.remove(p);完整的代码是酱紫的:

for (T property : pList) {
    if(p.getColumn().equals("he")){
        flag++;
        pList.remove(p);
        continue;
    }

 ,当进到那个if判断语句之后,再回到for语句,直接抛出java.util.ConcurrentModificationException,第一次遇到这种异常,平时一般只是碰到空指针异常或是类转换异常,百度之后发现是类集迭代出现问题。其实抛出这种异常也比较在理,如果不是在list集的最后一个执行remove方法,意味着被移除的类集后面的执行地址将地址,里面结果我不是很懂,但是list也是对数组的封装,而数组初始化的时候,根据存储的值得类型,初始化不同的空间,当中间某个值被删除了,如果一个个遍历过去,被删除的后面的数据也就访问不到了,这也是比较正常的情况。还有一个问题是运行过程中,感觉会有问题,实际情况真有问题。当上面那段代码被改写成如下的代码之后:

for (int i=0;i<prList.size();i++) 

 如果依然在里面执行remove方法,for语句应该会少执行一次,除非remove的是类集的最后一个数据。因为List类集根据里面的内容,动态的改变自身的size:

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

    /*
     * 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; // Let gc do its work
    }

 这段代码是java源码ArrayList里面的,每次执行remove方法的时候,它的size也就动态的建议(--size)。最后for循环没有变,重新建了一个List,将每次符合要求的对象存进去,最后return这个对象就好了,不这样的话,无法满足要求,因为这里也涉及到表格索引的问题。

猜你喜欢

转载自heshifk.iteye.com/blog/2250891