如何根据值对地图进行排序,即具有多个属性的对象
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
我有一个非常直接的代码来根据值而不是键对 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