【问题标题】:How to sort Map based on Value i.e. an Object having multiple properties如何根据值对地图进行排序,即具有多个属性的对象
【发布时间】:2018-01-03 06:36:52
【问题描述】:

我有一个非常简单的代码来根据值而不是键对 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 类以仅根据年龄比较对象的方式覆盖了 compareTo 方法。现在有没有一种方法可以使这进一步动态化。就像我可以更改进行比较的值吗?假设我也想根据姓名、身高、姓氏进行比较。

【问题讨论】:

  • 您无法对HashMap 进行排序;它没有顺序的概念
  • @fge 我说的是给我们这种行为的额外逻辑

标签: java dictionary collections


【解决方案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;
}

【讨论】:

  • 我当前的逻辑采用以下比较器 "new Comparator>()" 我怎样才能进一步发送一个以不同方式实现 Person 类的比较器对象
  • @kapilchhattani 查看我的编辑。您应该将实现 Comparator&lt;Person&gt; 的类的实例传递给您的 sortByComparator 并在您的 Comparator> 中使用该 Comparator
  • 所以 cmp 是比较器的对象。让我试试这个。如果这行得通,这实际上是一种祝福..
【解决方案2】:

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

【讨论】:

    【解决方案3】:
    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      • 2015-01-10
      • 2011-09-09
      相关资源
      最近更新 更多