编辑Hashtable / Hashmap时出现java.util.ConcurrentModificationException

时间:2016-07-16 17:11:12

标签: java android

我正在编写一段代码,如果它们的键相同,它们应该组合散列表/散列映射的值。但是,当我尝试使用迭代器执行此操作时,它会抛出java.util.ConcurrentModificationException。令人惊讶的事实是,这种情况仅在某些情况下发生,而在其他情况下则完全发挥作用。我的代码如下:

启动流程的行。从onPostExecute的{​​{1}}开始:

AsyncTask

ListFragment.addtolist(getdataformap()); 的片段:

ExpandableListView

堆栈:

 public static class ListFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static CustomMap1 datapforputcustom ;
        public static ExpandableListView expandablelistview;
        public static CustomExpandableListAdapter expandableadapter;
        public static Hashtable<Fitems, List<Fnitems>> datapforput = new Hashtable<>();
        public static List<Fitems> mainforput = new ArrayList<>();
        public static View view;
        public static Context getha;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            view = inflater.inflate(R.layout.activity_listfragment, container, false);
            //doddata();
            expandablelistview = (ExpandableListView) view.findViewById(R.id.expandableListView);
            expandableadapter = new CustomExpandableListAdapter(((Result) getActivity()).getha(), mainforput, datapforput);
            expandablelistview.setAdapter(expandableadapter);
            getha = ((Result) getActivity()).getha();
            return view;
        }

        @Override
        public void onStart() {
            super.onStart();
            Permutation.finallist = new ArrayList<>();
            Single_Permutation.singlelist = new ArrayList<>();
   /* doddata();
    expandablelistview = (ExpandableListView) view.findViewById(R.id.expandableListView);
    expandableadapter = new CustomExpandableListAdapter(((Result)getActivity()).getha(),mainforput,datapforput);
    expandablelistview.setAdapter(expandableadapter);*/
        }

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static class CustomMap1 extends Hashtable<Fitems, List<Fnitems>> {
            @Override
            public List<Fnitems> put(Fitems value, List<Fnitems> valuelist) {
                List<Fnitems> oldlist = new ArrayList<>();
                Fitems oldkey =value;
                String tester="";

                for (Entry<Fitems, List<Fnitems>> entry : entrySet()) {
                    Log.e("LIST",(entry.getKey().getName()+(value.getName())));
                    if (value.getName().equals(entry.getKey().getName())) {
                        tester = "ojfagsbou";
                        oldkey = entry.getKey();
                        oldlist.addAll(entry.getValue());
                        remove(entry.getKey());
                    }
                }
                // combine your keys as you wish
                List<Fnitems> newvaluelist = new ArrayList<>();
                if (!"".equals(tester)) {
                    System.out.println(oldkey.getName()+"oldkey");
                    newvaluelist.addAll(oldlist);
                    newvaluelist.addAll(valuelist);
                } else {
                    newvaluelist.addAll(valuelist);
                    System.out.println(oldkey.getName()+"oldkey");
                    mainforput.add(oldkey);
                }
                return super.put(oldkey, newvaluelist);
            }
        }
        public static void doddata() {
           /* Fitems fitems1 = new Fitems();
            Fitems fitems2 = new Fitems();
            Fnitems fnitems1 = new Fnitems();
            Fnitems fnitems2 = new Fnitems();
            Fnitems fnitems3 = new Fnitems();
            Fnitems fnitems4 = new Fnitems();
            fitems1.setName("AAA");
            fitems2.setName("BBB");
            fnitems1.setName("AAAa");
            fnitems2.setName("AAAb");
            fnitems3.setName("BBBa");
            fnitems4.setName("BBBb");
            List<Fnitems> listfnitem1 = new ArrayList<>();
            List<Fnitems> listfnitem2 = new ArrayList<>();
            listfnitem1.add(fnitems1);
            listfnitem1.add(fnitems2);
            listfnitem2.add(fnitems3);
            listfnitem2.add(fnitems4);*/
            mainforput=new ArrayList<>();
            datapforputcustom = new CustomMap1();
            datapforput = new Hashtable<>();
            ArrayList<String> strind = new ArrayList<>();
            for(Map.Entry<String,Map<String,Integer>> entry1 : Result.cart_names1.entrySet()){
                strind.add(entry1.getKey());
            }
            Log.e("ERROR", "thisis the list for god's sake " + Result.couldthis+datapforput.toString());
            if (Result.couldthis.size() > 0) {
                for (int i = 0; i < (Result.couldthis).size(); i++) {
                    Fitems fitems3 = new Fitems();
                        fitems3.setName(Result.couldthis.get(i));
                        Fnitems fnitems5 = new Fnitems();
                        fnitems5.setName(strind.get(i));
                        List<Fnitems> listfnitem3 = new ArrayList<>();
                        listfnitem3.add(fnitems5);
                    Log.e("RE",fitems3.getName()+" "+listfnitem3.get(0).getName());
                        datapforput.put(fitems3,listfnitem3);
                    }
                }
            datapforputcustom.putAll(datapforput);
            Log.e("UGF",datapforputcustom+" cusom");
            //datapforput.put(fitems1, listfnitem1);
           // datapforput.put(fitems2, listfnitem2);
           // mainforput.add(fitems1);
           // mainforput.add(fitems2);
        }

        public static ListFragment newInstance() {
            ListFragment fragment = new ListFragment();
            Log.e("ERROR", "man .... " + fragment.getTag());
            return fragment;
        }

        public static void addtolist(ArrayList<String> dataforputting) {
           Log.e("ERROR", "thisis the list 3" + (dataforputting));
            //if (expandableadapter != null){
            expandableadapter.clear();//}
            Log.e("INFO", "This is mainforput" + mainforput + "This is dataforput" + datapforput);
            doddata();
            Log.e("INFO", "This is mainforput" + mainforput.get(0).getName() + "This is dataforput" + datapforputcustom);
            expandableadapter = new CustomExpandableListAdapter(getha, mainforput, datapforputcustom);
            expandablelistview.setAdapter(expandableadapter);
        }


    }

