欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数组陷阱 博客分类: 开发随笔  

程序员文章站 2024-03-19 10:51:22
...

        由于需求变更,以前静态显示的值现在需要动态显示,用户能在配置文件或是在某些页面上面手工指定哪些东西需要显示,哪些需要隐藏。还有一个前提是,改后后设定了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这个对象就好了,不这样的话,无法满足要求,因为这里也涉及到表格索引的问题。