2 wuzangji0642 wuzangji0642 于 2018.01.03 22:44 提问

java list remove add问题 5C

原始数据
图片说明
排序后数据
图片说明
排序规则,如果一条数据的staff_id出现多次,date最大的那条记录的位置不变,将date较小的那条排在下面(对同一个staff_id进行内部排序)
原始数据中,staff_id为1和2的出现了多次,date最大的分别是
1 ada 7 201801和 2 anna 6 201712
因为anna的数据少,先看 anna ,anna的另一条记录,date是201711,小于201712,应该排在后面,所以数据变成了
1 ada 5 201711
3 jack 6 201711
1 ada 6 201712
2 anna 6 201712
2 anna 5 201711
1 ada 7 201801
ada同理,最后变成了第二幅图上的排序结果。
算法如下
List resultListOrder=...

for(Object[] rowOrder:resultListOrder)
{
for(Object[] row:resultListOrder)
{
//staff_id相同的且date较大
if((int)rowOrder[0] ==(int) row[0]&&(int)rowOrder[4]>(int)row[4])
{
Object[] tempRow = row;
//remove date较小记录
resultListOrder.remove(resultListOrder.indexOf(row));
//将date较小记录插入较大记录下一行
resultListOrder.add(resultListOrder.indexOf(rowOrder)+1,tempRow);

        }
  }

}
程序报错 ConcurrentModificationException,是remove造成的。解决方法可以用
Iterator,但是不知道怎么把刚刚那个算法改成Iterator,请问该怎么修改能实现正确的排序

9个回答

caozhy
caozhy   Ds   Rxr 2018.01.03 23:09

ConcurrentModificationException并发修改异常。迭代删除要用后往前删除。线程并发操作要加锁。

RunWithSmile
RunWithSmile   2018.01.04 09:04

改成最原始的for循环就没问题

RunWithSmile
RunWithSmile   2018.01.04 09:25

List list = new ArrayList();
public void sort(){
Iterator itr = list.iterator();
while(itr.hasNext()){
itr.remove();
}
}
是这个意思吗?

RunWithSmile
RunWithSmile 回复wuzangji0642: 你用if条件包裹itr.remove();当满足条件才删除。实在不行就换成最原始的for(;;)就不会产生这样的错误了
20 天之前 回复
wuzangji0642
wuzangji0642 Iterator不能在指定位置remove,我要通过if条件判断才能找到需要改变位置的那条记录,hasnext这个没法用吧
20 天之前 回复
jike316
jike316   2018.01.04 12:22
 public class TestListSort {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        List<Student> list = new ArrayList<Student>();
        Student s1 = new Student();
        s1.setId(1);
        s1.setName("Ada");
        s1.setPostionId(5);
        s1.setEntryDate(sdf.parse("201711"));
        list.add(s1);

        Student s2 = new Student();
        s2.setId(2);
        s2.setName("Anna");
        s2.setPostionId(5);
        s2.setEntryDate(sdf.parse("201711"));
        list.add(s2);

        Student s3 = new Student();
        s3.setId(3);
        s3.setName("Jack");
        s3.setPostionId(6);
        s3.setEntryDate(sdf.parse("201711"));
        list.add(s3);

        Student s6 = new Student();
        s6.setId(1);
        s6.setName("Ada");
        s6.setPostionId(6);
        s6.setEntryDate(sdf.parse("201712"));
        list.add(s6);

        Student s4 = new Student();
        s4.setId(2);
        s4.setName("Anna");
        s4.setPostionId(6);
        s4.setEntryDate(sdf.parse("201712"));
        list.add(s4);


        Student s5 = new Student();
        s5.setId(1);
        s5.setName("Ada");
        s5.setPostionId(7);
        s5.setEntryDate(sdf.parse("201801"));
        list.add(s5);
        System.out.println("before sort..........................");
        list.forEach(item ->{
            System.out.println(item);
        });

        list.sort(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                if(o1.getId()==o2.getId()) {
                    Long time1 = o1.getEntryDate().getTime();
                    Long time2 = o2.getEntryDate().getTime();
                    return time2.compareTo(time1);
                }
                return o2.getId().compareTo(o1.getId());
            }

        });
        System.out.println("after sort..........................");
        list.forEach(item ->{
            System.out.println(item);
        });
    }
}

如果不是jdk1.8,可以使用Collections来实现也可以。

wangjin9805
wangjin9805   2018.01.05 15:11

如果是排序 最好重写集合compare方法,如果是循环改写 应该类似
Iterator iterator = resultListOrder.iterator() ;
while(iterator.hasNext()){
Object[] b = (Object[]) iterator.next();

}
stiven900804
stiven900804   2018.01.05 23:29

在java中,ArrayList和LinkedList类型,不能使用迭代器时使用remove方法。
ListIterator it = arrayList.listIterator();

// while(it.hasNext())
// {

// String item = it.next();

// if(item.toLowerCase().indexOf(s.toLowerCase()) == 0)
// {

// //it.remove();
// arrayList.remove(item); //这里删除后,在下一次迭代的时候就会出BUG,用for循环
// arrayList.addFirst(item);
// }

// }

//

for (int i = 0 ; i < arrayList.size() ; i ++) {
if(arrayList.get(i).toLowerCase().indexOf(s.toLowerCase()) == 0)
{
String item = arrayList.get(i);
arrayList.remove(i);
arrayList.addFirst(item);
}
}

dcxy0
dcxy0   Ds   Rxr 2018.01.03 23:05

你把remove换成:符合要求的加入到一个新的List里面不就行了吗?

zy841958835
zy841958835   Ds   Rxr 2018.01.04 09:03

在remove只后会改变原有的list 可以试试jdk1.8的stream特性

sinat_34344123
sinat_34344123   2018.01.04 07:49

你只需要把ArrayList换成ConpyOnWriteList就可以了。快去试一下吧。

sinat_34344123
sinat_34344123 用手机回复的。卡了。。。不好意思回复了那么多条
20 天之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!