public List<CabinetStatisticBO> findCabinetStatistic(
CabinetStatisticSpec spec) {
List list = baseDAO.query(spec);
List<CabinetStatisticBO> statList = new ArrayList<CabinetStatisticBO>(); if (list != null && !list.isEmpty()) {
for (Object obj : list) {
CabinetStatisticBO statBO = new CabinetStatisticBO();
// 机房名称
String compLocaName = "";
// 已满机柜数
Integer fullCabinet = 0;
// 未满机柜数
Integer nofullCabinet = 0;
// 未使用机柜数
Integer unusedCabinet = 0;
// 总计
Integer totalCabinet = 0;
NetworkCabinets cabinet = (NetworkCabinets) obj;
                                     // 机房名称
compLocaName = cabinet.getComputerLocation().getName();
// 可使用高度
Integer allowHeight = cabinet.getAllowHeight();
// 已使用高度
Integer useHigh = cabinet.getUseHigh();
// 已满机柜数
if (useHigh != null && useHigh > 0
&& allowHeight - useHigh <= 0) {
fullCabinet += 1;
}
// 未满机柜数
if (useHigh != null && useHigh > 0 && allowHeight - useHigh > 0) {
nofullCabinet += 1;
}
// 未使用机柜数
if (useHigh == null || useHigh == 0) {
unusedCabinet += 1;
}
totalCabinet = fullCabinet + nofullCabinet + unusedCabinet;  if (statList == null || statList.isEmpty()) {
statBO.setCompLocaName(compLocaName);
statBO.setFullCabinet(fullCabinet);
statBO.setNofullCabinet(nofullCabinet);
statBO.setUnusedCabinet(unusedCabinet);
statBO.setTotalCabinet(totalCabinet);
statList.add(statBO);
} else {
for(Iterator iter = statList.iterator();iter.hasNext();) {
CabinetStatisticBO cs = (CabinetStatisticBO) iter
.next();
if (cs.getCompLocaName().equals(compLocaName)) {
cs
.setFullCabinet(fullCabinet
+ cs.getFullCabinet());
cs.setNofullCabinet(nofullCabinet
+ cs.getNofullCabinet());
cs.setUnusedCabinet(unusedCabinet
+ cs.getUnusedCabinet());
cs.setTotalCabinet(totalCabinet
+ cs.getTotalCabinet());
} else {                                                         statBO.setCompLocaName(compLocaName);
statBO.setFullCabinet(fullCabinet);
statBO.setNofullCabinet(nofullCabinet);
statBO.setUnusedCabinet(unusedCabinet);
statBO.setTotalCabinet(totalCabinet);
statList.add(statBO); //在这里会发生异常
}
}
} }
} return statList;
}要求在执行statList.add(statBO); 后继续循环遍历for(Iterator iter = statList.iterator();iter.hasNext();) 

