有人能解释一下SharedPreferences如何存储字符串集合吗?

3
我曾尝试使用SharedPreferences来保存一组名字,并且想要利用putStringSet方法,这样就不需要多个键值对了。我知道常规的HashSet无法保证迭代顺序,所以我使用了LinkedHashSet来维护插入的顺序,并将其保存到SharedPreferences中。
当我检索相同的字符串集时,我也使用了LinkedHashSet,但顺序与最初插入时不同。我通过仅存储逗号分隔的字符串并解析该字符串来解决了该问题,因此这不是我的问题。
我想知道SharedPreferences对一组字符串所做的操作,以使其不能保持正确的排序(至少不是我想要的那种)。
2个回答

4

简而言之,它通过从值创建一个简单的HashSet来取消关联您的已链接哈希集...从那时起 - 没有顺序链接。

源代码如下:

public Editor putStringSet(String key, Set<String> values) {
        synchronized (this) {
            mModified.put(key,
                    (values == null) ? null : new HashSet<String>(values));
            return this;
        }
    }

这就是为什么,如果你想保留顺序,你需要将其存储为带有分隔符的字符串(你使用了逗号),然后拆分分隔符以获得数组。

很直接的,我猜。谢谢,得经常查看源代码。 - Moshe Stauber
是的,我经常这样做。然后最终不得不扩展很多本地类来添加自定义功能... :-) - daxgirl

-1

我经常使用的一个技巧是 JSON。 将复杂对象转换为 JSON 并将其保存为简单字符串到 SharedPreferences 中非常容易。
你只需要几行代码即可完成此操作。

看一下受欢迎的 JSON 库,例如 GSONJackson

这是一个实用类,您可以使用它将对象转换为 JSON 和相反方向。

public class JsonUtils {
    private JsonUtils() {
    }
    public static String convertObjectToJSONString(Object object) {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonObject = "";
        try {
            jsonObject = objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonObject;
    }
    public static<T> T parseObjectFromString(String json,Class<T> objectClass) {
        ObjectMapper objectMapper = new ObjectMapper();
        T object = null;
        try {
            object = objectMapper.readValue(json, objectClass);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return object;
    }
}

如果您仍然想将 String Set 保存到共享首选项中,那么您不应该错过的一件事情就是删除旧集合,然后插入新集合。
Set<String> stringSet = sharedPrefs.getStringSet("set-key", new HashSet<String>());
            stringSet.add("Hello World");
            Editor edit = sharedPrefs.edit();
            edit.remove("set-key");
            edit.apply();
            edit.putStringSet("set-key", stringSet);

此外,您也可以只使用普通的 ObjectOutputStream 将对象转换为 byte[]String,然后保存它。但是正如许多人注意到的那样,这超出了本问题的范围。

1
这如何回答如何存储一组字符串的问题? - OneCricketeer
1
这完全没有回答问题。 - java8.being
虽然没有回答问题,但将来会很有用。谢谢! - Moshe Stauber
1
@p1g1n,我刚刚更新了答案,请看一下。 - CROSP
1
这是一个不错的技巧。但是有两个问题。使用HashSet会混合条目值而不保留顺序。发帖者想要保留确切的顺序,这很难通过本地类来实现。其次,除非你在后台线程上,否则不应该使用commit()而应该使用apply()。 - daxgirl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接