Map<Object, String> map = new HashMap<Object, String>();// Populate the MapList<String> mapValues = new ArrayList<String>(map.values());Collections.sort(mapValues);
public static <K, V extends Comparable<? super V>> List<K> getKeysSortedByValue(Map<K, V> map) {final int size = map.size();final List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size);list.addAll(map.entrySet());final ValueComparator<V> cmp = new ValueComparator<V>();Collections.sort(list, cmp);final List<K> keys = new ArrayList<K>(size);for (int i = 0; i < size; i++) {keys.set(i, list.get(i).getKey());}return keys;}
private static final class ValueComparator<V extends Comparable<? super V>>implements Comparator<Map.Entry<?, V>> {public int compare(Map.Entry<?, V> o1, Map.Entry<?, V> o2) {return o1.getValue().compareTo(o2.getValue());}}
public static <K, V extends Comparable<? super V>> List<K> getKeysSortedByValue2(Map<K, V> map) {final int size = map.size();final List reusedList = new ArrayList(size);final List<Map.Entry<K, V>> meView = reusedList;meView.addAll(map.entrySet());Collections.sort(meView, SINGLE);final List<K> keyView = reusedList;for (int i = 0; i < size; i++) {keyView.set(i, meView.get(i).getKey());}return keyView;}
private static final Comparator SINGLE = new ValueComparator();
/*** Sort a map by it's keys in ascending order.** @return new instance of {@link LinkedHashMap} contained sorted entries of supplied map.* @author Maxim Veksler*/public static <K, V> LinkedHashMap<K, V> sortMapByKey(final Map<K, V> map) {return sortMapByKey(map, SortingOrder.ASCENDING);}
/*** Sort a map by it's values in ascending order.** @return new instance of {@link LinkedHashMap} contained sorted entries of supplied map.* @author Maxim Veksler*/public static <K, V> LinkedHashMap<K, V> sortMapByValue(final Map<K, V> map) {return sortMapByValue(map, SortingOrder.ASCENDING);}
/*** Sort a map by it's keys.** @param sortingOrder {@link SortingOrder} enum specifying requested sorting order.* @return new instance of {@link LinkedHashMap} contained sorted entries of supplied map.* @author Maxim Veksler*/public static <K, V> LinkedHashMap<K, V> sortMapByKey(final Map<K, V> map, final SortingOrder sortingOrder) {Comparator<Map.Entry<K, V>> comparator = new Comparator<Entry<K,V>>() {public int compare(Entry<K, V> o1, Entry<K, V> o2) {return comparableCompare(o1.getKey(), o2.getKey(), sortingOrder);}};
return sortMap(map, comparator);}
/*** Sort a map by it's values.** @param sortingOrder {@link SortingOrder} enum specifying requested sorting order.* @return new instance of {@link LinkedHashMap} contained sorted entries of supplied map.* @author Maxim Veksler*/public static <K, V> LinkedHashMap<K, V> sortMapByValue(final Map<K, V> map, final SortingOrder sortingOrder) {Comparator<Map.Entry<K, V>> comparator = new Comparator<Entry<K,V>>() {public int compare(Entry<K, V> o1, Entry<K, V> o2) {return comparableCompare(o1.getValue(), o2.getValue(), sortingOrder);}};
return sortMap(map, comparator);}
@SuppressWarnings("unchecked")private static <T> int comparableCompare(T o1, T o2, SortingOrder sortingOrder) {int compare = ((Comparable<T>)o1).compareTo(o2);
switch (sortingOrder) {case ASCENDING:return compare;case DESCENDING:return (-1) * compare;}
return 0;}
/*** Sort a map by supplied comparator logic.** @return new instance of {@link LinkedHashMap} contained sorted entries of supplied map.* @author Maxim Veksler*/public static <K, V> LinkedHashMap<K, V> sortMap(final Map<K, V> map, final Comparator<Map.Entry<K, V>> comparator) {// Convert the map into a list of key,value pairs.List<Map.Entry<K, V>> mapEntries = new LinkedList<Map.Entry<K, V>>(map.entrySet());
// Sort the converted list according to supplied comparator.Collections.sort(mapEntries, comparator);
// Build a new ordered map, containing the same entries as the old map.LinkedHashMap<K, V> result = new LinkedHashMap<K, V>(map.size() + (map.size() / 20));for(Map.Entry<K, V> entry : mapEntries) {// We iterate on the mapEntries list which is sorted by the comparator putting new entries into// the targeted result which is a sorted map.result.put(entry.getKey(), entry.getValue());}
return result;}
/*** Sorting order enum, specifying request result sort behavior.* @author Maxim Veksler**/public static enum SortingOrder {/*** Resulting sort will be from smaller to biggest.*/ASCENDING,/*** Resulting sort will be from biggest to smallest.*/DESCENDING}
public class MapUtil {public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {List<Entry<K, V>> list = new ArrayList<>(map.entrySet());list.sort(Entry.comparingByValue());
Map<K, V> result = new LinkedHashMap<>();for (Entry<K, V> entry : list) {result.put(entry.getKey(), entry.getValue());}
return result;}}
ResultComparator rc = new ResultComparator();Set<Results> set = new TreeSet<Results>(rc);
您将创建类Results,
public class Results {private Driver driver;private Float time;
public Results(Driver driver, Float time) {this.driver = driver;this.time = time;}
public Float getTime() {return time;}
public void setTime(Float time) {this.time = time;}
public Driver getDriver() {return driver;}
public void setDriver (Driver driver) {this.driver = driver;}}
比较器类:
public class ResultsComparator implements Comparator<Results> {public int compare(Results t, Results t1) {if (t.getTime() < t1.getTime()) {return 1;} else if (t.getTime() == t1.getTime()) {return 0;} else {return -1;}}}
通过这种方式,您可以轻松添加更多依赖项。
作为最后一点,我将添加简单的迭代器:
Iterator it = set.iterator();while (it.hasNext()) {Results r = (Results)it.next();System.out.println( r.getDriver().toString//or whatever that is related to Driver class -getName() getSurname()+ " "+ r.getTime());}
import static org.junit.Assert.assertEquals;
import java.util.HashMap;import java.util.Map;import java.util.TreeMap;
import com.google.common.base.Functions;import com.google.common.collect.Ordering;
class ValueComparableMap<K extends Comparable<K>,V> extends TreeMap<K,V> {//A map for doing lookups on the keys for comparison so we don't get infinite loopsprivate final Map<K, V> valueMap;
ValueComparableMap(final Ordering<? super V> partialValueOrdering) {this(partialValueOrdering, new HashMap<K,V>());}
private ValueComparableMap(Ordering<? super V> partialValueOrdering,HashMap<K, V> valueMap) {super(partialValueOrdering //Apply the value ordering.onResultOf(Functions.forMap(valueMap)) //On the result of getting the value for the key from the map.compound(Ordering.natural())); //as well as ensuring that the keys don't get clobberedthis.valueMap = valueMap;}
public V put(K k, V v) {if (valueMap.containsKey(k)){//remove the key in the sorted set before adding the key againremove(k);}valueMap.put(k,v); //To get "real" unsorted values for the comparatorreturn super.put(k, v); //Put it in value order}
public static void main(String[] args){TreeMap<String, Integer> map = new ValueComparableMap<String, Integer>(Ordering.natural());map.put("a", 5);map.put("b", 1);map.put("c", 3);assertEquals("b",map.firstKey());assertEquals("a",map.lastKey());map.put("d",0);assertEquals("d",map.firstKey());//ensure it's still a map (by overwriting a key, but with a new value)map.put("d", 2);assertEquals("b", map.firstKey());//Ensure multiple values do not clobber keysmap.put("e", 2);assertEquals(5, map.size());assertEquals(2, (int) map.get("e"));assertEquals(2, (int) map.get("d"));}}
Map<String, Long> map = new HashMap<String, Long>();// populate with data to sort on Value// use datastructure designed for sorting
Queue queue = new PriorityQueue( map.size(), new MapComparable() );queue.addAll( map.entrySet() );
// get a sorted mapLinkedHashMap<String, Long> linkedMap = new LinkedHashMap<String, Long>();
for (Map.Entry<String, Long> entry; (entry = queue.poll())!=null;) {linkedMap.put(entry.getKey(), entry.getValue());}
public static class MapComparable implements Comparator<Map.Entry<String, Long>>{
public int compare(Entry<String, Long> e1, Entry<String, Long> e2) {return e1.getValue().compareTo(e2.getValue());}}
final class MapValueComparator<K,V extends Comparable<V>> implements Comparator<K> {private final Map<K,V> map;
private MapValueComparator() {super();}
public MapValueComparator(Map<K,V> map) {this();this.map = map;}
public int compare(K o1, K o2) {return map.get(o1).compareTo(map.get(o2));}}
package nl.iamit.util;
import java.util.Comparator;import java.util.Map;
public class Comparators {
public static class MapIntegerStringComparator implements Comparator {
Map<Integer, String> base;
public MapIntegerStringComparator(Map<Integer, String> base) {this.base = base;}
public int compare(Object a, Object b) {
int compare = ((String) base.get(a)).compareTo((String) base.get(b));if (compare == 0) {return -1;}return compare;}}
}
public static class MapStringDoubleComparator implements Comparator {
Map<String, Double> base;
public MapStringDoubleComparator(Map<String, Double> base) {this.base = base;}
//note if you want decending in stead of ascending, turn around 1 and -1public int compare(Object a, Object b) {if ((Double) base.get(a) == (Double) base.get(b)) {return 0;} else if((Double) base.get(a) < (Double) base.get(b)) {return -1;}else{return 1;}}}
这是这个的测试用例:
@Testpublic void testMapStringDoubleComparator(){HashMap<String, Double> unSoretedMap = new HashMap<String, Double>();Comparators.MapStringDoubleComparator bvc = new Comparators.MapStringDoubleComparator(unSoretedMap);TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc);//the testdata:unSoretedMap.put("D",new Double(67.3));unSoretedMap.put("A",new Double(99.5));unSoretedMap.put("B",new Double(67.4));unSoretedMap.put("C",new Double(67.5));unSoretedMap.put("E",new Double(99.5));
sorted_map.putAll(unSoretedMap);
Object[] targetKeys={"D","B","C","E","A"};Object[] currecntKeys=sorted_map.keySet().toArray();
assertArrayEquals(targetKeys,currecntKeys);}
/**
* Sort a map according to values.
* @param <K> the key of the map.* @param <V> the value to sort according to.* @param mapToSort the map to sort.
* @return a map sorted on the values.
*/public static <K, V extends Comparable< ? super V>> Map<K, V>sortMapByValues(final Map <K, V> mapToSort){List<Map.Entry<K, V>> entries =new ArrayList<Map.Entry<K, V>>(mapToSort.size());
entries.addAll(mapToSort.entrySet());
Collections.sort(entries,new Comparator<Map.Entry<K, V>>(){@Overridepublic int compare(final Map.Entry<K, V> entry1,final Map.Entry<K, V> entry2){return entry1.getValue().compareTo(entry2.getValue());}});
Map<K, V> sortedMap = new LinkedHashMap<K, V>();
for (Map.Entry<K, V> entry : entries){sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
// If you want to sort a map by value, and if there can be twice the same value:
// here is your original mapMap<String,Integer> mapToSortByValue = new HashMap<String, Integer>();mapToSortByValue.put("A", 3);mapToSortByValue.put("B", 1);mapToSortByValue.put("C", 3);mapToSortByValue.put("D", 5);mapToSortByValue.put("E", -1);mapToSortByValue.put("F", 1000);mapToSortByValue.put("G", 79);mapToSortByValue.put("H", 15);
// Sort all the map entries by valueSet<Map.Entry<String,Integer>> set = new TreeSet<Map.Entry<String,Integer>>(new Comparator<Map.Entry<String,Integer>>(){@Overridepublic int compare(Map.Entry<String,Integer> obj1, Map.Entry<String,Integer> obj2) {Integer val1 = obj1.getValue();Integer val2 = obj2.getValue();// DUPLICATE VALUE CASE// If the values are equals, we can't return 0 because the 2 entries would be considered// as equals and one of them would be deleted (because we use a set, no duplicate, remember!)int compareValues = val1.compareTo(val2);if ( compareValues == 0 ) {String key1 = obj1.getKey();String key2 = obj2.getKey();int compareKeys = key1.compareTo(key2);if ( compareKeys == 0 ) {// what you return here will tell us if you keep REAL KEY-VALUE duplicates in your set// if you want to, do whatever you want but do not return 0 (but don't break the comparator contract!)return 0;}return compareKeys;}return compareValues;}});set.addAll(mapToSortByValue.entrySet());
// OK NOW OUR SET IS SORTED COOL!!!!
// And there's nothing more to do: the entries are sorted by value!for ( Map.Entry<String,Integer> entry : set ) {System.out.println("Set entries: " + entry.getKey() + " -> " + entry.getValue());}
// But if you add them to an hashmapMap<String,Integer> myMap = new HashMap<String,Integer>();// When iterating over the set the order is still good in the println...for ( Map.Entry<String,Integer> entry : set ) {System.out.println("Added to result map entries: " + entry.getKey() + " " + entry.getValue());myMap.put(entry.getKey(), entry.getValue());}
// But once they are in the hashmap, the order is not kept!for ( Integer value : myMap.values() ) {System.out.println("Result map values: " + value);}// Also this way doesn't work:// Logic because the entryset is a hashset for hashmaps and not a treeset// (and even if it was a treeset, it would be on the keys only)for ( Map.Entry<String,Integer> entry : myMap.entrySet() ) {System.out.println("Result map entries: " + entry.getKey() + " -> " + entry.getValue());}
// CONCLUSION:// If you want to iterate on a map ordered by value, you need to remember:// 1) Maps are only sorted by keys, so you can't sort them directly by value// 2) So you simply CAN'T return a map to a sortMapByValue function// 3) You can't reverse the keys and the values because you have duplicate values// This also means you can't neither use Guava/Commons bidirectionnal treemaps or stuff like that
// SOLUTIONS// So you can:// 1) only sort the values which is easy, but you loose the key/value link (since you have duplicate values)// 2) sort the map entries, but don't forget to handle the duplicate value case (like i did)// 3) if you really need to return a map, use a LinkedHashMap which keep the insertion order
Set entries: E -> -1Set entries: B -> 1Set entries: A -> 3Set entries: C -> 3Set entries: D -> 5Set entries: H -> 15Set entries: G -> 79Set entries: F -> 1000Added to result map entries: E -1Added to result map entries: B 1Added to result map entries: A 3Added to result map entries: C 3Added to result map entries: D 5Added to result map entries: H 15Added to result map entries: G 79Added to result map entries: F 1000Result map values: 5Result map values: -1Result map values: 1000Result map values: 79Result map values: 3Result map values: 1Result map values: 3Result map values: 15Result map entries: D -> 5Result map entries: E -> -1Result map entries: F -> 1000Result map entries: G -> 79Result map entries: A -> 3Result map entries: B -> 1Result map entries: C -> 3Result map entries: H -> 15
public int compare(String a, String b) {if (base.get(a) > base.get(b)) {return 1;} else if (base.get(a) < base.get(b)){return -1;}
return 0;// returning 0 would merge keys}
class MapUtil {
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue( Map<K, V> map ){ValueComparator<K,V> bvc = new ValueComparator<K,V>(map);TreeMap<K,V> sorted_map = new TreeMap<K,V>(bvc);sorted_map.putAll(map);return sorted_map;}
}
class ValueComparator<K, V extends Comparable<? super V>> implements Comparator<K> {
Map<K, V> base;public ValueComparator(Map<K, V> base) {this.base = base;}
public int compare(K a, K b) {int result = (base.get(a).compareTo(base.get(b)));if (result == 0) result=1;// returning 0 would merge keysreturn result;}}
import java.util.*;
/*** A map where {@link #keySet()} and {@link #entrySet()} return sets ordered* by associated values based on the the comparator provided at construction* time. The order of two or more keys with identical values is not defined.* <p>* Several contracts of the Map interface are not satisfied by this minimal* implementation.*/public class ValueSortedMap<K, V> extends HashMap<K, V> {protected Map<V, Collection<K>> valueToKeysMap;
// uses natural order of value object, if anypublic ValueSortedMap() {this((Comparator<? super V>) null);}
public ValueSortedMap(Comparator<? super V> valueComparator) {this.valueToKeysMap = new TreeMap<V, Collection<K>>(valueComparator);}
public boolean containsValue(Object o) {return valueToKeysMap.containsKey(o);}
public V put(K k, V v) {V oldV = null;if (containsKey(k)) {oldV = get(k);valueToKeysMap.get(oldV).remove(k);}super.put(k, v);if (!valueToKeysMap.containsKey(v)) {Collection<K> keys = new ArrayList<K>();keys.add(k);valueToKeysMap.put(v, keys);} else {valueToKeysMap.get(v).add(k);}return oldV;}
public void putAll(Map<? extends K, ? extends V> m) {for (Map.Entry<? extends K, ? extends V> e : m.entrySet())put(e.getKey(), e.getValue());}
public V remove(Object k) {V oldV = null;if (containsKey(k)) {oldV = get(k);super.remove(k);valueToKeysMap.get(oldV).remove(k);}return oldV;}
public void clear() {super.clear();valueToKeysMap.clear();}
public Set<K> keySet() {LinkedHashSet<K> ret = new LinkedHashSet<K>(size());for (V v : valueToKeysMap.keySet()) {Collection<K> keys = valueToKeysMap.get(v);ret.addAll(keys);}return ret;}
public Set<Map.Entry<K, V>> entrySet() {LinkedHashSet<Map.Entry<K, V>> ret = new LinkedHashSet<Map.Entry<K, V>>(size());for (Collection<K> keys : valueToKeysMap.values()) {for (final K k : keys) {final V v = get(k);ret.add(new Map.Entry<K,V>() {public K getKey() {return k;}
public V getValue() {return v;}
public V setValue(V v) {throw new UnsupportedOperationException();}});}}return ret;}}
LinkedHashMap sortedByValueMap = map.entrySet().stream().sorted(comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey)) //first sorting by Value, then sorting by Key(entries with same value).collect(LinkedHashMap::new,(map,entry) -> map.put(entry.getKey(),entry.getValue()),LinkedHashMap::putAll);
//Create a list by HashMapList<Map.Entry<String, Double>> list = new LinkedList<>(hashMap.entrySet());
//Sorting the listCollections.sort(list, new Comparator<Map.Entry<String, Double>>() {public int compare(Map.Entry<String, Double> o1, Map.Entry<String, Double> o2) {return (o1.getValue()).compareTo(o2.getValue());}});
//put data from sorted list to hashmapHashMap<String, Double> sortedData = new LinkedHashMap<>();for (Map.Entry<String, Double> data : list) {sortedData.put(data.getKey(), data.getValue());}
System.out.print(sortedData);
map = your hashmap;
List<Map.Entry<String, Integer>> list = new LinkedList<Map.Entry<String, Integer>>(map.entrySet());Collections.sort(list, new cm());//IMP
HashMap<String, Integer> sorted = new LinkedHashMap<String, Integer>();for(Map.Entry<String, Integer> en: list){sorted.put(en.getKey(),en.getValue());}
System.out.println(sorted);//sorted hashmap
创建新的类
class cm implements Comparator<Map.Entry<String, Integer>>{@Overridepublic int compare(Map.Entry<String, Integer> a,Map.Entry<String, Integer> b){return (a.getValue()).compareTo(b.getValue());}}
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> (map.get(a) - map.get(b));for(int key: map.keySets()) {pq.add(key);if(pq.size() > 2) {pq.poll();}}// Now pq has the top 2 most frequent key based on value. It sorts the value.
Input : Key = Math, Value = 98Key = Data Structure, Value = 85Key = Database, Value = 91Key = Java, Value = 95Key = Operating System, Value = 79Key = Networking, Value = 80
Output : Key = Operating System, Value = 79Key = Networking, Value = 80Key = Data Structure, Value = 85Key = Database, Value = 91Key = Java, Value = 95Key = Math, Value = 98Solution: The idea is to store the entry set in a list and sort the list on the basis of values. Then fetch values and keys from the list and put them in a new hashmap. Thus, a new hashmap is sorted according to values.Below is the implementation of the above idea:
// Java program to sort hashmap by valuesimport java.util.*;import java.lang.*;
public class GFG {
// function to sort hashmap by valuespublic static HashMap<String, Integer> sortByValue(HashMap<String, Integer> hm){// Create a list from elements of HashMapList<Map.Entry<String, Integer> > list =new LinkedList<Map.Entry<String, Integer> >(hm.entrySet());
// Sort the listCollections.sort(list, new Comparator<Map.Entry<String, Integer> >() {public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2){return (o1.getValue()).compareTo(o2.getValue());}});
// put data from sorted list to hashmapHashMap<String, Integer> temp = new LinkedHashMap<String, Integer>();for (Map.Entry<String, Integer> aa : list) {temp.put(aa.getKey(), aa.getValue());}return temp;}
// Driver Codepublic static void main(String[] args){
HashMap<String, Integer> hm = new HashMap<String, Integer>();
// enter data into hashmaphm.put("Math", 98);hm.put("Data Structure", 85);hm.put("Database", 91);hm.put("Java", 95);hm.put("Operating System", 79);hm.put("Networking", 80);Map<String, Integer> hm1 = sortByValue(hm);
// print the sorted hashmapfor (Map.Entry<String, Integer> en : hm1.entrySet()) {System.out.println("Key = " + en.getKey() +", Value = " + en.getValue());}}}OutputKey = Operating System, Value = 79Key = Networking, Value = 80Key = Data Structure, Value = 85Key = Database, Value = 91Key = Java, Value = 95Key = Math, Value = 98