Android LinkedHashMap反序列化为HashMap,导致CCE错误 [英] Android LinkedHashMap deserializing as HashMap, causes CCE error

查看:124
本文介绍了Android LinkedHashMap反序列化为HashMap,导致CCE错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在活动之间传递序列化的LinkedHashMap,并在反序列化对象时遇到令人困惑的结果/错误。

I'm attempting to pass a serialized LinkedHashMap between activities, and getting a confusing result/error when I deserialize the object.

我按如下方式序列化对象:

I serialize the object as follows:

    Bundle exDetails = new Bundle();
    LinkedHashMap<String, Exercise> exMap = new LinkedHashMap<String, 
    Exercise (workout.getExercises());

    exDetails.putString(WORKOUTNAME, workout.getWorkoutName());
    exDetails.putSerializable(workout.getWorkoutName(), exMap);

    iComplete.putExtra("wName", exDetails);
    startActivity(iComplete);

似乎工作正常,问题出现在下一个活动中:

That seems to work fine, the problem shows up in the next activity:

    Bundle exDetails =  getIntent().getBundleExtra("wName");
    workoutName = exDetails.getString(WORKOUTNAME);
    Serializable eData = exDetails.getSerializable(workoutName);

    ex = new LinkedHashMap<String, Exercise>();
    ex = (LinkedHashMap<String, Exercise>) eData;

此时,反序列化对象(eData)包含一个HashMap对象(不是LinkedHashMap),并且给我

At this point, the deserialized object (eData) contains a HashMap object (not LinkedHashMap), and it gives me

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

。我已经通过调试器进行了验证,该捆绑包(在第二个活动中)包含一个HashMap,而不是LinkedHashMap(我认为应该如此)。我还应该提到,我需要保持将条目添加到Map的顺序,因此需要使用LinkedHashMap。最终将打印出条目,并且顺序对于输出非常重要。

on that last line. I've verified with the debugger that the bundle (in the second activity) contains a HashMap, instead of a LinkedHashMap (as I'm assuming it should). I should also mention that I need to maintain the order in which entries are added to the Map, hence the usage of LinkedHashMap. The entries eventually get printed, and order is very important for the output.

问题:
我是否特别在做任何错误,或者是由于LinkedHashMap的序列化错误导致此问题?我注意到一些类似的线程,似乎在说这是一些Map实现的持续问题。但是,他们并没有直接回答我的问题。

Questions: Am I doing anything wrong in particular, or is this problem due to bugs with LinkedHashMap's serialization? I've noticed a few similar threads, that seem to speak of this being an ongoing problem with several of the Map implementations. They didn't answer my problem directly though.

如果是后者,是否有一种不太先进的解决方法(我距离初学者不远,但是我愿意尝试大多数事情),还是我只需要硬着头皮去做LinkedHashMap以外的工作?

If the latter, is there a workaround that isn't too advanced (I'm not far beyond beginner level, but I'm willing to try most things), or do I need to just bite the bullet and work something other than LinkedHashMap?

Ps我试图包括所有相关内容,但是如果我遗漏了任何重要内容,我可以添加更多代码。

P.s. I tried to include everything relevant, but I can add more code if I left out anything important.

推荐答案

方法:将Map的任何(类型)序列化为2个ArrayLists:一个包含键,另一个包含值。这样,地图条目的顺序(在LinkedHashMap中很重要)得以保留。

I went for a different approach: serialize any (type of) Map into 2 ArrayLists: one containing the keys and the other one containing the values. This way, the order of the map entries (important in a LinkedHashMap) is kept.

每个键/值都实现了Serializable。如果您确定只需要字符串或仅一种特定类型的Map,那么将以下通用代码转换成所需的场景确实很容易,这也简化了复杂性。

Each key/value implements Serializable. If you know for sure you need just Strings or just one particular type of Map, then it should be really easy to convert the following generic code into the scenario needed which also simplifies the complexity.


Map-> 2 ArrayLists:

Map -> 2 ArrayLists:



public static <K extends Serializable, V extends Serializable> Pair<ArrayList<K>, ArrayList<V>> convertMapToArrays(@NonNull Map<K, V> map) {
        final Set<Map.Entry<K, V>> entries = map.entrySet();
        final int size = entries.size();
        final ArrayList<K> keys = new ArrayList<>(size);
        final ArrayList<V> values = new ArrayList<>(size);
        for (Map.Entry<K, V> entry : entries) {
            keys.add(entry.getKey());
            values.add(entry.getValue());
        }
        return new Pair<>(keys, values);
}




2 ArrayLists->特定类型的映射

2 ArrayLists -> Map of a specific type



 public static <K extends Serializable, V extends Serializable> Map<K, V> convertArraysToMap(@NonNull ArrayList<K> keys, @NonNull ArrayList<V> values, @NonNull Class<? extends Map<K, V>> mapClass) {
        if (keys.size() != values.size()) {
            throw new RuntimeException("keys and values must have the same number of elements");
        }
        final int size = keys.size();
        Map<K, V> map;
        try {
            final Constructor<? extends Map<K, V>> constructor = mapClass.getConstructor(Integer.TYPE);
            map = constructor.newInstance(size);
        } catch (Exception nse) {
            throw new RuntimeException("Map constructor that accepts the initial capacity not found.");
        }

        for (int i = 0; i < size; i++) {
            final K key = keys.get(i);
            final V value = values.get(i);
            map.put(key, value);
        }
        return map;
    }




Android捆绑软件的助手:

Helpers for Android's Bundle:



 public static <K extends Serializable, V extends Serializable> void saveMapToBundleAsArrays(@NonNull Map<K, V> map, @NonNull String key, @NonNull Bundle bundle) {
        final Pair<ArrayList<K>, ArrayList<V>> mapToArrays = convertMapToArrays(map);
        final String keyForKeys = key + "_keys";
        final String keyForValues = key + "_values";
        bundle.putSerializable(keyForKeys, mapToArrays.first);
        bundle.putSerializable(keyForValues, mapToArrays.second);
    }

public static Map<Serializable, Serializable> loadMapFromBundle(@NonNull Bundle bundle, @NonNull String key, @NonNull Class<? extends Map<Serializable, Serializable>> mapClass) {
        final String keyForKeys = key + "_keys";
        final String keyForValues = key + "_values";
        final ArrayList<Serializable> keys = (ArrayList<Serializable>) bundle.getSerializable(keyForKeys);
        final ArrayList<Serializable> values = (ArrayList<Serializable>) bundle.getSerializable(keyForValues);
        return convertArraysToMap(keys, values, mapClass);
    }




用法:

Usage:



saveMapToBundleAsArrays(mModelEvolution, KEY_MODEL_DATA, bundle);

Class<LinkedHashMap<Serializable, Serializable>> linkedHashMapClazz =
                (Class<LinkedHashMap<Serializable, Serializable>>) new LinkedHashMap<String, String>().getClass();
mModelEvolution = (LinkedHashMap) ObjectUtils.loadMapFromBundle(bundle, KEY_MODEL_DATA, linkedHashMapClazz);

这篇关于Android LinkedHashMap反序列化为HashMap,导致CCE错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