How can I save a HashMap Object into Shared Preferences in Android?
-
1try this http://stackoverflow.com/a/39435730/6561141 – mrtpk Sep 13 '16 at 08:57
12 Answers
I use Gson
to convert HashMap
to String
and then save it to SharedPrefs
private void hashmaptest()
{
//create test hashmap
HashMap<String, String> testHashMap = new HashMap<String, String>();
testHashMap.put("key1", "value1");
testHashMap.put("key2", "value2");
//convert to string using gson
Gson gson = new Gson();
String hashMapString = gson.toJson(testHashMap);
//save in shared prefs
SharedPreferences prefs = getSharedPreferences("test", MODE_PRIVATE);
prefs.edit().putString("hashString", hashMapString).apply();
//get from shared prefs
String storedHashMapString = prefs.getString("hashString", "oopsDintWork");
java.lang.reflect.Type type = new TypeToken<HashMap<String, String>>(){}.getType();
HashMap<String, String> testHashMap2 = gson.fromJson(storedHashMapString, type);
//use values
String toastString = testHashMap2.get("key1") + " | " + testHashMap2.get("key2");
Toast.makeText(this, toastString, Toast.LENGTH_LONG).show();
}

- 4,743
- 35
- 37
-
2how to get hashmap from gson i got error msg like com.qb.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 – – Ram Feb 26 '15 at 10:46
-
Expected BEGIN_OBJECT but was BEGIN_ARRAY is happening because HashMap
should be HashMap – Stoycho Andreev Jul 13 '16 at 22:11, if the values are always String object you will not have any problems but if the value of some key is diff then String (for example custom object , or list or array) then exception will be thrown . So to be able to parse back everything you need HashMap
I would not recommend writing complex objects into SharedPreference. Instead I would use ObjectOutputStream
to write it to the internal memory.
File file = new File(getDir("data", MODE_PRIVATE), "map");
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
outputStream.writeObject(map);
outputStream.flush();
outputStream.close();

- 42,195
- 18
- 124
- 148
-
6
-
5here is an example how to use ObjectOutputStream and ObjectInputStream together: http://www.tutorialspoint.com/java/io/objectinputstream_readobject.htm – Krzysztof Skrzynecki Apr 20 '15 at 11:27
-
2Since when Hashmap is a complex object? How did you assume this? – Pedro Paulo Amorim Mar 02 '20 at 13:42
-
1Why do you not recommend putting objects like a HashMap into SharedPreference? – TomV Jan 11 '21 at 16:43
-
When you write to sharedpreferences you save key-value data so it's not that much different from saving a hashmap – Marina Dunst Mar 14 '21 at 15:51
private void saveMap(Map<String,Boolean> inputMap) {
SharedPreferences pSharedPref = getApplicationContext().getSharedPreferences("MyVariables", Context.MODE_PRIVATE);
if (pSharedPref != null){
JSONObject jsonObject = new JSONObject(inputMap);
String jsonString = jsonObject.toString();
pSharedPref.edit()
.remove("My_map")
.putString("My_map", jsonString)
.apply();
}
}
private Map<String,Boolean> loadMap() {
Map<String,Boolean> outputMap = new HashMap<>();
SharedPreferences pSharedPref = getApplicationContext().getSharedPreferences("MyVariables", Context.MODE_PRIVATE);
try {
if (pSharedPref != null) {
String jsonString = pSharedPref.getString("My_map", (new JSONObject()).toString());
if (jsonString != null) {
JSONObject jsonObject = new JSONObject(jsonString);
Iterator<String> keysItr = jsonObject.keys();
while (keysItr.hasNext()) {
String key = keysItr.next();
Boolean value = jsonObject.getBoolean(key);
outputMap.put(key, value);
}
}
}
} catch (JSONException e){
e.printStackTrace();
}
return outputMap;
}

- 8,948
- 9
- 47
- 69

