我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。

由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。

有没有更简单的方法?


当前回答

    Map<String, Integer> map = new HashMap<>();
    map.put("b", 2);
    map.put("a", 1);
    map.put("d", 4);
    map.put("c", 3);
    
    // ----- Using Java 7 -------------------
    List<Map.Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());
    Collections.sort(entries, (o1, o2) -> o1.getValue().compareTo(o2.getValue()));
    System.out.println(entries); // [a=1, b=2, c=3, d=4]


    // ----- Using Java 8 Stream API --------
   map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println); // {a=1, b=2, c=3, d=4}

    

其他回答

这是Anthony答案的变体,如果存在重复值,则该答案无效:

public static <K, V extends Comparable<V>> Map<K, V> sortMapByValues(final Map<K, V> map) {
    Comparator<K> valueComparator =  new Comparator<K>() {
        public int compare(K k1, K k2) {
            final V v1 = map.get(k1);
            final V v2 = map.get(k2);

            /* Not sure how to handle nulls ... */
            if (v1 == null) {
                return (v2 == null) ? 0 : 1;
            }

            int compare = v2.compareTo(v1);
            if (compare != 0)
            {
                return compare;
            }
            else
            {
                Integer h1 = k1.hashCode();
                Integer h2 = k2.hashCode();
                return h2.compareTo(h1);
            }
        }
    };
    Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
    sortedByValues.putAll(map);
    return sortedByValues;
}

注意,如何处理空值还很难说。

这种方法的一个重要优点是它实际上返回了一个Map,这与这里提供的其他解决方案不同。

用Java中最简单的方式对任何Hashmap进行排序。我们不需要将其存储在树图、列表等中。

在这里,我将使用Java Streams:

让我们按其值(升序)对该地图进行排序

Map<String, Integer> mp= new HashMap<>();
mp.put("zebra", 1);
mp.put("blossom", 2);
mp.put("gemini", 3);
mp.put("opera", 7);
mp.put("adelaide", 10);

Map<String, Integer> resultMap= mp.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e1, LinkedHashMap::new));

现在,您可以通过多种方式打印排序后的resultMap,例如使用高级for循环或迭代器。

上面的映射也可以按值的降序排序

 Map<String, Integer> resultMap= mp.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e1, LinkedHashMap::new));

现在让我们来看另一个场景,我们将“User”存储在地图中,并根据“User”的“name”按升序(词典)对其进行排序:

User u1= new User("hi", 135);
User u2= new User("bismuth", 900);
User u3= new User("alloy", 675);
User u4= new User("jupiter", 342);
User u5= new User("lily", 941);

Map<String, User> map2= new HashMap<>();
map2.put("zebra", u3);
map2.put("blossom", u5);
map2.put("gemini", u1);
map2.put("opera", u2);
map2.put("adelaide", u4);


Map<String, User>  resultMap= 
          map2.entrySet().stream().sorted(Map.Entry.<String, User>comparingByValue( (User o1, User o2)-> o1.getName().compareTo(o2.getName()))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e2, LinkedHashMap::new));



class User
 {
    String name;
    int id;
        

public User(String name, int id) {
    super();
    this.name = name;
    this.id = id;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
@Override
public String toString() {
    return "User [name=" + name + ", id=" + id + "]";
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    User other = (User) obj;
    if (id != other.id)
        return false;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;


    }
 }

从…起http://www.programmersheaven.com/download/49349/download.aspx

private static <K, V> Map<K, V> sortByValue(Map<K, V> map) {
    List<Entry<K, V>> list = new LinkedList<>(map.entrySet());
    Collections.sort(list, new Comparator<Object>() {
        @SuppressWarnings("unchecked")
        public int compare(Object o1, Object o2) {
            return ((Comparable<V>) ((Map.Entry<K, V>) (o1)).getValue()).compareTo(((Map.Entry<K, V>) (o2)).getValue());
        }
    });

    Map<K, V> result = new LinkedHashMap<>();
    for (Iterator<Entry<K, V>> it = list.iterator(); it.hasNext();) {
        Map.Entry<K, V> entry = (Map.Entry<K, V>) it.next();
        result.put(entry.getKey(), entry.getValue());
    }

    return result;
}
public class SortedMapExample {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();

        map.put("Cde", "C");
        map.put("Abc", "A");
        map.put("Cbc", "Z");
        map.put("Dbc", "D");
        map.put("Bcd", "B");
        map.put("sfd", "Bqw");
        map.put("DDD", "Bas");
        map.put("BGG", "Basd");

        System.out.println(sort(map, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
            }}));
    }

    @SuppressWarnings("unchecked")
    public static <K, V> Map<K,V> sort(Map<K, V> in, Comparator<? super V> compare) {
        Map<K, V> result = new LinkedHashMap<K, V>();
        V[] array = (V[])in.values().toArray();
        for(int i=0;i<array.length;i++)
        {

        }
        Arrays.sort(array, compare);
        for (V item : array) {
            K key= (K) getKey(in, item);
            result.put(key, item);
        }
        return result;
    }

    public static <K, V>  Object getKey(Map<K, V> in,V value)
    {
       Set<K> key= in.keySet();
       Iterator<K> keyIterator=key.iterator();
       while (keyIterator.hasNext()) {
           K valueObject = (K) keyIterator.next();
           if(in.get(valueObject).equals(value))
           {
                   return valueObject;
           }
       }
       return null;
   }

}

//请在这里尝试。我正在修改值排序的代码。

好的,这个版本使用两个新的Map对象和两次迭代,并对值进行排序。希望,虽然地图条目必须循环两次,但表现良好:

public static void main(String[] args) {
    Map<String, String> unsorted = new HashMap<String, String>();
    unsorted.put("Cde", "Cde_Value");
    unsorted.put("Abc", "Abc_Value");
    unsorted.put("Bcd", "Bcd_Value");

    Comparator<String> comparer = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareTo(o2);
        }};

    System.out.println(sortByValue(unsorted, comparer));

}

public static <K, V> Map<K,V> sortByValue(Map<K, V> in, Comparator<? super V> compare) {
    Map<V, K> swapped = new TreeMap<V, K>(compare);
    for(Entry<K,V> entry: in.entrySet()) {
        if (entry.getValue() != null) {
            swapped.put(entry.getValue(), entry.getKey());
        }
    }
    LinkedHashMap<K, V> result = new LinkedHashMap<K, V>();
    for(Entry<V,K> entry: swapped.entrySet()) {
        if (entry.getValue() != null) {
            result.put(entry.getValue(), entry.getKey());
        }
    }
    return result;
}

该解决方案使用带有比较器的TreeMap,并对所有空键和值进行排序。首先,使用TreeMap中的排序功能对值进行排序,然后使用排序后的Map创建一个结果,因为LinkedHashMap保留了相同的值顺序。

格里兹,GHad