解决方案 »

  1.   

    发生java.util.ConcurrentModificationException异常
    寻求网上解决办法没找到,一般就是讨论列表中元素的删除问题,即remove()
    而add()不知道怎么解决呢??
      

  2.   

    在statList.add(statBO);后,break 跳出循环,然后重新获取迭代器,继续循环
    也可以判断结束的条件(虽然往里面添加东西,但总有结束的条件),结束了就不在遍历了,不结束的话您老继续
    始终感觉这样子的实现不太好,建议楼主更换实现的思路
      

  3.   

    java.util.ConcurrentModificationException异常 
      

  4.   


    要做的是统计机房里面机柜的使用情况:机柜总计、未满机柜数、已满机柜数、未使用机柜数
    这里我查询的是机柜实体类,也就是已机柜为主,机房没有机柜的不统计
    如果不对列表进行处理,直接把机房名称和那些统计数设置一次,就添加到列表中,返回回去的列表是一个一个的列出每个机柜,同一个机房的机柜的统计数字根本没进行相加操纵数据库的SQL语句贴出来大家就明白了:机柜表:network_cabinets(ID int,COMP_LOCA_ID int,HEIGHT int,USE_HEIGHT int) 
    机房表:computer_location(ID int,NAME varchar) 
    其中,COMP_LOCA_ID是机房表的ID,HEIGHT是机柜的高度,USE_HEIGHT是已经使用的高度 
    现在要统计每个机房的机柜总数、未使用机柜总数(即已使用高度为空或等于0)、 
    未满机柜数(即已使用高度不为空并且大于0,并且高度-已使用高度>0) 
    已满机柜数(即已使用高度不为空并且大于0,并且高度=已使用高度) select l.NAME,
        count(*) as 机柜总计,
        sum(if(r.USE_HEIGHT is null or r.USE_HEIGHT=0,1,0)) as 未使用机柜数,
        sum(if(r.USE_HEIGHT>0 and r.USE_HEIGHT<r.HEIGHT,1,0)) as 未满机柜数,
        sum(if(r.USE_HEIGHT>=r.HEIGHT,1,0)) as 已满机柜数
    from network_cabinets r,computer_location l
    where r.COMP_LOCA_ID=l.ID
    group by l.NAME
      

  5.   

    for(Iterator iter = statList.iterator();iter.hasNext();) {
                            CabinetStatisticBO cs = (CabinetStatisticBO) iter
                                    .next();

                            if (cs.getCompLocaName().equals(compLocaName)) {
                                cs
                                        .setFullCabinet(fullCabinet
                                                + cs.getFullCabinet());
                                cs.setNofullCabinet(nofullCabinet
                                        + cs.getNofullCabinet());
                                cs.setUnusedCabinet(unusedCabinet
                                        + cs.getUnusedCabinet());
                                cs.setTotalCabinet(totalCabinet
                                        + cs.getTotalCabinet());
                            } else {                                                                                    statBO.setCompLocaName(compLocaName);
                                statBO.setFullCabinet(fullCabinet);
                                statBO.setNofullCabinet(nofullCabinet);
                                statBO.setUnusedCabinet(unusedCabinet);
                                statBO.setTotalCabinet(totalCabinet);
                                statList.add(statBO); //在这里会发生异常
                            }
                        }
    这里写的有问题,不是逻辑或者其他问题,这么做肯定会有问题的,Iterator iter = statList.iterator();iter.hasNext();这么将list转换成iterator再CabinetStatisticBO cs = (CabinetStatisticBO) iter
                                    .next();进而想改变cs的属性,这样做不是可能会出现问题,是一定会出现问题,相信lz查查ConcurrentModificationException产生的原因就知道了或者查查Iterator的api,建议lz直接用list的get方法来取得相应对象,进而改变其属性。
      

  6.   

    我更新CabinetStatisticBO cs不会有问题
    但是到else那add元素绝对有问题,因为list在遍历过程中,改变了list元素数量,就会抛那个异常
    还有,用list循环还是Interator来循环都是一样的
    你可以试试用Interator来操纵list的情况
    而且,我list定义的时候就给定是CabinetStatisticBO泛型,所以转换不会有问题
      

  7.   

     List list = baseDAO.query(spec);
            List<CabinetStatisticBO> statList = new ArrayList<CabinetStatisticBO>();
    if (list != null && !list.isEmpty()) {
                for (Object obj : list) {
                    CabinetStatisticBO statBO = new CabinetStatisticBO();
                }
    }如果在上面这个循环里,把值就直接设置到statBO ,再将statBO add到statList ,这样statList列表的元素为多个CabinetStatisticBO,这些BO里面有一些compLocaName相同,我想将compLocaName的BO的那四个统计数字分别相加,得到的相加后的四个统计数字再设置给其中一个BO,compLocaName机房名称不变,其它的BO remove掉
    也就是对statList 用一个两层循环,像排序法那样,挨个取出机房名称,相同的话将统计数字相加,设置到其中一个对象中,另一个对象则删掉;这样一直循环下去,到最后得到的就是根据不同机房,得到机柜的统计数字
    列表在遍历时要移除只能采用Iterator的remove方法
      

  8.   


    public class Score { private String name;
    private Integer chinese;
    private Integer math;

    public static void main(String[] args) {
    List<Score> scores = new ArrayList<Score>();
    Score score1 = new Score();
    score1.name="张三";
    score1.chinese = 89;
    score1.math = 90;

    Score score2 = new Score();
    score2.name="张三";
    score2.chinese = 78;
    score2.math = 83;

    Score score3 = new Score();
    score3.name="李四";
    score3.chinese = 67;
    score3.math = 50;

    Score score4 = new Score();
    score4.name="王五";
    score4.chinese = 88;
    score4.math = 99;

    Score score5 = new Score();
    score5.name="李四";
    score5.chinese = 80;
    score5.math = 86;

    Score score6 = new Score();
    score6.name="王五";
    score6.chinese = 90;
    score6.math = 96;

    Score score7 = new Score();
    score7.name="张三";
    score7.chinese = 76;
    score7.math = 90;

    Score score8 = new Score();
    score8.name="李四";
    score8.chinese = 88;
    score8.math = 83;

    scores.add(score1);
    scores.add(score2);
    scores.add(score3);
    scores.add(score4);
    scores.add(score5);
    scores.add(score6);
    scores.add(score7);
    scores.add(score8); for(int i=0;i<scores.size();i++){
    for(int j=i+1;j<scores.size();j++){
    Score s1 = scores.get(i);
    Score s2 = scores.get(j);
    if(s1.name.equals(s2.name)){
    Integer chinese2 = s2.chinese;
    Integer math2 = s2.math;
    s1.chinese=s1.chinese+chinese2;
    s1.math=s1.math+math2;
    scores.remove(s2);
    }
    }
    }
    for(int i=0;i<scores.size();i++){
    Score s = scores.get(i);
    System.out.println(s.name+":语文="+s.chinese+" 数学="+s.math);
    }
    }}
    运行结果:
    张三:语文=243 数学=263
    李四:语文=235 数学=219
    王五:语文=178 数学=195我作了下测试,能统计名字相同的对象的其它属性,去掉多余的对象,运行正常,不知道这样两层循环会不会有别的问题?有一点,就是性能会很差
      

  9.   

    你这里报那个异常是因为你用迭代的那个数组statList随时都在发生变化,而迭代随时发生变化的集合时就会报那个异常,我一般在那个循环条件里用get(int i)这个方法来获取对象,就不会报那个异常了。建议楼主试试看。
      

  10.   

    为什么不能等startList 添加完之后,再将startList进行遍历啊
      

  11.   


    // 贴出统计类CabinetStatisticBO public class CabinetStatisticBO {
    /** 机房名称 */
    private String compLocaName;

    /** 已满机柜数 */
    private Integer fullCabinet;

    /** 未满机柜数 */
    private Integer nofullCabinet;

    /** 未使用机柜数 */
    private Integer unusedCabinet;

    /** 机柜总数 */
    private Integer totalCabinet;
    public Integer getFullCabinet() {
    return fullCabinet;
    } public void setFullCabinet(Integer fullCabinet) {
    this.fullCabinet = fullCabinet;
    } public Integer getNofullCabinet() {
    return nofullCabinet;
    } public void setNofullCabinet(Integer nofullCabinet) {
    this.nofullCabinet = nofullCabinet;
    } public Integer getTotalCabinet() {
    return totalCabinet;
    } public void setTotalCabinet(Integer totalCabinet) {
    this.totalCabinet = totalCabinet;
    } public Integer getUnusedCabinet() {
    return unusedCabinet;
    } public void setUnusedCabinet(Integer unusedCabinet) {
    this.unusedCabinet = unusedCabinet;
    }
    public String getCompLocaName() {
    return compLocaName;
    } public void setCompLocaName(String compLocaName) {
    this.compLocaName = compLocaName;
    }
      

  12.   


    因为我要判断列表中元素机房名称是否和外面那个遍历过程中的机房名称相同,如果相同,直接改变列表中统计数字的值,将列表中统计的值取出和当前的外层遍历的统计值相加,
    不就是机房相同的机柜使用情况得到了统计嘛?等startList 添加完后,列表里是所有机柜,再如何进行统计?用两层循环?机房名字相同的,统计数字进行相加,设置到其中一个对象的属性中?另外对象删除掉?
    我也这么想过,但是达不到效果看看我回复在上面的测试程序,那样是行不通的,那段程序运行结果貌似正确,改变list里面的元素个数,就不对了
      

  13.   

    试试  Connections.synchronizedList(List<T> list) ;
      

  14.   

    看你的需求,感觉你clone下对象,用它的副本遍历应该就能满足你的要求了,要不搞不好会死循环的,所以会报异常的。
      

  15.   

    把你的对象clone一份,然后再循环
      

  16.   

    嘿嘿,看来是我说的不明白了,你是先将list iterator了,在用iterator的next返回对象强制转换成相应的对象,然后再对得到的对象进行修改,问题就处在这里,你可以用list的get方法取得对象,再对这个对象进行修改,你可以先试试结果如何,不行再说,可以么
      

  17.   


    刚开始就是用的list的get方式做的
    看来你对Iterator不太了解,它本来就是用来迭代集合的,迭代的哪个List,next()当然就是那个List里面的元素,哪里是强制转换??
    你去试试用Iterator来迭代list进行输出吧
    java基础问题,呵呵
      

  18.   

    用ListIterator有add方法的啊,不过add不是加在最后,而是加在当前元素后,下面只是个例子
    List list = new ArrayList(){{
    add("1");
    add("2");
    add("3");
    }};
    for(ListIterator iter = list.listIterator(0);iter.hasNext();iter.next()) {
    if (new Random().nextBoolean()) {
    iter.add("4");
    }
    }
    System.out.println(list);
      

  19.   

    迭代的同时add,会有同步异常,建议加同步处理
      

  20.   

    靠,来晚了。就是25楼说的方法。1.把Iterator换成ListIterator。
    2.把抛出异常的那行代码,换成iter.add(statBO)。原因是,Iterator中有List中某些元素的缓存,所以,当List中元素个数发生变化的时候,造成Iterator的不同步。
    他们把元素的个数的改变以及元素本身内容的改变称为状态的改变。
    因为缓存的存在,使得List的状态改变后,无法同步给Iterator。
    所以会抛出那个什么异常。
      

  21.   

    算了,还用什么Iterator,直接用for(int i=0;i<list.size();i++)
    不就行了,也不要考虑同步什么的问题了,在循环里面添加元素也不会有问题。
    不要用for(Object o : list)这种循环,它实际上也是用Iterator实现的。
      

  22.   

    你一边在迭代循环LIST中的值,又一边往里加别的东西。所以才会报这种异常的。按照我以前的做法。你可以另外定义一个LIST。满足条件的添加到这个LIST中去。然后通过collection的removeall的方法。将这些值去掉。
      

  23.   

    public class ConcurrentModificationException extends RuntimeException当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不明确的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。 注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。 
      

  24.   

    死活都要操作那个结果的list吗?干吗不用HashMap?它可是很快的。package csdn;import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;public class Score {    private String name;
        private Integer chinese;
        private Integer math;
        
        public static void main(String[] args) {
            List<Score> scores = new ArrayList<Score>();
            Score score1 = new Score();
            score1.name="张三";
            score1.chinese = 89;
            score1.math = 90;
            
            Score score2 = new Score();
            score2.name="张三";
            score2.chinese = 78;
            score2.math = 83;
            
            Score score3 = new Score();
            score3.name="李四";
            score3.chinese = 67;
            score3.math = 50;
            
            Score score4 = new Score();
            score4.name="王五";
            score4.chinese = 88;
            score4.math = 99;
            
            Score score5 = new Score();
            score5.name="李四";
            score5.chinese = 80;
            score5.math = 86;
            
            Score score6 = new Score();
            score6.name="王五";
            score6.chinese = 90;
            score6.math = 96;
            
            Score score7 = new Score();
            score7.name="张三";
            score7.chinese = 76;
            score7.math = 90;
            
            Score score8 = new Score();
            score8.name="李四";
            score8.chinese = 88;
            score8.math = 83;
            
            scores.add(score1);
            scores.add(score2);
            scores.add(score3);
            scores.add(score4);
            scores.add(score5);
            scores.add(score6);
            scores.add(score7);
            scores.add(score8);        
            Map<String,Score> scoreMap = new HashMap<String,Score>();
            for(Score score:scores){
             Score temp =scoreMap.get(score.name);
             if(temp==null)
             scoreMap.put(score.name, score);
             else{
             temp.chinese+=score.chinese;
             temp.math+=score.math;
             }
            }
           List<Score> result = new ArrayList<Score>(scoreMap.values());
           System.out.println(result);
        }
        public String toString(){
         return name+":语文="+this.chinese+" 数学="+this.math;
        }}