简体   繁体   中英

Why is the system automatically converting my LinkedHashMap to HashMap while passing it in an Intent as a Serializable?

I am getting

java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap

at LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>) intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY"); in the given (relevant parts of) code of Activity B.


  1. In Fragment A, I have the following check:

     Log.i(TAG, "THE TYPE OF THE MAP RETURNED FROM populateSelectedEntryList(selectedResultEntry) IS " + populateSelectedEntryList(selectedResultEntry).getClass().getSimpleName() + ".");//******PRINTS LinkedHashMap**********************

which prints LinkedHashMap .

  1. In Activity B, I have the following check:

     LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>)intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");//**********ClassCastException*****************

    which prints HashMap .


The question is why? Why is the system converting my LinkedHashMap to HashMap. How do i force the LinkedHashMap to continue to be a LinkedHashMap when it is passed in an intent as a Serializable?

RELEVANT PARTS OF CODE:

In Fragment A,

public class A extends Fragment {
  ...

  public void onListItemClick(...) { 
    Intent intent = new Intent(getActivity(), B.class);
    ...
    intent.putExtra("tests.test.MyApp.A.EXTRA_KEY", populateSelectedEntryList(selectedResultEntry));
    Log.i(TAG, "THE TYPE OF THE MAP RETURNED FROM populateSelectedEntryList(selectedResultEntry) IS "
 + populateSelectedEntryList(selectedResultEntry).getClass().getSimpleName() + ".");//******PRINTS LinkedHashMap**********************
    startActivity(intent);
  };

  ...

  private LinkedHashMap<String, String> populateSelectedEntryList(MyParser.Entry selectedResultEntry) {
    LinkedHashMap<String, String> selectedEntryMap = new LinkedHashMap<>();
    ...
    return selectedEntryMap;
  }
}

And inside Activity B,

public class B extends FragmentActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
        ...
        Intent intent = getIntent();
        LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>) intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");
  } //**********ClassCastException*****************
  ...
}

The explanation for this is given here: LinkedList put into Intent extra gets recast to ArrayList when retrieving in next activity

If you want to recover a LinkedList , or a Map where the order of the keys is not important, you can use the solution of @schtever. If you want to recover a LinkedHashMap or a TreeMap and the order of the keys is important, it is a bit more tricky.

One possible solution is to convert the Map into a pair of List s, as demonstrated below:

Activity1:

public class Activity1 extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Map<Integer, String> map = new LinkedHashMap<Integer, String>();
        map.put(1, "ONE");
        map.put(2, "TWO");
        map.put(3, "THREE");

        ArrayList<Integer> keys = new ArrayList<Integer>();
        ArrayList<String> values = new ArrayList<String>();
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            keys.add(entry.getKey());
            values.add(entry.getValue());
        }

        Intent intent = new Intent(this, Activity2.class);
        intent.putExtra("KEYS", keys);
        intent.putExtra("VALUES", values);

        startActivity(intent);
    }
}

Activity2:

public class Activity2 extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        List<Integer> keys = (List<Integer>) intent.getSerializableExtra("KEYS");
        List<String> values = (List<String>) intent.getSerializableExtra("VALUES");

        Map<Integer, String> map = new LinkedHashMap<Integer, String>();
        for (int i = 0, n = keys.size(); i < n; i++)
            map.put(keys.get(i), values.get(i));

        Log.i("Activity2",  "" + map);
    }
}

This is a bit of a hack, and it's extremely verbose, but it works. I would be interested to know if there is a better solution to this.

如果排序不重要,请使用返回的 HashMap 重新创建 LinkedHashMap:

LinkedHashMap<String, String> dataHashMap = new LinkedHashMap(intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM