Rūšiuoti žemėlapį <Raktas, reikšmė> pagal vertę

Esu gana naujas „Java“ ir dažnai pastebiu, kad turiu rūšiuoti Map<Key, Value> pagal vertes.

Kadangi reikšmės nėra unikalios, aš keySet kad aš perskaičiau keySet į array ir surūšiuoju šią masyvą rūšiuojant masyvą, naudojant specializuotą komparatorių , kuris suskirstomas pagal reikšmę, susijusią su raktu.

Ar yra lengviau?

1463
21 сент. Abe yra nustatytas 21 sep. 2008-09-21 00:03 '08 at 0:03 2008-09-21 00:03
šaltinis
@ 49 atsakymai
  • 1
  • 2

Čia yra bendra versija:

 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; } } 
819
06 апр. atsakymą pateikė „ Carter“. 2010-04-06 02:24 '10, 2:24, 2010-04-06 02:24
šaltinis

Svarbi pastaba:

Šis kodas gali būti sugadintas keliais būdais. Jei ketinate naudoti pateiktą kodą, būtinai perskaitykite komentarus, kad žinotumėte pasekmes. Pavyzdžiui, reikšmės nebegali gauti iš jų raktų. (visada get null .)


Atrodo tiek daug lengviau nei pirmiau. Naudokite „TreeMap“:

 public class Testing { public static void main(String[] args) { HashMap<String, Double> map = new HashMap<String, Double>(); ValueComparator bvc = new ValueComparator(map); TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc); map.put("A", 99.5); map.put("B", 67.4); map.put("C", 67.4); map.put("D", 67.3); System.out.println("unsorted map: " + map); sorted_map.putAll(map); System.out.println("results: " + sorted_map); } } class ValueComparator implements Comparator<String> { Map<String, Double> base; public ValueComparator(Map<String, Double> base) { this.base = base; } // Note: this comparator imposes orderings that are inconsistent with // equals. public int compare(String a, String b) { if (base.get(a) >= base.get(b)) { return -1; } else { return 1; } // returning 0 would merge keys } } 

Išvada:

 unsorted map: {D=67.3, A=99.5, B=67.4, C=67.4} results: {D=67.3, B=67.4, C=67.4, A=99.5} 
407
16 авг. vartotojo157196 atsakymas 16 rug . 2009-08-16 10:53 '09, 10:53 AM 2009-08-16 10:53
šaltinis

„Java 8“ siūlo naują atsakymą: konvertuokite įrašus į srautą ir naudokite Comparators kombinatorius iš Map.Entry:

 Stream<Map.Entry<K,V>> sorted = map.entrySet().stream() .sorted(Map.Entry.comparingByValue()); 

Tai leis jums vartoti įrašus, surūšiuotus didėjančia tvarka. Jei norite sumažinti vertę, tiesiog atšaukite palyginimą:

 Stream<Map.Entry<K,V>> sorted = map.entrySet().stream() .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())); 

Jei vertės nėra palyginamos, galite perduoti aiškų palyginimą:

 Stream<Map.Entry<K,V>> sorted = map.entrySet().stream() .sorted(Map.Entry.comparingByValue(comparator)); 

Tada galite naudoti kitus srauto veiksmus, kad galėtumėte naudoti duomenis. Pavyzdžiui, jei norite, kad top 10 būtų naujame žemėlapyje:

 Map<K,V> topTen = map.entrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .limit(10) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); 

Arba įveskite „ System.out :

 map.entrySet().stream() .sorted(Map.Entry.comparingByValue()) .forEach(System.out::println); 
249
24 мая '14 в 18:53 2014-05-24 18:53 Atsakymą pateikė Brian Goetz gegužės 14 d. 14, 18:53 2014-05-24 18:53
šaltinis

Trys vienos eilutės atsakymai ...

Norėčiau tai padaryti naudodamas „ Google“ kolekcijas Guava - jei jūsų vertybės yra Comparable , tada galite naudoti

 valueComparator = Ordering.natural().onResultOf(Functions.forMap(map)) 

Kas sukurs žemėlapio funkciją (objektą), kuris įveda bet kurį raktą kaip įvestį, grąžina atitinkamą reikšmę, o tada taiko jiems natūralią (palyginamą) tvarką [reikšmes].

Jei jie nėra palyginami, jums reikia kažką daryti pagal linijas.

 valueComparator = Ordering.from(comparator).onResultOf(Functions.forMap(map)) 

Jie gali būti taikomi „TreeMap“ (pvz., Ordering pratęsia Comparator ) arba „ LinkedHashMap“ po tam tikro rūšiavimo

Pastaba Jei ketinate naudoti „TreeMap“, nepamirškite, kad jei palyginimas == 0, tada elementas jau yra sąraše (kas atsitinka, jei turite keletą jų palyginančių vertybių). Norėdami tai palengvinti, galite pridėti raktą į panašų palyginimą (jei jūsų raktai ir vertės yra Comparable ):

 valueComparator = Ordering.natural().onResultOf(Functions.forMap(map)).compound(Ordering.natural()) 

= Taikykite natūralią eilės reikšmę raktui rodomai vertei ir prijunkite jį prie natūralios rakto tvarkos

Atkreipkite dėmesį, kad tai vis tiek neveiks, jei jūsų raktai bus lyginami su 0, bet tai turėtų pakakti daugumai Comparable elementų (kadangi hashCode , equals ir Comparable dažnai sinchronizuojami ...)

Žr. „ Ordering.onResultOf () ir„ Functions.forMap “() .

Įgyvendinimas

Taigi dabar, kai mes turime lyginamąją priemonę, kuri daro tai, ko mes norime, turime gauti iš to rezultatą.

 map = ImmutableSortedMap.copyOf(myOriginalMap, valueComparator); 

Dabar jis greičiausiai veiks, bet:

  • reikia paleisti su visa baigta kortele
  • Nebandykite naudoti „ TreeMap lyginamųjų TreeMap ; nėra prasmės bandyti palyginti įterptą raktą, kai tai nėra svarbu, kol ji tinka, t.y. labai greitai sprogo

1 punktas man yra šiek tiek; „Google“ kolekcijos yra neįtikėtinai tingios (tai yra gera: galite atlikti beveik kiekvieną operaciją iš karto, tikrasis darbas atliekamas pradėjus naudoti rezultatą), o tai reikalauja kopijuoti visą žemėlapį!

„Visas“ atsakymas / „Live“ rūšiuojamas žemėlapis pagal vertę

Nesijaudinkite; jei buvo pakankamai apsėstas, kad „gyvas“ žemėlapis buvo surūšiuotas tokiu būdu, galite išspręsti ne vieną, bet abu (!) pirmiau minėtas problemas, pavyzdžiui:

Pastaba Tai gerokai pasikeitė 2012 m. Birželio mėn. - ankstesnis kodas niekada neveikė: ieškoti vertybių, nesukuriant begalinės kilpos tarp „ TreeMap.get()compare() ir → get()

 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 loops private 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 clobbered this.valueMap = valueMap; } public V put(K k, V v) { if (valueMap.containsKey(k)){ //remove the key in the sorted set before adding the key again remove(k); } valueMap.put(k,v); //To get "real" unsorted values for the comparator return 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 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 keys map.put("e", 2); assertEquals(5, map.size()); assertEquals(2, (int) map.get("e")); assertEquals(2, (int) map.get("d")); } } 

Kai mes pateikiame, mes garantuojame, kad maišos žemėlapis yra tinkamas lyginamajam įrenginiui, ir tada įdėtas į TreeSet rūšiavimui. Bet prieš tai mes patikriname maišos žemėlapį, kad pamatytume, kad raktas iš tikrųjų nėra dublikatas. Be to, mūsų sukurtas palyginimas taip pat turės raktą, kad dvigubos reikšmės neištrintų ne nulinių raktų (dėl == palyginimų). Šie du elementai yra gyvybiškai svarbūs užtikrinant kortelės sutarties išsaugojimą; jei manote, kad to nenorite, tada beveik visiškai pasukote žemėlapį (iki Map<V,K> ).

Konstruktorius turi būti vadinamas

  new ValueComparableMap(Ordering.natural()); //or new ValueComparableMap(Ordering.from(comparator)); 
208
06 авг. atsakymas suteiktas Stephen 06 rug. 2010-08-06 06:59 '10, 6:59, 2010-08-06 06:59
šaltinis

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; } 
176
21 сент. atsakymas pateikiamas devinmoore 21 sep . 2008-09-21 00:06 '08 0:06 2008-09-21 00:06
šaltinis

Naudodami „Java 8“ galite naudoti „ api“ srautus, kad tai atliktumėte dar mažiau išsamiai:

 Map<K, V> sortedMap = map.entrySet().stream() .sorted(Entry.comparingByValue()) .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); 
41
02 марта '14 в 22:38 2014-03-02 22:38 atsakymas, kurį pateikė Asylias, kovo 2 d. 14 d., 22:38 2014-03-02 22:38
šaltinis

Norėdami surūšiuoti raktus, reikalaujama, kad palygintojas kiekvienam palyginimui ieškotų kiekvienos vertės. Skaidresnis sprendimas bus naudojamas tiesiogiai, nes tuomet vertė bus nedelsiant prieinama kiekvienam palyginimui (nors tai nepalaikiau skaičiais).

Čia yra bendrosios tokios versijos versija:

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

Yra būdų, kaip sumažinti atminties apyvartą minėtam sprendimui. Pirmasis sukurtas „ArrayList“ gali būti pakartotinai naudojamas kaip grąžinimo vertė; tam reikės panaikinti kai kuriuos bendrus įspėjimus, tačiau galbūt tai būtų naudinga pakartotinai naudojamiems bibliotekos kodams. Be to, Comparator neturėtų būti perskirstytas su kiekvienu skambučiu.

Čia yra efektyvesnis, nors ir mažiau patrauklus variantas:

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

Galiausiai, jei reikia nuolat prieiti prie rūšiuojamos informacijos (o ne tik rūšiuoti vieną kartą per tam tikrą laiką), galite naudoti papildomą žemėlapį. Leiskite man sužinoti, ar jums reikalinga išsami informacija ...

30
21 сент. atsakymas pateikiamas tinklui 21 sep. 2008-09-21 02:41 '08 at 2:41 am 2008-09-21 02:41
šaltinis

Kolekcijos rinkimo bibliotekoje yra sprendimas „ TreeBidiMap“ . Arba galite pažvelgti į „Google“ kolekcijų API. Jis turi „ TreeMultimap“ , kurį galėtumėte naudoti.

Ir jei nenorite naudoti šių sistemų ... jie ateina su šaltiniu.

25
21 сент. atsakymas pateikiamas p3t0r 21 sep . 2008-09-21 00:10 '08 0:10 2008-09-21 00:10
šaltinis

Žvelgiau į šiuos atsakymus, tačiau daugelis jų yra sudėtingesni nei būtina, arba ištrinti žemėlapio elementus, kai keli raktai turi tą pačią vertę.

Čia yra sprendimas, kurį manau geriausia:

 public static <K, V extends Comparable<V>> Map<K, V> sortByValues(final Map<K, V> map) { Comparator<K> valueComparator = new Comparator<K>() { public int compare(K k1, K k2) { int compare = map.get(k2).compareTo(map.get(k1)); if (compare == 0) return 1; else return compare; } }; Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator); sortedByValues.putAll(map); return sortedByValues; } 

Atkreipkite dėmesį, kad žemėlapis yra surūšiuotas nuo didžiausios vertės iki mažiausios.

23
21 янв. Anthony atsakymas, sausio 21 d 2010-01-21 23:34 '10, 23:34, 2010-01-21 23:34
šaltinis

Norėdami tai padaryti su naujomis „Java 8“ funkcijomis:

 import static java.util.Map.Entry.comparingByValue; import static java.util.stream.Collectors.toList; <K, V> List<Entry<K, V>> sort(Map<K, V> map, Comparator<? super V> comparator) { return map.entrySet().stream().sorted(comparingByValue(comparator)).collect(toList()); } 

Įrašai tvarkomi pagal jų vertes naudojant šį palyginamąjį kompiuterį. Arba, jei jūsų vertės yra tarpusavyje palyginamos, nereikia jokių aiškių palyginamųjų duomenų:

 <K, V extends Comparable<? super V>> List<Entry<K, V>> sort(Map<K, V> map) { return map.entrySet().stream().sorted(comparingByValue()).collect(toList()); } 

Grąžintas sąrašas yra šios kortelės momentinė nuotrauka, kai skambinama į šį metodą, todėl nė vienas iš jų neatspindės vėlesnių pakeitimų kitame. Jei norite pateikti gyvą iteracinį žemėlapio pristatymą:

 <K, V extends Comparable<? super V>> Iterable<Entry<K, V>> sort(Map<K, V> map) { return () -> map.entrySet().stream().sorted(comparingByValue()).iterator(); } 

Grįžtama iteracija sukuria naują tam tikro žemėlapio vaizdą kiekvieną kartą, kai ji kartojasi, todėl vienalaikio modifikavimo draudimas visada atspindi dabartinę žemėlapio būseną.

17
20 нояб. gdejohn lapkričio 20 d 2013-11-20 09:54 '13 ne 9:54 2013-11-20 09:54
šaltinis

Nors sutinku, kad nuolatinis poreikis rūšiuoti žemėlapį tikriausiai yra kvapas, manau, kad šis kodas yra paprasčiausias būdas tai padaryti nenaudojant kitokios duomenų struktūros.

 public class MapUtilities { public static <K, V extends Comparable<V>> List<Entry<K, V>> sortByValue(Map<K, V> map) { List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>(map.entrySet()); Collections.sort(entries, new ByValue<K, V>()); return entries; } private static class ByValue<K, V extends Comparable<V>> implements Comparator<Entry<K, V>> { public int compare(Entry<K, V> o1, Entry<K, V> o2) { return o1.getValue().compareTo(o2.getValue()); } } 

}

Ir tai yra nepatogiai nebaigtas vieneto testas:

 public class MapUtilitiesTest extends TestCase { public void testSorting() { HashMap<String, Integer> map = new HashMap<String, Integer>(); map.put("One", 1); map.put("Two", 2); map.put("Three", 3); List<Map.Entry<String, Integer>> sorted = MapUtilities.sortByValue(map); assertEquals("First", "One", sorted.get(0).getKey()); assertEquals("Second", "Two", sorted.get(1).getKey()); assertEquals("Third", "Three", sorted.get(2).getKey()); } 

}

Rezultatas yra surūšiuotas Map.Entry objektų sąrašas, iš kurio galite gauti raktus ir vertes.

14
23 сент. Atsakymas, kurį pateikė Lyudmil Sep 23 2008-09-23 07:30 '08, 7:30, 2008-09-23 07:30
šaltinis

Sukurkite pasirinktinį palyginimą ir naudokite jį kurdami naują medžio žemėlapio objektą.

 class MyComparator implements Comparator<Object> { Map<String, Integer> map; public MyComparator(Map<String, Integer> map) { this.map = map; } public int compare(Object o1, Object o2) { if (map.get(o2) == map.get(o1)) return 1; else return ((Integer) map.get(o2)).compareTo((Integer) map.get(o1)); } } 

Naudokite žemiau esantį kodą savo pagrindinėje funkcijoje.

  Map<String, Integer> lMap = new HashMap<String, Integer>(); lMap.put("A", 35); lMap.put("B", 75); lMap.put("C", 50); lMap.put("D", 50); MyComparator comparator = new MyComparator(lMap); Map<String, Integer> newMap = new TreeMap<String, Integer>(comparator); newMap.putAll(lMap); System.out.println(newMap); 

Išvada:

 {B=75, D=50, C=50, A=35} 
14
10 февр. Atsakymą pateikė Sujan Reddy A 10 vasaris. 2013-02-10 09:10 '13, 9:10, 2013-02-10 09:10
šaltinis

Naudokite bendrą palyginimą, pavyzdžiui:

 final class MapValueComparator<K,V extends Comparable<V>> implements Comparator<K> { private 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)); } } 
11
05 июля '11 в 17:49 2011-07-05 17:49 atsakymą pateikė „ RoyalBigorno“ liepos 5 d. 11 d. 17:49 2011-07-05 17:49
šaltinis

Atsakymas, už kurį balsavo už daugumą, neveikia, jei turite du vienodus elementus. „TreeMap“ palieka vienodas vertes.

exmaple: nerūšiuotas žemėlapis

 raktas / vertė: D / 67.3 raktas / vertė: A / 99.5 raktas / vertė: b / 67.4 raktas / vertė: C / 67.5 raktas / vertė: E / 99,5

