Results 1 to 4 of 4
  1. #1
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    7

    Default Why is the system automatically converting my LinkedHashMap to HashMap

    I am getting

    Java Code:
    java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
    at
    Java Code:
    LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>) intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");
    in the given code of Activity B.

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

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

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

    Java Code:
    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,

    Java Code:
        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) {
    Log.i(TAG, "THE CLASS OF THE PASSED Map INTENT-ARGUMENT TO B IS " + intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY").getClass().getSimpleName()); //***PRINTS HashMap****************
            LinkedHashMap<String, String> selectedEntryMap = new LinkedHashMap<>();
            ...
            return selectedEntryMap;
          }
        }
    And inside Activity B,

    Java Code:
        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*****************
          } 
          ...
        }
    Last edited by Zarah; 08-01-2015 at 06:00 PM.

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,003
    Rep Power
    33

    Default Re: Why is the system automatically converting my LinkedHashMap to HashMap

    Look at the API doc for LinkedHashMap. Is it serializable? Is HashMap?
    If you don't understand my response, don't ignore it, ask a question.

  3. #3
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    7

    Default Re: Why is the system automatically converting my LinkedHashMap to HashMap

    Quote Originally Posted by Norm View Post
    Look at the API doc for LinkedHashMap. Is it serializable? Is HashMap?
    Yeah both are serializable:

    1. From LinkedHashMap docs,
    All Implemented Interfaces:
    Serializable, Cloneable, Map<K,V>
    2. From HashMap docs,
    All Implemented Interfaces:
    Serializable, Cloneable, Map<K,V>
    But I now know the reason, and ended up using a poor, hacky solution:

    Why (learnt from here)!

    The Extras in an intent are key-value-pairs in a Bundle, which is actually a HashMap.

    Java Code:
    intent.putExtra("tests.test.MyApp.A.EXTRA_KEY", populateSelectedEntryList(selectedResultEntry));
    In the above snippet, we are adding the key-value-pair of "tests.test.MyApp.A.EXTRA_KEY" (as the key) and the LinkedHashMap returned by populateSelectedEntryList(selectedResultEntry) (as the value) to that internal HashMap.

    Now when we call startActivity with the intent containing that Extras Bundle, the Android system needs to convert that Bundle into Byte stream, i.e. serialize the Bundle (because (1) the Activity to be started might be started in another process, so the system serializes and then deserializes the objects in the Bundle, so that it can recreate them in the other process. (2) Android saves the contents of the intent in some system tables, so that it can recreate the intent later if needed).

    So in the process of doing so, the system has to see what type the "values" in the extras' key-value-pairs are (in order to do the serialization in the most efficient way), by comparing them against a pool of known Object's ( like Integer, Long, String, Map, List, Bundle etc.), one of which is a Map. So the system finds out that the type of value is Map, so it serializes it and marks it as having the type Map.

    When this value is deserialized in

    Java Code:
    LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>) intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");
    Android converts that Map into a HashMap, and there is No way to change this behavior of Android. :-|

    The Hacky Solution

    I needed a datastructure which "maintains insertion order", "has key value pairs" and "provides index search". I needed to pass it between activities.
    The first choice was LinkedHashMap, but that ^ failed. So I passed two ArrayLists in the intent, one of keys and one of values.

    (The credit for suggesting the solution goes to the person who answered in my cross-post here I am thankful for their advice).
    Last edited by Zarah; 08-02-2015 at 10:10 AM.

  4. #4
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    13,541
    Rep Power
    27

    Default Re: Why is the system automatically converting my LinkedHashMap to HashMap

    Can't you pass a HashMap<String, LinkedHashMap>?
    Please do not ask for code as refusal often offends.

    ** This space for rent **

Similar Threads

  1. Convert JSON string to HashMap in Java
    By anjibman in forum New To Java
    Replies: 9
    Last Post: 09-12-2014, 09:14 AM
  2. HashMap vs LinkedHashMap
    By suhaas_mohandos in forum New To Java
    Replies: 10
    Last Post: 04-10-2014, 12:57 PM
  3. How to convert hashmap to treeset ?
    By javaworld in forum New To Java
    Replies: 5
    Last Post: 06-02-2013, 08:22 PM
  4. [SOLVED] LinkedHashMap
    By mtyoung in forum Advanced Java
    Replies: 6
    Last Post: 04-06-2009, 05:20 AM
  5. LinkedHashMap insertion whilst iterating
    By Paul Richards in forum Advanced Java
    Replies: 7
    Last Post: 02-13-2009, 01:24 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •