如何基于Value对Map进行排序,即具有多个属性的Object

时间:2015-01-02 19:21:46

标签: java dictionary collections

我有一个非常简单的代码来根据不在键上的值对HashMap进行排序(从SO复制,但在SO上只是排序String,我想根据对象的属性进行排序)

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class SortMapByValue
{
    public static boolean ASC = true;
    public static boolean DESC = false;

    public static void main(String[] args)
    {
Person person = new Person(21, "John", 174, "Doe");
    Person personTwo = new Person(19, "Michael", 154, "Jordan");
    Person personThree = new Person(22, "David", 184, "Sun");
    Person personFour = new Person(23, "Ian", 164, "Miller");
        // Creating dummy unsorted map
        Map<String, Person> unsortMap = new HashMap<>();
        unsortMap.put("B", person);
        unsortMap.put("A", personTwo);
        unsortMap.put("D", personThree);
        unsortMap.put("C", personFour);

        System.out.println("Before sorting......");
        printMap(unsortMap);

        System.out.println("After sorting ascending order......");
        Map<String, Person> sortedMapAsc = sortByComparator(unsortMap, ASC);
        printMap(sortedMapAsc);


        System.out.println("After sorting descindeng order......");
        Map<String, Person> sortedMapDesc = sortByComparator(unsortMap, DESC);
        printMap(sortedMapDesc);

    }

    private static Map<String, Person> sortByComparator(Map<String, Person> unsortMap, final boolean order)
    {

        List<Entry<String, Person>> list = new LinkedList<>(unsortMap.entrySet());

        // Sorting the list based on values
        Collections.sort(list, new Comparator<Entry<String, Person>>()
        {
            @Override
            public int compare(Entry<String, Person> o1, Entry<String, Person> o2)
            {
                if (order)
                {
                    return o1.getValue().compareTo(o2.getValue());
                }
                else
                {
                    return o2.getValue().compareTo(o1.getValue());

                }
            }
        });

        // Maintaining insertion order with the help of LinkedList
        Map<String, Person> sortedMap = new LinkedHashMap<>();
        for (Entry<String, Person> entry : list)
        {
            sortedMap.put(entry.getKey(), entry.getValue());
        }

        return sortedMap;
    }

    public static void printMap(Map<String, Person> map)
    {
        for (Entry<String, Person> entry : map.entrySet())
        {
            System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue().getName());
        }
    }
}

这是人类:

public class Person implements Comparable{

    private int age;
    private String name;
    private int height;
    private String lastname;

    public Person(int age, String name, int height, String lastname) {
        this.age = age;
        this.name = name;
        this.height = height;
        this.lastname = lastname;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    @Override
    public int compareTo(Object arg0) {
        Person country=(Person) arg0;
        return (this.getAge() < country.getAge() ) ? -1: (this.getAge() > country.getAge() ) ? 1:0;
    }        

}

现在,如果您将代码复制粘贴到IDE,您将看到地图中的值都是根据年龄进行排序的,因为Person类会以基于年龄的方式比较对象的方式覆盖compareTo方法。现在有一种方法,我可以使这进一步动态。就像我可以改变比较发生的值,例如假设我想根据名称,身高,姓氏进行比较。

3 个答案:

答案 0 :(得分:1)

您的sortByComparator方法创建了Comparator的实现,它依赖于Person类的Comparable实现。相反,您可以将Comparator传递给sortByComparator,每个传递Comparator的人都可以按不同的标准排序。

private static Map<String, Person> sortByComparator(Map<String, Person> unsortMap, Comparator<Person> cmp, final boolean order)
{

    List<Entry<String, Person>> list = new LinkedList<>(unsortMap.entrySet());

    // Sorting the list based on values
    Collections.sort(list, new Comparator<Entry<String, Person>>()
    {
        @Override
        public int compare(Entry<String, Person> o1, Entry<String, Person> o2)
        {
            if (order)
            {
                return cmp.compare(o1.getValue(),o2.getValue());
            }
            else
            {
                return cmp.compare(o2.getValue(),o1.getValue());
            }
        }
    });

    // Maintaining insertion order with the help of LinkedList
    Map<String, Person> sortedMap = new LinkedHashMap<>();
    for (Entry<String, Person> entry : list)
    {
        sortedMap.put(entry.getKey(), entry.getValue());
    }

    return sortedMap;
}

答案 1 :(得分:0)

排序的HashMap毫无意义,它将破坏散列算法。如果您想要一个已排序的地图,您应该考虑使用TreeMap。

答案 2 :(得分:0)

public class Test {
public static void main(String[] args) {
TreeMap<Integer, String> hm=new TreeMap();
hm.put(3, "arun singh");
hm.put(5, "vinay singh");
hm.put(1, "bandagi singh");
hm.put(6, "vikram singh");
hm.put(2, "panipat singh");
hm.put(28, "jakarta singh");

ArrayList<String> al=new ArrayList(hm.values());
Collections.sort(al, new myComparator());

System.out.println("//sort by values \n");
for(String obj: al){
    for(Map.Entry<Integer, String> map2:hm.entrySet()){
        if(map2.getValue().equals(obj)){
            System.out.println(map2.getKey()+" "+map2.getValue());
        }
    } 
 }
}
}

class myComparator implements Comparator{
    @Override
    public int compare(Object o1, Object o2) {
     String o3=(String) o1;
     String o4 =(String) o2;
return o3.compareTo(o4);
    }   
}

OUTPUT =

//sort by values 

3 arun singh
1 bandagi singh
28 jakarta singh
2 panipat singh
6 vikram singh
5 vinay singh