Rezultatai

 raktas / vertė: A / 99.5 raktas / vertė: C / 67.5 raktas / vertė: b / 67.4 raktas / vertė: D / 67.3

Taigi, E neįtraukta !!

Man tai buvo gerai, kad sukurtų lyginamąjį elementą, jei jis lygus negrąžina 0, bet -1.

pavyzdyje:

Class ValueComparator įgyvendina Comparator {

Bazinės kortelės; public ValueComparator (kortelės duomenų bazė) {this.base = base; }

public int palyginti (Objektas a, Objektas b) {

 if((Double)base.get(a) < (Double)base.get(b)) { return 1; } else if((Double)base.get(a) == (Double)base.get(b)) { return -1; } else { return -1; } 

}}

dabar jis grąžina:

nerūšiuota kortelė:

 raktas / vertė: D / 67.3 raktas / vertė: A / 99.5 raktas / vertė: b / 67.4 raktas / vertė: C / 67.5 raktas / vertė: E / 99,5

rezultatai:

 raktas / vertė: A / 99.5 raktas / vertė: E / 99,5 raktas / vertė: C / 67.5 raktas / vertė: b / 67.4 raktas / vertė: D / 67.3

kaip atsakymą į užsieniečius (2011 m. lapkričio 22 d.): naudoju šį sprendimą „Integer ID“ kortelėms ir vardams, tačiau idėja yra tokia pati, todėl gali pasirodyti, kad aukščiau nurodytas kodas yra neteisingas (aš jį užrašysiu bandyme ir suteikiu jums tinkamą kodą), tai yra rūšiavimo kodas žemėlapiai, paremti aukščiau pateiktu sprendimu:

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

ir tai yra bandymų klasė (aš tiesiog ją išbandžiau ir veikia „Integer“, „String Map“:

 package test.nl.iamit.util; import java.util.HashMap; import java.util.TreeMap; import nl.iamit.util.Comparators; import org.junit.Test; import static org.junit.Assert.assertArrayEquals; public class TestComparators { @Test public void testMapIntegerStringComparator(){ HashMap<Integer, String> unSoretedMap = new HashMap<Integer, String>(); Comparators.MapIntegerStringComparator bvc = new Comparators.MapIntegerStringComparator( unSoretedMap); TreeMap<Integer, String> sorted_map = new TreeMap<Integer, String>(bvc); //the testdata: unSoretedMap.put(new Integer(1), "E"); unSoretedMap.put(new Integer(2), "A"); unSoretedMap.put(new Integer(3), "E"); unSoretedMap.put(new Integer(4), "B"); unSoretedMap.put(new Integer(5), "F"); sorted_map.putAll(unSoretedMap); Object[] targetKeys={new Integer(2),new Integer(4),new Integer(3),new Integer(1),new Integer(5) }; Object[] currecntKeys=sorted_map.keySet().toArray(); assertArrayEquals(targetKeys,currecntKeys); } } 

Čia yra žemėlapio palyginimo kodas:

 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 -1 public 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; } } } 

ir tai yra bandymo failas:

 @Test public 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); } 

Iš kurso, jūs galite padaryti jį daug bendresnį, bet man tik reikėjo 1 atvejis (žemėlapis)

11
15 июля '11 в 12:23 2011-07-15 12:23 atsakymą pateikė michel.iamit liepos 15 d. 11 val. 12:23 2011-07-15 12:23
šaltinis

Užuot naudojusi „ Collections.sort , kaip ir kai kurie, aš siūlau naudoti „ Arrays.sort . Iš tiesų tai, ką daro Collections.sort , yra toks:

 public static <T extends Comparable<? super T>> void sort(List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } } 

Jis paprasčiausiai skambina į „ toArray “ sąrašą, tada naudoja „ Arrays.sort . Taigi visi žemėlapio įrašai bus nukopijuoti tris kartus: vieną kartą iš žemėlapio į laikinąjį sąrašą (ar „LinkedList“ ar „ArrayList“), tada į laikiną masyvą ir galiausiai į naują žemėlapį.