百万提前谢谢!

2 个答案:

答案 0 :(得分:0)

请阅读:https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Hashtable.html

Hashtable的开头说明涵盖了您遇到的ConcurrentModificationException;文档声明Hashtable的迭代器是快速失败的,并且只要迭代器和迭代器下的基础ConcurrentModificationException更改未用于进行这些更改,就会抛出Hashtable。 / p>

在堆栈中,列出了putAll() - 因此它正在修改底层结构并导致迭代器失败。无论如何你可以协调这两个事件不同时发生吗?如果你能找到一种方法,那么我认为你将解决问题。

答案 1 :(得分:0)

  

发生ConcurrentModificationException是因为你没有锁定对HashTable的REMOVE方法的访问,因此有人可以在你的重写PUT方法中迭代HashTable时插入和删除项目。

     

请检查我的课程,这个可以随时重现您的错误。修复程序可以在&#34; CustomMapImproved&#34;中找到。类。

import java.util.concurrent.locks.ReentrantLock;

public class TestHashTable {

public static class CustomMap1 extends Hashtable<String, List<String>> {
    @Override
    public List<String> put(String value, List<String> valuelist) {
        List<String> oldlist = new ArrayList<>();
        String oldkey = value;
        String tester="";

        for (Map.Entry<String, List<String>> entry : entrySet()) {
            if (entry.getValue().get(0)!=null 
                    && value.equals(entry.getValue().get(0))) {
                tester = "arbitrary";
                oldkey = entry.getKey();
                oldlist.addAll(entry.getValue());
                remove(entry.getKey());
            }
        }

        // combine your keys as you wish
        List<String> newvaluelist = new ArrayList<>();
        if (!"".equals(tester)) {
            //System.out.println(oldkey.getName()+"oldkey");
            newvaluelist.addAll(oldlist);
            newvaluelist.addAll(valuelist);
        } else {
            newvaluelist.addAll(valuelist);
        }
        return super.put(oldkey, newvaluelist);
    }
}

public static class CustomMapImproved extends Hashtable<String, List<String>> {
    private final Lock lock = new ReentrantLock();

    @Override
    public List<String> put(String value, List<String> valuelist) {
        lock.lock();
        try{
            List<String> oldlist = new ArrayList<>();
            String oldkey = value;
            String tester="";

            Iterator<Map.Entry<String, List<String>>> iterator = entrySet().iterator();
            java.util.Map.Entry<String, List<String>> entry;

            while (iterator.hasNext()) {
                entry = iterator.next();
                if (entry.getValue().get(0) != null && value.equals(entry.getValue().get(0))) {
                    tester = "arbitrary";
                    oldkey = entry.getKey();
                    oldlist.addAll(entry.getValue());
                    iterator.remove();//use this instead of remove(Object);
                }
            }

            // combine your keys as you wish
            List<String> newvaluelist = new ArrayList<>();
            if (!"".equals(tester)) {
                //System.out.println(oldkey.getName()+"oldkey");
                newvaluelist.addAll(oldlist);
                newvaluelist.addAll(valuelist);
            } else {
                newvaluelist.addAll(valuelist);
            }
            return super.put(oldkey, newvaluelist);
        }finally{
            lock.unlock();
        }
    }

    @Override
    public List<String> get(Object obj){
        lock.lock();
        try{
            return super.get(obj);
        }finally{
            lock.unlock();
        }
    }

    @Override
    public List<String> remove(Object obj){
        lock.lock();
        try{
            return super.remove(obj);
        }finally{
            lock.unlock();
        }
    }
}

public static void main(String[]args){
    //final Hashtable<String,List<String>> map = new CustomMap1();
    final Hashtable<String,List<String>> map = new CustomMapImproved();
    final List<Thread> tList = new ArrayList<Thread>();
    final int reps = 1000;
    int thread = 100;

    for(int i=0;i<thread; i++){
        final int idx = i;
        Thread t = new Thread(new Runnable(){
            public void run(){
                for(int i=0;i<reps;i++){
                    if(idx%2==0){
                        List<String> list = new ArrayList<String>();
                        list.add("value"+idx);
                        map.put("value"+idx,list);
                    }
                    else{
                        map.remove("value"+idx);
                    }
                }

            }
        });
        t.start();
        tList.add(t);
    }

    for(Thread t : tList){
        try {t.join();} catch (InterruptedException e) {}
    }
}

}