如何根据值对地图进行排序,即具有多个属性的对象

How to sort Map based on Value i.e. an Object having multiple properties

我有一个非常直接的代码来根据值而不是键对 HashMap 进行排序(从 SO 复制但是例如在 SO 上只是对字符串进行排序,因为我想根据对象的属性进行排序)

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());
        }
    }
}

这是 Person 类:

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 class 以比较对象的方式覆盖了 compareTo 方法仅基于年龄。现在有什么方法可以使它更加动态。就像我可以更改发生比较的值,例如假设我也想根据姓名、身高、姓氏进行比较。

您的 sortByComparator 方法创建了 Comparator 的实现,它依赖于 Person class 的 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;
}

一个排序的HashMap是没有意义的,它会破坏哈希算法。如果你想要一个排序的地图,你应该考虑使用 TreeMap。

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);
    }   
}

输出=

//sort by values 

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