- 6,448
- 2
- 41
- 37
-
-
-
@Dmitry A shortcut: In your simple class, include set context method and set the context as member variable and use it accordingly – Vinoj John Hosan Aug 24 '18 at 11:50
-
What's the point of the strangely complicated default value for `getString()`? Wouldn't a simple null or empty string work just as well? – SMBiggs Jun 29 '21 at 14:59
-
This code is bad: 1) you catch a generic exception instead of a json exception. Why do you need the generic? Since you may have NPE, which you can avoid by checking for null of the json string (you already do this for the shared preference). – elcuco Sep 02 '21 at 13:02
-
This code is bad: 2) for saving you commit twice instead of a single apply at the editor also chain the responces of the editor - into a single logical command. – elcuco Sep 02 '21 at 13:05
Map<String, String> aMap = new HashMap<String, String>();
aMap.put("key1", "val1");
aMap.put("key2", "val2");
aMap.put("Key3", "val3");
SharedPreferences keyValues = getContext().getSharedPreferences("Your_Shared_Prefs"), Context.MODE_PRIVATE);
SharedPreferences.Editor keyValuesEditor = keyValues.edit();
for (String s : aMap.keySet()) {
keyValuesEditor.putString(s, aMap.get(s));
}
keyValuesEditor.commit();

- 54,294
- 25
- 151
- 185

- 30,580
- 6
- 55
- 83
-
but i need to save the hash map as itself like we adding vector into the shared preferences – jibysthomas Oct 30 '11 at 13:33
-
than you have to probably use serialization and save the serialized HashMap in SharedPrefs. You can easily find code-examples on how to do that. – hovanessyan Oct 30 '11 at 13:49
As a spin off of Vinoj John Hosan's answer, I modified the answer to allow for more generic insertions, based on the key of the data, instead of a single key like "My_map"
.
In my implementation, MyApp
is my Application
override class, and MyApp.getInstance()
acts to return the context
.
public static final String USERDATA = "MyVariables";
private static void saveMap(String key, Map<String,String> inputMap){
SharedPreferences pSharedPref = MyApp.getInstance().getSharedPreferences(USERDATA, Context.MODE_PRIVATE);
if (pSharedPref != null){
JSONObject jsonObject = new JSONObject(inputMap);
String jsonString = jsonObject.toString();
SharedPreferences.Editor editor = pSharedPref.edit();
editor.remove(key).commit();
editor.putString(key, jsonString);
editor.commit();
}
}
private static Map<String,String> loadMap(String key){
Map<String,String> outputMap = new HashMap<String,String>();
SharedPreferences pSharedPref = MyApp.getInstance().getSharedPreferences(USERDATA, Context.MODE_PRIVATE);
try{
if (pSharedPref != null){
String jsonString = pSharedPref.getString(key, (new JSONObject()).toString());
JSONObject jsonObject = new JSONObject(jsonString);
Iterator<String> keysItr = jsonObject.keys();
while(keysItr.hasNext()) {
String k = keysItr.next();
String v = (String) jsonObject.get(k);
outputMap.put(k,v);
}
}
}catch(Exception e){
e.printStackTrace();
}
return outputMap;
}

