2

There are many question related to this which suggests to use Comparator to compare and sort data, and I am already trying it and struggling to make it work so please don't report it as duplicate.

I have an arraylist of HashMap<String, String>

ArrayList<HashMap<String, String>>

and having data in this list in this form,

title , link and number are keys.

{ {title="",link="",number=}, {title="",link="",number=}, {title="",link="",number=} }

Example,

{ {title,link,number = 8}, {title,link,number = 1}, {title,link,number = 3} }

should be changed to,

{ {title,link,number = 1}, {title,link,number = 3}, {title,link,number = 8} }

and I wanted to sort it based on the number, I have tried this,

I create a new class (as suggested in many post to create new class to compare data) which implements Comparator.

public class SortData implements Comparator<ArrayList<HashMap<String, String>>> 

the method which is automatically implemented is ,

@Override
    public int compare(ArrayList<HashMap<String, String>> lhs,
            ArrayList<HashMap<String, String>> rhs) {


        return 0;
    }

Now this method suggest to use two arraylist of Hashmap to compare, but since I have only one arraylist which needs to be sorted so what should i use for the second arraylist ?

my Arraylist name is SecondArray, and I want to compare each value of it with the next value,

 @Override
        public int compare(ArrayList<HashMap<String, String>> lhs,
                ArrayList<HashMap<String, String>> rhs) {

                lhs = SecondArray;
                rhs = // How to compare to the next value of the same Array ? 
            return 0;
        }

How should I compare the same arraylist with the next value ?

Update: each Array list element has three key/value pairs, one of them is a number , I want to sort the arraylist based on that number , which means, key/value pairs which has the lowest number should be first in the array list.

7
  • 4
    How can a HashMap have the data { {title,link,number}, {title,link,number}, {title,link,number} }? Maps are key=value... Commented Jan 9, 2015 at 16:41
  • What exactly do you want to sort? And what exactly do you want to accomplish by sorting? This sounds like an x y problem Commented Jan 9, 2015 at 16:42
  • Do you want to sort ArrayLists of hashmaps or do you want to sort hashmaps within an ArrayList? Because what you are trying to do is compaye an arraylist to an arraylist, which would mean that you want to sort an arraylist of arraylists of hashmaps... Seems overcomplicated. O_o Commented Jan 9, 2015 at 16:43
  • 1
    chancea, each array list element has three key/value pairs, one of them is a number , I want to sort the arraylist based on that number , which means, key/value pairs which has the lowest number should be first in the array list Commented Jan 9, 2015 at 16:46
  • 2
    @joe If each has exactly 3 key-value pairs then it sounds like you should be using a data holding class for those 3 variables and not a map Commented Jan 9, 2015 at 16:48

5 Answers 5

3

Change the implements to Comparator<Hashmap<String,String>> and use:

public int compare(HashMap<String, String>> lhs,
        HashMap<String, String>> rhs) {
    return Integer.compare(Integer.parseInt(lhs.get("number")),
        Integer.parseInt(rhs.get("number")));
}

I assume you meant a list of (Hash)maps.

Sign up to request clarification or add additional context in comments.

Comments

3

I strongly suggest making a data holding class for the 3 variables and just have that class implement Comarable (you could make a separate class that implements Comparator like you have shown, but I find that to be more complicated)

After you implement comparable you can use Collections.sort to just sort your list.

Here I have complied a short example:

import java.util.*;
import java.lang.*;
import java.io.*;

class Data implements Comparable<Data>
{
    public static void main (String[] args) throws java.lang.Exception
    {
        List<Data> data = new ArrayList<Data>();
        data.add(new Data("Title1", "Link1", 8));
        data.add(new Data("Title2", "Link2", 1));
        data.add(new Data("Title3", "Link3", 3));

        for(Data d : data)
        {
            System.out.print(d.getNumber() + " ");
        }

        System.out.println();

        Collections.sort(data);

        for(Data d : data)
        {
            System.out.print(d.getNumber() + " ");
        }
    }

    private String title;
    private String link;
    private int number;

    public Data(){}
    public Data(String title, String link, int number)
    {
        setTitle(title);
        setLink(link);
        setNumber(number);
    }
    public void setTitle(String title)
    {
        this.title = title;
    }

    public void setLink(String link)
    {
        this.link = link;
    }

