0

So I'm working on an app and I have a button in which the user clicks to cycle through three ordering sets for an array list. I have it where Collections.sort(list) sorts the list numerically and alphabetically, but I'm trying to make it where listis sorted by either index number or time added.

Here's what I have:

public class MainActivity extends Activity 
{
    ArrayList<String> list;
    ArrayAdapter adapter;
    ListView listView;
    public int counter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        list = new ArrayList<>();
        listView = findViewById(R.id.listView);
        adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,list);
        listView.setAdapter(adapter);
        addEntries();

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){

                @Override
                public void onItemClick(AdapterView<?> p1, View p2, int p3, long p4)
                {

                }
        });
    }

    public void addEntries(){
        for(int e=0; e<=10; e++){
            list.add(String.valueOf(e));
        }
        adapter.notifyDataSetChanged();
    }

    public void sort(View v){
        counter = counter + 1;
        if(counter == 2){
            counter = 0;
        }
        switch(counter){
            case 0:Collections.sort(list);
            message("0");
            break;

            case 1://code to sort by time/index;
            message("1");
            break;

        }
        adapter.notifyDataSetChanged();
    }

    public void message(String message){
        Toast.makeText(getApplicationContext(),message,Toast.LENGTH_SHORT).show();
    }
}

2 Answers 2

1

Latest Answer

This is best done storing a object instead of a string in your list.

class Info {
  String value;
  Long time;
  int index;
}

new ArrayList<Info>()

When your item is added, update the timestamp, and set the index to the list length.

Then sort by field

list.sort((a,b)-> a.time - b.time )
list.sort((a,b)-> a.value.compareTo(b.value) )
list.sort((a,b)-> a.index - b.index )

You can easily get your original list of strings using a map function.

list.map(it->it.value)

Other issues

  • You will need to re-sort when items are added.

  • There are shortcut notations to the above lambdas.


Older Answer

Otherwise you need to get the time from somewhere else (map, etc):

list.sort((a,b)-> getTimeFromSomewhere(a) - getTimeFromSomewhere(b) )

You should really make a copy so you still have the original index based list when sorting by index:

new ArrayList<String>(list).sort((a,b)-> getTimeFromSomewhere(a) - getTimeFromSomewhere(b) )

To sort by index, return a copy of your original list.

new ArrayList<String>(list)

To sort alphabetically, return a copy of your original list using the default sort

new ArrayList<String>(list).sort()
Sign up to request clarification or add additional context in comments.

6 Comments

Would this still work if the list was user created? I want it to eventually get to a point where the user can make multiple entries and be able to sort it with the push of a button. I don't think there would ever be an "original list" if the user was able to make entries at different times, would it?
When the user adds another item to the original list, you will call sort again. The only reason you need the original list is to remember the index order. It would make more sense to have a list of objects containing string value, timestamp, and index. Use my first example to sort based on each object field.
@CouchMango I updated answer with a suggest design change.
I'll give these a try and get back with you
Ok, this just doesn't make sense to me. What do you mean make a copy of the list? Is there not a way to simply sort the strings in the arraylist by index? I shouldn't have said time because I want the entries in order from which they were added to the Arraylist.
|
0
    ArrayList<String> list = new ArrayList<>();
    for (int e = 0; e <= 10; e++) {
        list.add(String.valueOf(e));
    }

    Collections.sort(list);
    System.out.println("Sorted as strings:  " + list);

    Collections.sort(list, Comparator.comparingInt(Integer::parseInt));
    System.out.println("Sorted numerically: " + list);

Output:

Sorted as strings:  [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]
Sorted numerically: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Comparator.comparingInt is new in Java 8 and may only be available on newer Android versions. The Java 7 equivalent is wordier, but exists. Your search engine can help.

A more gold-plated solution: design a model class and make a list of instances of that class, not a list of string. Have your class include an Instant creation time so you may sort by it.

Could you give an example?

Edit: Here’s a simple example of a model class. You know better what your entries are and what needs to go into an entry.

public class Entry {

    String name;
    final Instant created = Instant.now();

    public Entry(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Instant getCreated() {
        return created;
    }

    @Override
    public String toString() {
        return name;
    }

}

Putting instances of this class into a list and sorting it:

        ArrayList<Entry> list = new ArrayList<>();
        for (int e = 0; e <= 10; e++) {
            list.add(new Entry(String.valueOf(e)));
        }

        Collections.sort(list, Comparator.comparing(Entry::getName));
        System.out.println("Sorted by name:          " + list);

        Collections.sort(list, Comparator.comparing(Entry::getCreated));
        System.out.println("Sorted by creation time: " + list);

Since the toString method of the model class just prints the name (not the creation time), output is very similar to what it was before:

Sorted by name:          [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]
Sorted by creation time: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

If you want to see that we have really sorted our own objects rather than strings, you may experiment with changing the toString method. An example:

    @Override
    public String toString() {
        return name + ' ' + created.atZone(ZoneId.of("Pacific/Niue"));
    }

2 Comments

Could you give an example? You'd definately be showing me something new.
I'll try this as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.