Mano sprendimas apeina šį žingsnį, nes jis nesukuria nereikalingo „LinkedList“. Čia yra kodas, kuris yra universalus ir optimalus našumo atžvilgiu:

 public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { @SuppressWarnings("unchecked") Map.Entry<K,V>[] array = map.entrySet().toArray(new Map.Entry[map.size()]); Arrays.sort(array, new Comparator<Map.Entry<K, V>>() { public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) { return e1.getValue().compareTo(e2.getValue()); } }); Map<K, V> result = new LinkedHashMap<K, V>(); for (Map.Entry<K, V> entry : array) result.put(entry.getKey(), entry.getValue()); return result; } 
9
30 мая '12 в 3:47 2012-05-30 03:47 atsakymas pateikiamas ciamej 30 d., 12 val. 3:47 2012-05-30 03:47
šaltinis

Tai Anthony atsakymo parinktis, kuri neveikia, jei yra dvigubų reikšmių:

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

Atkreipkite dėmesį, kad tai yra ore, kaip elgtis su nuliais.

Svarbus šio požiūrio pranašumas yra tai, kad ji iš tikrųjų grąžina žemėlapį, kitaip nei kai kurie kiti čia siūlomi sprendimai.

8
09 февр. atsakymas pateikiamas Roger 09 Feb. 2011-02-09 13:21 '11, 13:21 pm. 2011-02-09 13:21
šaltinis

Pagrindinė problema. Jei naudosite pirmąjį atsakymą („Google“ jus čia), pakeiskite lyginamąjį elementą, kad pridėtumėte lygybės sąlygą, kitaip negalėsite gauti reikšmių iš rūšiuojamo_map raktų:

 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 } 
7
18 нояб. atsakymas, kurį pateikė Cuneyt 18 lapkritis 2012-11-18 09:37 '12 at 9:37 2012-11-18 09:37
šaltinis

Jau yra daug atsakymų į šį klausimą, bet niekas man nepateikė to, ko ieškojau, žemėlapio, kuris grąžina raktus ir įrašus, suskirstytus pagal susijusias vertes, įgyvendinimą, ir saugo šią savybę kaip raktus ir vertybes į žemėlapį. Kiti du klausimai apie jį konkrečiai klausia.

Paruošiau bendrą draugišką pavyzdį, kuris išsprendžia šį precedentą. Šis įgyvendinimas neatitinka visų žemėlapio sąsajos sutarčių, pvz., Atspindi pakeitimus ir vertybių ištrynimą rinkiniuose, grąžintuose iš pradinio objekto () ir entrySet (). Jaučiau, kad toks sprendimas būtų per didelis, kad į jį būtų įtrauktas stekų perpildymas. Jei sugebėsiu sukurti išsamesnį įgyvendinimą, galbūt išsiųsiu jį į „Github“, o tada - nuorodą į ją atnaujintoje šio atsakymo versijoje.

 import java.util.*;  public class ValueSortedMap<K, V> extends HashMap<K, V> { protected Map<V, Collection<K>> valueToKeysMap; // uses natural order of value object, if any public 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; } } 
6
ответ дан David Bleckmann 24 апр. '16 в 8:11 2016-04-24 08:11
šaltinis

Лучший подход

 import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; public class OrderByValue { public static void main(String a[]){ Map<String, Integer> map = new HashMap<String, Integer>(); map.put("java", 20); map.put("C++", 45); map.put("Unix", 67); map.put("MAC", 26); map.put("Why this kolavari", 93); Set<Entry<String, Integer>> set = map.entrySet(); List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set); Collections.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() );//Ascending order //return (o2.getValue()).compareTo( o1.getValue() );//Descending order } } ); for(Map.Entry<String, Integer> entry:list){ System.out.println(entry.getKey()+" ==== "+entry.getValue()); } }} 

Выход

 java ==== 20 MAC ==== 26 C++ ==== 45 Unix ==== 67 Why this kolavari ==== 93 
6
ответ дан Nilesh Jadav 19 нояб. '15 в 13:29 2015-11-19 13:29
šaltinis

В зависимости от контекста используйте java.util.LinkedHashMap<T> , который запоминает порядок размещения элементов на карте. В противном случае, если вам нужно сортировать значения на основе их естественного упорядочения, я бы рекомендовал поддерживать отдельный список, который можно отсортировать с помощью Collections.sort() .

5
ответ дан Ryan Delucchi 21 сент. '08 в 0:07 2008-09-21 00:07
šaltinis