    public void setNumber(int number)
    {
        this.number = number;
    }

    public String getTitle()
    {
        return title;
    }

    public String getLink()
    {
        return link;
    }

    public int getNumber()
    {
        return number;
    }

    @Override
    public int compareTo(Data data)
    {
        return this.getNumber() - data.getNumber();
    }
}

Output:

8 1 3 
1 3 8 

You can try this out at Ideone

4 Comments

This answer makes more sense +1 , I will try to understand it...thanks a lot
I like the idea of implementing Comparable, but it is worth mentioning that this allows only one way of comparing. Role of Comparator is to provide additional ways to compare our data.
if this could more easily be done with simple bubble sorting why implement Comparable in the first place ?
@sufiyan because Collections does this for you. Why bother re-coding the sorting algorithm?
2

When sorting a List of Maps where the you want to sort on the key "number" I believe that you should use this instead:

    Collections.sort(myList, new Comparator<Map<String, String>>() {
        @Override
        public int compare(final Map<String, String> o1, final Map<String, String> o2) {
            // Do your sorting...
            return Integer.valueOf(o1.get("number"))
                          .compareTo(Integer.valueOf(o2.get("number")));
        }
    });

Or, if you use Java 8 you can sort List of Maps like this:

final List<Map<String, String>> sorted = 
    myList.stream()
          .sorted((m1, m2) -> Integer.valueOf(m1.get("number"))
                                     .compareTo(Integer.valueOf(m2.get("number"))))
          .collect(Collectors.toList());

Comments

2

It seems that you misunderstood concept of Comparator. This class should provide way to decide if two elements in collection should be swapped or not, so it is focussed on content of collection.

public class SortData implements Comparator<HashMap<String, String>>
//                                          ^^^^^^^^^^^^^^^^^^^^^^^

not

public class SortData implements Comparator<ArrayList<HashMap<String, String>>>
// this would sort collection of -----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
// like List<ArrayList<HashMap<String, String>>>

Also assuming that {title,link,number} are keys in your map, your compare code should probably look like

public int compare(HashMap<String, String> o1, HashMap<String, String> o2) {
    int nr1= Integer.parseInt(o1.get("number"));
    int nr2= Integer.parseInt(o2.get("number"));
    return Integer.compare(nr1, nr2);
}

But if you are sure that Map will hold only values for title, link, and number then I would create separate class for this structure like

class Data{//you should also pick better name :)
    private String title;
    private String link;//you can also use URL here instead of String,
    private int number;
    //add getters and setters for each field like
    public int getNumber(){
        return number;
    }
}

This way your comparator would be simpler

public class SortData implements Comparator<Data>{

    @Override
    public int compare(Data o1, Data o2) {
        return Integer.compare(o1.getNumber(), o2.getNumber());
    }
}

or actually since Java 8 you don't even need to create separate comparator class explicitly. You can do it implicitly with Lambdas

Comparator<Data> numberComparator =  (o1,o2)->Integer.compare(o1.getNumber(), o2.getNumber());

If you want to shorten your code you can also use method references

COmparator<Data> numberComparator = Comparator.comparingInt(Data::getNumber);

So now your list

List<Data> list = ...

can be sorted like

list.sort(numberComparator);

or

list.sort(Comparator.comparingInt(Data::getNumber));

3 Comments

Woah, Lambdas are freaking sweet. Didn't know about that
@downvoter If there is something wrong with this answer feel free to let me know about is so I could correct it. Currently answer contains explanation of problem and solution based on OP code and suggestion of how to improve it even farther. Did I miss something?
Lambdas are fun ! definitely the best answer.
1

how about not using a Comparator class and simply implementing bubble sorting ?

something like this,

for (int c = 0; c < (yourArrayList.size() - 1); c++) {
            for (int d = 0; d < (yourArrayList.size() - c - 1); d++) {
                
                if (Integer.parseInt(yourArrayList.get(d).get("number")) > Integer
                        .parseInt(yourArrayList.get(d + 1).get("number"))) {
                    
                    temporary = yourArrayList.get(d);
                    yourArrayList.set(d, yourArrayList.get(d + 1));
                    yourArrayList.set(d + 1, temporary);
                    
                }
            }
        }

Look at this example,

import java.util.ArrayList;
import java.util.HashMap;

