0

I have a sorted ArrayList of contacts. I want to store the list in SharedPreference. I have tried the below code:

SharedPreferences.Editor editor = app_preference.edit();
Set<String> set = new HashSet<String>();
set.addAll(contact_names_list);
editor.putStringSet("CONTACT_LIST", set);
editor.apply();

The problem is, when I retrieve this from HashSet I got an unsorted list. Is there any other way to store ArrayList other than Hashset?

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Jack
  • 1,825
  • 3
  • 26
  • 43
  • are you saying `set ` does not have ordered value ? – Ravi Jan 04 '18 at 07:33
  • You can find your answer here: https://stackoverflow.com/questions/47973805/save-sharepreference-string-to-a-listview – Patrick R Jan 04 '18 at 07:34
  • 1
    Why don't you just use a database? It will make things much easier – 0xDEADC0DE Jan 04 '18 at 07:34
  • 1
    Shared preferences store values in xml format, database is a better option – Sonu Sanjeev Jan 04 '18 at 07:35
  • `... I got an unsorted list.` and what's the problem in sorting it once it's been retrieved and before presenting it to the user? – Phantômaxx Jan 04 '18 at 07:50
  • @NoiseGenerator he wants to retain the insertion order – Willi Mentzel Jan 04 '18 at 08:31
  • 1
    @WilliMentzel Which is probably an ordered list... so, what changes, to sort it *after*? – Phantômaxx Jan 04 '18 at 08:34
  • 1
    @NoiseGenerator how can it be an ordered list? it's a HashSet in his case. how can he know the insertion order after retrieval? the information is lost then. pls, see my answer. maybe I am not thinking straight :D – Willi Mentzel Jan 04 '18 at 08:36
  • @WilliMentzel The insertion order is probably an alphabetical or by number or "by any field" order. He knows how the list should be sorted. And can use the same field to re-order the list once retrieved. – Phantômaxx Jan 04 '18 at 08:38
  • @NoiseGenerator you don't know that. that's your guess. in would see it in a more generic way. I have a sorted list and I want to keep that sorting no matter what logic it follows. – Willi Mentzel Jan 04 '18 at 08:40
  • you can check this .... it will help you https://stackoverflow.com/a/15011927/6559031 – Devil10 Jan 04 '18 at 08:41
  • @WilliMentzel True, I don't know that. I suppose the developer does know the logic s/he uses across the program. I just made a *reasonable* supposition. – Phantômaxx Jan 04 '18 at 08:57
  • @Noise Generator ,@WilliMentzel , In my app i have generated all the contacts in sorted order "ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC"", and there is an option to delete contacts from the sorted list , and i am saving the contacts list in to SharedPreference when activity onStop called , and i want to retrive the same list on next app launch .So i can not reorder the list .Hope you understood – Jack Jan 04 '18 at 09:08
  • And **why** can't you reorder the list on the name field *on retrieval*? – Phantômaxx Jan 04 '18 at 09:29
  • 1
    @Gibs I you delete items from an ordered list the resulting list is still ordered. so, why not sorting it after retrieval (what Noise Generator says)? – Willi Mentzel Jan 04 '18 at 09:56
  • Ok i can make it clear , i have a sorted list of contact names and i have a separate list of numbers of each contact.Total two lists, i want to save both lists in preference, when the user deletes a name from the app ,i want to delete the corresponding number from numbersList ,when i use hashset ,this number list also becomes orderless , so after retrivel i can reorder the name list , but what to do with number list ? – Jack Jan 05 '18 at 09:33
  • hope you understood – Jack Jan 05 '18 at 09:34
  • hashset changes the order of number list too ,so i can't reorder it based on corresponding contact list. – Jack Jan 05 '18 at 09:35

6 Answers6

0

Retrieve the values

Set<String> set = myScores.getStringSet("CONTACT_LIST", null);
KeLiuyue
  • 8,149
  • 4
  • 25
  • 42
Mohit Kalia
  • 351
  • 1
  • 6
0
static Prefs singleton = null;

public static Prefs with(Context context) {
        if (singleton == null) {
            singleton = new Builder(context).build();
        }
        return singleton;
    }

Do it this way-:

SharedPreferences.Editor editor = app_preference.edit();
        Set<String> set = new HashSet<String>();
        set.addAll(contact_names_list);
        editor.putStringSet("CONTACT_LIST", set);
        editor.apply();

or

Prefs.with(getAppContext()).putStringSet("CONTACT_LIST", set);

Retrive the values by using this code-:

Set<String> existindData = Prefs.with(getAppContext()).getStringSet("CONTACT_LIST", null);
Shivam Oberoi
  • 1,447
  • 1
  • 9
  • 18
0

Since putStringSet accepts any class which implements the Set interface you can use a LinkedHashSet which retains the order of insertion.

Documentaion of LinkedHashSet:

This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).

HashSet does not retain order of insertion, which is the problem here.

// ...

Set<String> set = new LinkedHashSet<String>();

// insert from ArrayList
set.addAll(contact_names_list);

// or single elements
set.add("Homer");
set.add("Marge");

editor.putStringSet("CONTACT_LIST", set);
Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
  • Thanks for the quick response , i have tried with LinkedHashSet but still i am getting unsorted list. – Jack Jan 04 '18 at 08:52
0

Save array in SharedPreferences :

 SharedPreferences shdPre=getSharedPreferences("MainActivity",MODE_PRIVATE);
    shdPre.edit().putInt("Size",myarray.size());
    while(i<myarray.size())
    {
shdPre.edit().remove("value"+i).commit();
shdPre.edit().putString("value"+i,myarray.get(i)).commit();
i++;
}

Load array from SharedPreferences

SharedPreferences shdPre=getSharedPreferences("MainActivity",MODE_PRIVATE);
 myarray =new ArrayList();
 Int msize=shdPre.getInt("Size",null);
 while(i<msize)
{
myarray.add(shdPre.getString("value" + i, null);
i++;
}
-1

As the Android documentation explains https://developer.android.com/training/data-storage/shared-preferences.html?hl=en the Share Preferences is a way to save Key-Value data. Given that that behind scenes that dictionary can be save in almost a random order you can't retrieve something in order. However I can recommend a couple of solutions:

  1. The easy not good performance one: Add as part of the value the index, therefore you can create an array with the size of the Hashset and then iterate the Hashset and add every element in the array that you created. O(N) temporal complexity plus the one involved in the reading process of the file.
  2. Saved the data in a local SQLite database: This solution is more flexible in future terms (you can add new contacts). https://developer.android.com/training/data-storage/sqlite.html Usually you create your own SQLite database that you put in assets and then you just import it. You can create queries to bring them in the order that you want (maybe create a column for that).

    InputStream myInput = context.getAssets( ).open( "test.db" );
    
    // Path to the just created empty db
    String outFileName = "/data/YOUR_APP/test.db";
    
    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream( outFileName );
    
    // transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while( ( length = myInput.read( buffer ) ) > 0 )
    {
        myOutput.write( buffer, 0, length );
    }
    // Close the streams
    myOutput.flush( );
    myOutput.close( );
    myInput.close( );
    
  3. Simple not scalable option: In the values folder you can always create a strings.xml file where you can put that data as a string-array. https://developer.android.com/guide/topics/resources/string-resource.html?hl=en

    <string-array name="types"> <item>A</item> <item>B and users</item> <item>C</item> <item>D</item> <item>E</item> </string-array>

If you need something more structured I have done stuff like this (saved as JSON).

<string-array name="quality_attributes">
        <item>{id:1,name:Performance,sub:[{id:2,name:Scalability},{id:3,name:Response_Time}]}</item>
        <item>{id:4,name:Security,sub:[{id:5,name:Availability,sub:[{id:6,name:Reliability},{id:7,name:Recovery}]},{id:8,name:Privacy}]}</item>
        <item>{id:9,name:Interoperability}</item>
        <item>{id:10,name:Maintainability}</item>
        <item>{id:12,name:Testability}</item>
        <item>{id:13,name:Usability,sub:[{id:14,name:Findability},{id:15,name:Correctness}]}</item>
    </string-array>

And in my code:

String[] elementsArray = getResources().getStringArray(
                R.array.quality_attributes);

        for (int i = 0; i < attributesArray.length; i++) {
            Gson gson = new Gson();
            MyJsonObject obj = gson.fromJson(elementsArray[i],
                    MyJsonObject.class);
           // Do something
        }

In general terms if you want something that needs to be change, the second options is the best one. If you are looking for something simple, the third option is good enough.

Juan Urrego
  • 343
  • 2
  • 10
-2

We can use Java 8 sorting way for sorting the collections . Set<String> s = new HashSet<String>(); s.add("Kunal"); s.add("Bhism"); s.add("Work"); s.add("Abdgg"); s.add("Psss"); s.add("Work"); List<Object> l = s.stream().sorted().collect(Collectors.toList()); System.out.println(l); Try this above code , you will get the sorted HashSet now.