0

I am relatively new to Java, and the whole sort by using comparators is a bit confusing to me.

Is it possible to sort the current output of the code below in descending order without using comparators?

Or is there an easier way for me to understand how to sort said values.

myRef.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(@NonNull DataSnapshot dataSnapshot , String s) {
        Map<String, Object> userInfo = (Map<String, Object>)dataSnapshot.getValue();
        String username = (String) userInfo.get("username");

        Map<String, Long> steps = (Map<String, Long>) userInfo.get("steps");

        long existingSteps = 0;
        for (Map.Entry<String, Long> step : steps.entrySet()) {
            existingSteps += Long.valueOf(step.getValue());
        }

        arrayList.add(new String( username + "  -  " + "steps:  " + existingSteps));

        arrayAdapter = new ArrayAdapter<>(Leaderboard.this , 
        android.R.layout.simple_list_item_1 , arrayList);

        listView.setAdapter(arrayAdapter);
}

The current output of this code is:

John Doe I - Steps: 79
John Doe II - Steps: 111
John Doe III - Steps: 0
John Doe IV - Steps: 88
John Doe V - Steps: 12
John Doe VI - Steps: 0

Is it possible to get this code to run the following output:

John Doe II - Steps: 111
John Doe IV - Steps: 88
John Doe I - Steps: 79
John Doe V - Steps: 12
John Doe III - Steps: 0
John Doe VI - Steps: 0

Database Structure

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Molinho
  • 31
  • 1
  • 6
  • use sortmap for java, – hemen May 27 '19 at 12:57
  • 2
    Possible duplicate of [Sort a Map by values](https://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values) – Dinesh Shingadiya May 27 '19 at 13:00
  • How is `myRef` defined? Please also add your database structure and responde with @AlexMamo – Alex Mamo May 27 '19 at 13:02
  • Either use a TreeMap with a custom comparator https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html#TreeMap-java.util.Comparator- or use a SortedSet to get the map values. But this is all about comparators... – Maia May 27 '19 at 13:04
  • `DatabaseReference myRef;` `myRef = database.getReference("user");` myRef is defined as stated above @AlexMamo – Molinho May 27 '19 at 13:08
  • Please also add a screenshot to see the content of an object within user node. – Alex Mamo May 27 '19 at 13:13
  • changed the screenshot to one with an open node @AlexMamo – Molinho May 27 '19 at 13:17
  • Since I'm relatively new to it, I don't exactly understand how to use the answers given in your link @DineshShingadiya I've tried to do what they say but I doesn't make any sense to me. – Molinho May 27 '19 at 13:24
  • @Molinho I see now. I'll write you an answer right away. – Alex Mamo May 27 '19 at 13:25

1 Answers1

2

The simplest solution I can think of, is to add under each user object, the total number of steps, as a new property. In this case, there is one more thing that you need to do, which is to increment that property with the number of steps that you get every day. Your new schema should look like this:

Firebase-root
  |
  --- user
       |
       --- userId
            |
            --- steps
            |    |
            |    --- //daily steps
            |
            --- target: 100
            |
            --- username: "John Doe I"
            |
            --- totalNumberOfSteps: 111

To get the users in (ascending) order according to the totalNumberOfSteps property, please use the following lines of code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userRef = rootRef.child("user");
Query query = userRef.orderByChild("totalNumberOfSteps");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String username = ds.child("username").getValue(String.class);
            long totalNumberOfSteps = ds.child("totalNumberOfSteps").getValue(Long.class);
            Log.d(TAG, username + " - Steps: " + totalNumberOfSteps);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};
query.addListenerForSingleValueEvent(valueEventListener);

Then to order it descending, please see my answer from the following post:

Finally, the result in the logcat will be:

John Doe II - Steps: 111
John Doe IV - Steps: 88
John Doe I - Steps: 79
John Doe V - Steps: 12
John Doe III - Steps: 0
John Doe VI - Steps: 0
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Does this also include data which gets added later on, for example the steps I walk tomorrow are those taken into account aswell ? – Molinho May 27 '19 at 13:45
  • Yes, it will as long as you update the `totalNumberOfSteps` property daily this the corresponding number of steps. – Alex Mamo May 27 '19 at 13:46
  • Is it possible to make it update automatically, or is manually the only option ? – Molinho May 27 '19 at 13:48
  • You can also make it automatically but you need to write code yourself. The operation is simple, in every user object, iterate throught the `steps` object to get all steps. Once you have the number of all steps, simply write it in the new property. That's it, simple as that. – Alex Mamo May 27 '19 at 13:50
  • Yeah, that's what I have at the moment, it iterates through the steps with `long existingSteps = 0; for (Map.Entry step : steps.entrySet()) { existingSteps += Long.valueOf(step.getValue()); }` This way it automatically stores the sum in "existingSteps" but then I'm still left with the unsorted pile of numbers. I'll try your method nevertheless, manually isn't a problem either. Thanks for answering! – Molinho May 27 '19 at 13:53
  • Yes, in this case you only need to write that value to the database. – Alex Mamo May 27 '19 at 13:53
  • I tried using your code Alex but it doesn't work, it doesn't give any errors, but the order stays the same even when adding the code to order it by ascending order. – Molinho May 28 '19 at 14:44
  • "It doesn't work" will not help me understand the problem and without seeing the code that you are using, I cannot be much of a help. – Alex Mamo May 28 '19 at 14:49
  • I see now, that you have asked another question, which is ussualy the best practice. So I definitely recommend you use Frank van Puffelen's [answer](https://stackoverflow.com/a/56343559/5246885). – Alex Mamo May 28 '19 at 14:51
  • I've added a property `totalNumberOfSteps` in my database and afterwards added your line of code within my `myRef` statement – Molinho May 28 '19 at 15:09
  • I this case, I recommend you post another fresh question using the entire code you have used, so me and other Firebase developers can help you. The code above works as I tested it before so should also work in your case. – Alex Mamo May 28 '19 at 15:33
  • hopefully you can take a look: https://stackoverflow.com/questions/56345948/how-to-get-firebase-data-listed-in-ascending-order-when-using-an-arraylist – Molinho May 28 '19 at 15:52
  • @Molinho Ok, I'll take a look. – Alex Mamo May 28 '19 at 15:53