- 8,302
- 6
- 48
- 68
-
-
@Dmitry You would do this in the same way you would access the `Context` instance from a library. Check out this other SO question: [Is it possible to get application's context in an Android Library Project?](https://stackoverflow.com/q/7157501/940217) – Kyle Falconer Aug 20 '18 at 18:41
map -> string
val jsonString: String = Gson().toJson(map)
preferences.edit().putString("KEY_MAP_SAVE", jsonString).apply()
string -> map
val jsonString: String = preferences.getString("KEY_MAP_SAVE", JSONObject().toString())
val listType = object : TypeToken<Map<String, String>>() {}.type
return Gson().fromJson(jsonString, listType)

- 159
- 1
- 3
You could try using JSON instead.
For saving
try {
HashMap<Integer, String> hash = new HashMap<>();
JSONArray arr = new JSONArray();
for(Integer index : hash.keySet()) {
JSONObject json = new JSONObject();
json.put("id", index);
json.put("name", hash.get(index));
arr.put(json);
}
getSharedPreferences(INSERT_YOUR_PREF).edit().putString("savedData", arr.toString()).apply();
} catch (JSONException exception) {
// Do something with exception
}
For getting
try {
String data = getSharedPreferences(INSERT_YOUR_PREF).getString("savedData");
HashMap<Integer, String> hash = new HashMap<>();
JSONArray arr = new JSONArray(data);
for(int i = 0; i < arr.length(); i++) {
JSONObject json = arr.getJSONObject(i);
hash.put(json.getInt("id"), json.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
}

- 2,591
- 1
- 22
- 40
You can use this in a dedicated on shared prefs file (source: https://developer.android.com/reference/android/content/SharedPreferences.html):
getAll
added in API level 1 Map getAll () Retrieve all values from the preferences.
Note that you must not modify the collection returned by this method, or alter any of its contents. The consistency of your stored data is not guaranteed if you do.
Returns Map Returns a map containing a list of pairs key/value representing the preferences.

- 10,654
- 2
- 52
- 51
-
I think this is actually a better and simpler idea. You just create a dedicated SharedPreferences for this map and you are good to go besides an extra transformation from/to the actual data type. – Henry Aug 21 '21 at 17:03
String converted = new Gson().toJson(map);
SharedPreferences sharedPreferences = getSharedPreferences("sharepref",Context.MODE_PRIVATE);
sharedPreferences.edit().putString("yourkey",converted).commit();
The lazy way: storing each key directly in SharedPreferences
For the narrow use case when your map is only gonna have no more than a few dozen elements you can take advantage of the fact that SharedPreferences works pretty much like a map and simply store each entry under its own key:
Storing the map
Map<String, String> map = new HashMap<String, String>();
map.put("color", "red");
map.put("type", "fruit");
map.put("name", "Dinsdale");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// OR use a specific pref name
// context.getSharedPreferences("myMegaMap");
for (Map.Entry<String, String> entry : map.entrySet()) {
prefs.edit().putString(entry.getKey(), entry.getValue());
}
Reading keys from the map
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// OR use a specific pref name
// context.getSharedPreferences("myMegaMap");
prefs.getString("color", "pampa");
In case where you use a custom preference name (i.e. context.getSharedPreferences("myMegaMap")
) you can also get all keys with prefs.getAll()
Your values can be of any type supported by SharedPreferences:
String
,int
,long
,float
,boolean
.

- 28,968
- 18
- 162
- 169
using File Stream
fun saveMap(inputMap: Map<Any, Any>, context: Context) {
val fos: FileOutputStream = context.openFileOutput("map", Context.MODE_PRIVATE)
val os = ObjectOutputStream(fos)
os.writeObject(inputMap)
os.close()
fos.close()
}
fun loadMap(context: Context): MutableMap<Any, Any> {
return try {
val fos: FileInputStream = context.openFileInput("map")
val os = ObjectInputStream(fos)
val map: MutableMap<Any, Any> = os.readObject() as MutableMap<Any, Any>
os.close()
fos.close()
map
} catch (e: Exception) {
mutableMapOf()
}
}
fun deleteMap(context: Context): Boolean {
val file: File = context.getFileStreamPath("map")
return file.delete()
}
Usage Example:
var exampleMap: MutableMap<Any, Any> = mutableMapOf()
exampleMap["2"] = 1
saveMap(exampleMap, applicationContext) //save map
exampleMap = loadMap(applicationContext) //load map

- 914
- 10
- 14
You don't need to save HashMap to file as someone else suggested. It's very well easy to save a HashMap and to SharedPreference and load it from SharedPreference when needed. Here is how:
Assuming you have a
class T
and your hash map is:
HashMap<String, T>
which is saved after being converted to string like this:
SharedPreferences sharedPref = getSharedPreferences(
"MyPreference", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("MyHashMap", new Gson().toJson(mUsageStatsMap));
editor.apply();
where mUsageStatsMap is defined as:
HashMap<String, T>
The following code will read the hash map from saved shared preference and correctly load back into mUsageStatsMap:
Gson gson = new Gson();
String json = sharedPref.getString("MyHashMap", "");
Type typeMyType = new TypeToken<HashMap<String, UsageStats>>(){}.getType();
HashMap<String, UsageStats> usageStatsMap = gson.fromJson(json, typeMyType);
mUsageStatsMap = usageStatsMap;
The key is in Type typeMyType which is used in * gson.fromJson(json, typeMyType)* call. It made it possible to load the hash map instance correctly in Java.

- 4,431
- 35
- 29