public class Main {

    public static void main(String[] args) {

        ArrayList<HashMap<String, String>> yourArrayList = 
                new ArrayList<HashMap<String, String>>();

        HashMap<String, String> myHashMap = new HashMap<String, String>();

        myHashMap.put("title", "first Title");
        myHashMap.put("date", "This is 1st date");
        myHashMap.put("number", "5");
        yourArrayList.add(0, myHashMap);

        myHashMap = new HashMap<String, String>();

        myHashMap.put("title", "Second Title");
        myHashMap.put("date", "This is 2nd date");
        myHashMap.put("number", "2");
        yourArrayList.add(1, myHashMap);

        myHashMap = new HashMap<String, String>();

        myHashMap.put("title", "Third Title");
        myHashMap.put("date", "This is 3rd date");
        myHashMap.put("number", "7");
        yourArrayList.add(2, myHashMap);

        myHashMap = new HashMap<String, String>();

        myHashMap.put("title", "Fourth Title");
        myHashMap.put("date", "This is 4th date");
        myHashMap.put("number", "0");
        yourArrayList.add(3, myHashMap);

        System.out.println("=================");
        System.out.println("BEFORE SORTING");
        System.out.println("=================");

        for (int i = 0; i < yourArrayList.size(); i++) {
            System.out.println(yourArrayList.get(i));
        }

        HashMap<String, String> temporary;

        for (int c = 0; c < (yourArrayList.size() - 1); c++) {
            for (int d = 0; d < (yourArrayList.size() - c - 1); d++) {

                if (Integer.parseInt(yourArrayList.get(d).get("number")) > Integer
                        .parseInt(yourArrayList.get(d + 1).get("number"))) {

                    temporary = yourArrayList.get(d);
                    yourArrayList.set(d, yourArrayList.get(d + 1));
                    yourArrayList.set(d + 1, temporary);

                }
            }
        }

        System.out.println("=================");
        System.out.println("AFTER SORTING");
        System.out.println("=================");

        for (int i = 0; i < yourArrayList.size(); i++) {
            System.out.println(yourArrayList.get(i));
        }

    }

}

Output,

=================
BEFORE SORTING
=================
{date=This is 1st date, number=5, title=first Title}
{date=This is 2nd date, number=2, title=Second Title}
{date=This is 3rd date, number=7, title=Third Title}
{date=This is 4th date, number=0, title=Fourth Title}
=================
AFTER SORTING
=================
{date=This is 4th date, number=0, title=Fourth Title}
{date=This is 2nd date, number=2, title=Second Title}
{date=This is 1st date, number=5, title=first Title}
{date=This is 3rd date, number=7, title=Third Title}

You can test it here -> http://ideone.com/E0XXoN

8 Comments

@Joe bubble sorting is very far away from effective one (see example video youtube.com/watch?v=ZZuD6iUe3Pc) but it is indeed simple one. If you are looking for effective solution use default sort method which uses effective algorithms (currently in most cases slightly optimized version of merge-sort is used), your only job would be provide code which should decide if two elements should be swapped (Comparator), so you don't have to implement sorting algorithm, which main job is to pick which elements should be compared ( and swapped if they are in wrong positions).
@Joe That is the point, with comparator you don't even need to write nested loop, you just write logic for swap condition like in for () {for () {if(*swapCondition*){swap} } }, so all you have to do is use list.sort(comparator).
@Joe To give you example of what I am saying lets rewrite this answer a little. Instead of for (int c,...)for(){ ... }} loop all you need to do is write comparator which will compare value of number like pastebin.com/9HY8B9Rn and use it like Collections.sort(yourList,comparator) or yourList.sort(comparator) depending on if you have Java 8 or not. You can shorten this code farther with lambdas and Comparator generator for integer values. Your entire code could be yourList.sort(Comparator.comparingInt(map -> Integer.parseInt(map.get("number"))));
thanks a lot @Pshemo, this certainly works better...i have one question, in your pastebin code how did you open curly braces after terminating the statement ? I mean new Comparator<HashMap<String, String>>() { <-- How did you open this bracket ? what this phenomeon is called ?
@Joe It is anonymous class. It is nested class but without specified name. Judging by fact that you are not familiar with them you will probably need to put learning lambdas after you will learn about it.
|

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.