සිතියම් <යතුර, අගය> අගයන් අනුව වර්ග කරන්න


1647

මම ජාවා වලට සාපේක්ෂව අලුත් ය, බොහෝ විට මට Map<Key, Value>සාරධර්ම අනුව වර්ග කිරීමට අවශ්‍ය බව පෙනී යයි .

අගයන් අද්විතීය නොවන බැවින්, මම එය keySetබවට පරිවර්තනය කර array, යතුර හා සම්බන්ධිත අගය අනුව වර්ග කරන අභිරුචි සංසන්දකයෙකු සමඟ අරාව වර්ග කිරීම හරහා පෙළගස්වන්නෙමි .

පහසු ක්‍රමයක් තිබේද?


24
සිතියමක් වර්ග කිරීමට අදහස් නොකෙරේ, නමුත් වේගයෙන් ප්‍රවේශ විය හැකිය. වස්තු සමාන අගයන් සිතියමේ අවහිරතා බිඳ දමයි. ඇතුලත් කිරීමේ කට්ටලය භාවිතා කරන්න, වැනි List<Map.Entry<...>> list =new LinkedList(map.entrySet())සහ Collections.sort ....එය ඒ ආකාරයෙන්.
හැනස්

1
අපි ජාවාහි කවුන්ටරයක් ​​භාවිතා කිරීමට උත්සාහ කරන විට මෙය ඇතිවිය හැකි අවස්ථාවක් (සිතියම <වස්තුව, පූර්ණ සංඛ්‍යා>). සිදුවීම් ගණන අනුව වර්ග කිරීම පොදු මෙහෙයුමක් වනු ඇත. පයිතන් වැනි භාෂාවක් තුළ කවුන්ටර දත්ත ව්‍යුහයක් ඇත. ජාවා හි විකල්ප ක්‍රියාත්මක කිරීමේ ක්‍රමයක් සඳහා, මෙන්න උදාහරණයක්
ඩිමොන්ගෝලම්

7
වර්ග කළ සිතියම් සඳහා භාවිත අවස්ථා ඕනෑ තරම් තිබේ, ඒ නිසා ඔබට jdk හි TreeMap සහ ConcurrentSkipListMap ඇත.
alobodzk


1
TreeMap සහ ConcurrentSkipListMap යතුර අනුව වර්ග කිරීම. ප්‍රශ්නය වන්නේ අගය අනුව වර්ග කිරීම ය.
පීටර්

Answers:


906

මෙන්න සාමාන්‍ය-හිතකාමී අනුවාදයක්:

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

10
මෙය උපකාර කිරීම ගැන සතුටුයි. ජෝන්, LinkedHashMap විසඳුමට වැදගත් වන්නේ එය පුරෝකථනය කළ හැකි පුනරාවර්තන අනුපිළිවෙලක් සපයන බැවිනි.
කාටර් පිටුව

3
@ buzz3791 ඇත්ත. ඕනෑම වර්ග කිරීමේ ඇල්ගොරිතමයක එය එසේ වනු ඇත. වර්ග කිරීමකදී ව්‍යුහයක ඇති නෝඩ් වල අගය වෙනස් කිරීම අනපේක්ෂිත (හා සෑම විටම පාහේ නරක) ප්‍රති .ල ඇති කරයි.
කාටර් පිටුව

3
He ෂීගෝරත් මම එය ඇන්ඩ්‍රොයිඩ් වල අත්හදා බැලුවෙමි. ඔබ ජාවා 6 අනුවාදය භාවිතා කරන බව සලකන විට එය වේදිකා විශේෂිත ගැටළුවක් නොවේ. ඔබේ වටිනාකම් වස්තුව තුළ සැසඳිය හැකි දේ නිවැරදිව ක්‍රියාත්මක කර තිබේද ?
සයියන්කෝඩර්

6
ජාවා 8 අනුවාදය භාවිතා නොකළ යුතු forEachOrderedවෙනුවට forEachඇති චෝදනාව නිසා, forEachමෙසේ සඳහන් වෙනවා: "මෙම මෙහෙයුමේ හැසිරීම සුවිශේෂව nondeterministic වේ."?
මංකොල්ලකෑම

1
මෙය මුළුමනින්ම ඉරා දැමූ නමුත් අදහස් දැක්වීමේදී ar කාටර් පේජ් බැර කරන ලදි (එය කෙසේ හෝ විවෘත මූලාශ්‍ර ව්‍යාපෘතියක වනු ඇත). බොහෝම ස්තූතියි.
නේතන් බීච්

423

වැදගත් සටහනක්:

මෙම කේතය විවිධ ආකාරවලින් බිඳ දැමිය හැකිය. ඔබ සපයා ඇති කේතය භාවිතා කිරීමට අදහස් කරන්නේ නම්, අදහස් කියවීමට වග බලා ගන්න. උදාහරණයක් ලෙස, අගයන් ඒවායේ යතුරෙන් තවදුරටත් ලබා ගත නොහැක. ( getසෑම විටම ආපසු පැමිණේ null.)


ඉහත සඳහන් සියල්ලටම වඩා එය පහසු බව පෙනේ. පහත දැක්වෙන පරිදි 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
    }
}

ප්‍රතිදානය:

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}

18
තවත් නැත ( stackoverflow.com/questions/109383/… ). එසේම, ඩබල් වෙත රංගනයක් ඉදිරිපත් කළේ ඇයි? එය එසේ විය යුතු return ((Comparable)base.get(a).compareTo(((Comparable)base.get(b)))නොවේද?
ස්ටීවන්

12
Te ස්ටෙෆන්: නැත. මේ අවස්ථාවේ දී වටිනාකමට සමාන සියලුම යතුරු අතහැර දමනු ලැබේ (සමානාත්මතාවය හා යොමු කිරීම හා සැසඳීම අතර වෙනස). මීට අමතරව: මෙම කේතයට පවා පහත දැක්වෙන අනුක්‍රමය සමඟ ගැටලු ඇත map.put("A","1d");map.put("B","1d");map.put("C",67d);map.put("D",99.5d);
ස්ටෙෆන්

43
ගස සිතියම සඳහා භාවිතා කරන සංසන්දකය සමානකම් සමඟ නොගැලපේ (sortMap javadox බලන්න). මෙයින් අදහස් කරන්නේ ගස් සිතියමෙන් අයිතම විශ්‍රාම ගැනීම සාර්ථක නොවන බවයි. sorted_map.get ("A") ශුන්‍ය වේ. ඒ කියන්නේ මෙම සිතියම් භාවිතය කැඩී ඇත.
mR_fr0g

87
එය මිනිසුන්ට පැහැදිලි නැති අවස්ථාවකදී: එකම අගයට බහුවිධ යතුරු සිතියම් ගත කරන්නේ නම් මෙම විසඳුම ඔබට අවශ්‍ය දේ නොකරනු ඇත - වර්ග කළ ප්‍රති .ලයේ එම යතුරු වලින් එකක් පමණක් දිස්වනු ඇත.
මැක්සි-බී

63
ලුවී වස්මන් (ඔව්, ගූගල් ගුවා හි එක් අයෙක්) ඇත්ත වශයෙන්ම මෙම පිළිතුර තරමක් අකමැතියි: "ඔබ එය විහිළුවක් ලෙස බැලුවහොත් එය සැබවින්ම ව්‍යාකූල ආකාර කිහිපයකින් කැඩී යයි. පසුබිම් සිතියම වෙනස් වුවහොත් එය කැඩී යනු ඇත. එකම අගයට සිතියම, එය කැඩී යනු ඇත. ඔබ පසුබිම් සිතියමේ නොමැති යතුරක් ලබා ගැනීමට ඇමතුමක් ගත්තොත්, එය බිඳී යනු ඇත.ඔබ කිසියම් දෙයක් කළහොත් එය නොමැති යතුරක් සොයා බැලීමට හේතු වේ සිතියම - Map.equals ඇමතුමක, කේ, ඕනෑම දෙයක් අඩංගු වේ - එය ඇත්තෙන්ම අමුතු සිරස් හෝඩුවාවන් සමඟ බිඳී යනු ඇත. plus.google.com/102216152814616302326/posts/bEQLDK712MJ
haylem

345

ජාවා 8 නව පිළිතුරක් ඉදිරිපත් කරයි: ඇතුළත් කිරීම් ප්‍රවාහයක් බවට පරිවර්තනය කර සිතියමෙන් සංසන්දනාත්මක සංයෝජක භාවිතා කරන්න.

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

වටිනාකමේ අනුපිළිවෙලට වර්ග කර ඇති ප්‍රවේශයන් පරිභෝජනය කිරීමට මෙය ඔබට ඉඩ සලසයි. ඔබට අවරෝහණ අගය අවශ්‍ය නම්, සංසන්දකය ආපසු හරවන්න:

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

අගයන් සැසඳිය නොහැකි නම්, ඔබට පැහැදිලි සංසන්දකයෙකු සමත් විය හැකිය:

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

එවිට ඔබට දත්ත පරිභෝජනය සඳහා වෙනත් ප්‍රවාහ මෙහෙයුම් භාවිතා කළ හැකිය. උදාහරණයක් ලෙස, ඔබට නව සිතියමක හොඳම 10 දෙනා අවශ්‍ය නම්:

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

හෝ මුද්‍රණය කරන්න System.out:

map.entrySet().stream()
   .sorted(Map.Entry.comparingByValue())
   .forEach(System.out::println);

හොඳයි, නමුත් parallelStream()මෙම නඩුවේ භාවිතය ගැන කුමක් කිව හැකිද?
බෙන්ජ්

11
එය සමාන්තරව ක්‍රියා කරනු ඇත, කෙසේ වෙතත්, අර්ධ ප්‍රති results ල ඒකාබද්ධ කිරීම සඳහා සිතියම් ඒකාබද්ධ කිරීමේ පිරිවැය ඉතා මිල අධික වන අතර සමාන්තර අනුවාදය ක්‍රියා නොකරනු ඇති අතර ඔබ බලාපොරොත්තු වනවා සේම. නමුත් එය ක්‍රියාත්මක වන අතර නිවැරදි පිළිතුර සපයයි.
බ්‍රයන් ගොට්ස්

ඔබගේ ප්‍රයෝජනවත් උපදෙස් වලට ස්තූතියි. එය හරියටම මා කල්පනා කරමින් සිටියේ, එය ඔබ භාවිතා කරන්නේ කුමන ආකාරයේ යතුරක් සහ බොහෝ පරාමිතීන් මත වුවද ... වැදගත් දෙය නම් "එය ක්‍රියාත්මක වන අතර නිවැරදි පිළිතුර නිපදවයි".
බෙන්ජ්

2
Top10 උදාහරණයේ ඔබ සංසන්දනාත්මක බයිවලූ භාවිතා කළ යුතු නොවේද?
ලියෝ

1
En බෙන්ජ් එය ඉහළම -10 උපුටා ගැනීම අනුව ක්‍රියා කරනු ඇත, නමුත් ප්‍රති ing ලයක් ලෙස සිතියම තවදුරටත් ඇණවුම් නොකෙරේ.
OrangeDog

211

පේළි 1 ක පිළිතුරු තුනක් ...

මෙය සිදු කිරීම සඳහා මම ගූගල් එකතු ගුවා භාවිතා කරමි - ඔබේ අගයන් Comparableනම් ඔබට භාවිතා කළ හැකිය

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

එමඟින් සිතියම සඳහා ශ්‍රිතයක් (වස්තුවක්) නිර්මාණය කරනු ඇත [එය ඕනෑම යතුරක් ආදානය ලෙස ගෙන, අදාළ අගය ආපසු ලබා දෙයි], ඉන්පසු ඒවාට [අගයන්] සඳහා ස්වාභාවික (සංසන්දනාත්මක) ඇණවුමක් යොදනු ඇත.

ඒවා සැසඳිය නොහැකි නම්, එවිට ඔබට යමක් කළ යුතුය

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

මේවා TreeMap ( Orderingවිස්තාරණය වන පරිදි Comparator) හෝ යම් වර්ග කිරීමකින් පසු LinkedHashMap වෙත යෙදිය හැකිය

සැ.යු : ඔබ TreeMap භාවිතා කිරීමට යන්නේ නම්, සංසන්දනය == 0 නම්, අයිතමය දැනටමත් ලැයිස්තුවේ ඇති බව මතක තබා ගන්න (ඔබට සමාන අගයන් කිහිපයක් සසඳන විට එය සිදුවනු ඇත). මෙය සමනය කිරීම සඳහා, ඔබට ඔබේ යතුර සංසන්දකයාට එකතු කළ හැකිය (ඔබේ යතුරු සහ අගයන් යැයි උපකල්පනය කරමින් Comparable):

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

= යතුර සිතියම් ගත කළ අගයට ස්වාභාවික අනුපිළිවෙල යොදන්න, සහ යතුරේ ස්වාභාවික අනුපිළිවෙල සමඟ සංයුක්ත කරන්න

ඔබගේ යතුරු 0 සංසන්දනය නම්, නමුත් මේ බොහෝ සඳහා ප්රමාණවත් විය යුතු මෙය තවමත් වැඩ නොකරන බව සටහන comparableභාණ්ඩ (ලෙස hashCode, equalsහා compareToසමපාත වේදැයි බොහෝවිට ...)

බලන්න Ordering.onResultOf () හා Functions.forMap () .

ක්‍රියාත්මක කිරීම

ඉතින් දැන් අපට අවශ්‍ය දේ කරන සංසන්දකයෙකු අප සතුව ඇති බැවින්, එයින් අපට ප්‍රති result ලයක් ලබා ගත යුතුය.

map = ImmutableSortedMap.copyOf(myOriginalMap, valueComparator);

දැන් මෙය බොහෝ දුරට වැඩ කරනු ඇත, නමුත්:

  1. සම්පූර්ණ නිමි සිතියමක් ලබා දිය යුතුය
  2. ඉහත සංසන්දකයන් උත්සාහ නොකරන්න TreeMap; ඇතුළත් කළ යතුරක් වටිනාකමක් නොමැති විට එය සංසන්දනය කිරීමට උත්සාහ කිරීමෙන් පලක් නැත, එනම්, එය වේගයෙන් කැඩී යයි

පොයින්ට් 1 මට ටිකක් ගනුදෙනු කරන්නෙක්; ගූගල් එකතු කිරීම ඇදහිය නොහැකි තරම් කම්මැලි ය (එය හොඳයි: ඔබට සෑම ක්‍රියාවක්ම ක්ෂණිකව කළ හැකිය; සැබෑ කාර්යය ඔබ ප්‍රති result ලය භාවිතා කිරීමට පටන් ගත් විට සිදු වේ), මේ සඳහා සම්පූර්ණ සිතියමක් පිටපත් කිරීම අවශ්‍ය වේ !

"සම්පූර්ණ" පිළිතුර / සාරධර්ම අනුව සජීවීව වර්ග කළ සිතියම

කෙසේ වෙතත් කරදර නොවන්න; "සජීවී" සිතියමක් මේ ආකාරයෙන් වර්ග කර තිබීම පිළිබඳව ඔබ දැඩි ලෙස උමතු වී ඇත්නම්, ඉහත ගැටළු වලින් එකක් පමණක් නොව (!) දෙකම පහත දැක්වෙන පිස්සු වැනි දේ සමඟ විසඳා ගත හැකිය:

සටහන: මෙය 2012 ජුනි මාසයේදී සැලකිය යුතු ලෙස වෙනස් වී ඇත - පෙර කේතය කිසි විටෙකත් ක්‍රියා කළ නොහැක: TreeMap.get()-> compare()සහ compare()-> අතර අසීමිත පුඩුවක් නිර්මාණය නොකර අගයන් සොයා බැලීමට අභ්‍යන්තර හැෂ්මැප් අවශ්‍ය වේ.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'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 keys
        map.put("e", 2);
        assertEquals(5, map.size());
        assertEquals(2, (int) map.get("e"));
        assertEquals(2, (int) map.get("d"));
    }
 }

අපි දැමූ විට, හැෂ් සිතියමට සංසන්දකය සඳහා වටිනාකමක් ඇති බව අපි සහතික කරමු, ඉන්පසු වර්ග කිරීම සඳහා ට්‍රීසෙට් වෙත දමමු. නමුත් ඊට පෙර අපි යතුර ඇත්ත වශයෙන්ම අනුපිටපතක් නොවන බව බැලීමට හැෂ් සිතියම පරීක්ෂා කරමු. එසේම, අප විසින් සාදන සංසන්දකයාට යතුරද ඇතුළත් වන අතර එමඟින් අනුපිටපත් අගයන් අනුපිටපත් නොවන යතුරු මකා නොදමනු ඇත (== සංසන්දනය හේතුවෙන්). සිතියම් කොන්ත්රාත්තුව තබා ගැනීම සහතික කිරීම සඳහා මෙම අයිතම 2 ඉතා වැදගත් වේ; ඔබට එය අවශ්‍ය නැතැයි ඔබ සිතන්නේ නම්, ඔබ සිතියම මුළුමනින්ම ආපසු හැරවීමට ආසන්නව සිටී Map<V,K>.

ඉදිකිරීම්කරු ලෙස හැඳින්විය යුතුය

 new ValueComparableMap(Ordering.natural());
 //or
 new ValueComparableMap(Ordering.from(comparator));

හායි te ස්ටෙෆන්, ඇණවුම් කිරීම භාවිතා කරන්නේ කෙසේදැයි ඔබට උදාහරණයක් දිය හැකිද? මම ඇණවුම් කිරීමේ ප්‍රභව කේතය සොයා බැලුවෙමි .සමහර (.) .ResultOf (...) ප්‍රතිලාභ මොනවාදැයි මුළුමනින්ම වටහා ගත නොහැක. ප්‍රභව කේතය "පොදු <F> ඇණවුම් කිරීම <F> onResultOf", එය සම්පාදනය කරන්නේ කෙසේදැයි මම නොදනිමි! වැදගත්ම දේ, සිතියමක් වර්ග කිරීම සඳහා "<F> ඇණවුම් කිරීම <F>" භාවිතා කරන්නේ කෙසේද? එය සංසන්දකයෙකු හෝ යමක් ද? ස්තූතියි.
smallufo

Orderingහුදෙක් ධනවත් ය Comparator. මම එක් එක් උදාහරණය අදහස් දැක්වීමට උත්සාහ කර ඇත්තෙමි (එක් එක් යටින් ඇති ඇල අකුරු). “ස්වාභාවික” යන්නෙන් දැක්වෙන්නේ වස්තූන් ය Comparable; එය අපාචේ පොදුගේ සංසන්දනාත්මක සංසන්දකය වැනි ය. onResultOfසංසන්දනය කරන අයිතමයට ශ්‍රිතයක් අදාළ වේ. එබැවින් ඔබට පූර්ණ සංඛ්‍යාවක් සඳහා 1 එකතු කළ ශ්‍රිතයක් තිබේ නම්, natural().onResultOf(add1Function).compare(1,2)එය අවසන් වනු ඇත2.compareTo(3)
ස්ටීවන්

මුල් සිතියමේ අනුපිටපත් අගයන් තිබේ නම් ImmutableSortedMap.copyOf නීති විරෝධී ආරෝපණ එක්සෙප්ෂන් විසි කරයි.
lbalazscs

BIbalazscs ඔව් එය එසේ වනු ඇත - ඔබට අනුපිටපත් විචල්‍යයන් භාවිතා කිරීමට ImmutableSetMultiMapහෝ ImmutableListMultiMapඅඩංගු කිරීමට හැකි විය යුතුය .
ස්ටීවන්

1
මේ සඳහා ස්තූතියි, මම ඔබේ විසඳුම එක් ව්‍යාපෘතියක භාවිතා කළෙමි. කෙසේ වෙතත්, ගැටලුවක් ඇති බව මම සිතමි: සිතියමක් මෙන් හැසිරීමට එය යතුර සමඟ කලින් සම්බන්ධ කර ඇති අගය ආපසු ලබා දිය යුතුය, එය තිබේ නම්, නමුත් මේ ආකාරයට එය කිසි විටෙකත් සිදු නොවේ. මා භාවිතා කළ විසඳුම නම් ඉවත් කළ අගය තිබේ නම් එය ආපසු ලබා දීමයි.
ඇලෙක්ස්

185

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

16
වර්ග කළ යුතු ලැයිස්තුව "නව සම්බන්ධක ලැයිස්තුව" ?? ගී. ස්තූතිවන්ත වන Collections.sort () මෙම ආකාරයේ වැරැද්දක් වළක්වා ගැනීම සඳහා පළමුව ලැයිස්තුව අරාවකට දමන්න (නමුත් තවමත්, අරා ලැයිස්තුවක් අරාවකට ඇද දැමීම සම්බන්ධක ලැයිස්තුවක් සඳහා එය කිරීමට වඩා වේගවත් විය යුතුය).
ඩිමිට්‍රිස් ඇන්ඩෘ

ඉටරේටරයේ සිට ටර්නරිට්‍රී බවට පරිවර්තනය කළ නොහැක. ඉරේටරේටර්
ලිසාක්

4
g gg.kaspersky මම "සම්බන්ධක ලැයිස්තුවක් වර්ග කිරීම නරකයි" යැයි නොකියමි, නමුත් වර්ග කිරීම නොසලකා සබැඳි ලැයිස්තුව මෙහි නරක තේරීමක් වේ. බොහෝ වඩා හොඳ යනු ArrayList, සහ අමතර ලකුණු සඳහා, හරියටම map.size (දී විශාලත්වය එය) භාවිතා කිරීමට. ArrayList හි එක් මූලද්‍රව්‍යයක් සඳහා code.google.com/p/memory-measurer/wiki/… සාමාන්‍ය පිරිවැය ද බලන්න: LinkedList හි එක් මූලද්‍රව්‍යයකට බයිට් 5 ක සාමාන්‍ය පිරිවැය: බයිට් 24. හරියටම ප්‍රමාණයේ අරා ලැයිස්තු සඳහා සාමාන්‍ය පිරිවැය බයිට් 4 කි. බව LinkedList ගනී, වන සය ArrayList අවශ්ය බව මතක ප්රමාණය වතාවක්. එය නිකම්ම පිපිරී ඇත
ඩිමිට්‍රිස් ඇන්ඩෘ

2
ඉහත අගයන් භාවිතා කිරීම ආරෝහණ අනුපිළිවෙලට වර්ග කර ඇත. බැසීමේදී වර්ග කරන්නේ කෙසේද?
ram

1
අවරෝහණය වර්ග කිරීම සඳහා o1 සහ o2 ආදේශ කරන්න.
සොහෙයිල්

72

ජාවා 8 සමඟ, ඔබට සැලකිය යුතු ලෙස අඩු වාචික ආකාරයකින් එය කිරීමට api ධාරා භාවිතා කළ හැකිය :

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

එය ප්‍රතිලෝම අනුපිළිවෙලකට වර්ග කරන්නේ කෙසේද?
ව්ලැඩ් හොලූබීව්

6
විසඳුමක් සොයා ගත්තා -Collections.reverseOrder(comparing(Entry::getValue))
ව්ලැඩ් හොලූබීව්

1
මම හිතන්නේ මම එහි යතුරු ලියනයක දකිනවා - “ToMap” “Collectors.toMap ()” ලෙස හැඳින්විය යුතු නොවේද?
ජේක් ස්ටොක්ස්

1
Ake ජේක්ස්ටොක්ස් හෝ ස්ථිතික ආනයනයක් භාවිතා කරන්න :-)
assylias

6
ප්‍රතිලෝම අනුපිළිවෙලින් ඇතුළත් වීමේ අගය අනුව වර්ග කිරීමට වඩා හොඳ ක්‍රමයක් නම්:Entry.comparingByValue(Comparator.reverseOrder())
ගෙඩිමිනාස් රිම්සා

32

යතුරු වර්ග කිරීම සඳහා එක් එක් සංසන්දනය සඳහා එක් එක් අගය සොයා බැලීමට සංසන්දකයාට අවශ්‍ය වේ. වඩාත් පරිමාණය කළ හැකි විසඳුමක් කෙලින්ම පිවිසුම් කට්ටලය භාවිතා කරනු ඇත, එතැන් සිට සෑම සැසඳීමක් සඳහාම අගය වහාම ලබා ගත හැකිය (මම මෙය සංඛ්‍යා වලින් උපස්ථ කර නොතිබුණද).

මෙන්න එවැනි දෙයක සාමාන්‍ය අනුවාදය:

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

අවසාන වශයෙන්, ඔබට නිරන්තරයෙන් වර්ග කළ තොරතුරු වෙත ප්‍රවේශ වීමට අවශ්‍ය නම් (වරකට වරක් එය වර්ග කිරීම වෙනුවට), ඔබට අතිරේක බහු සිතියමක් භාවිතා කළ හැකිය. ඔබට වැඩි විස්තර අවශ්‍ය නම් මට දන්වන්න ...


ලැයිස්තුව <සිතියම. එන්ට්‍රි <කේ, වී >> ඔබ ආපසු එවන්නේ නම් දෙවන අනුවාදය වඩාත් සංක්ෂිප්ත විය හැකිය. මේ සියල්ලම උපකල්පනය කරන්නේ මෙම කේතය නූල් අනාරක්ෂිත වීම නිසා ඔබ හොඳින් කියාය. පසුබිම් සිතියම හෝ වර්ග කළ ලැයිස්තුව බහු තෙරපුම් පරිසරයක බෙදාගෙන තිබේ නම්, සියලු ඔට්ටු අක්‍රීයයි.
මයික් මිලර්

26

කොමන්ස් -එකතු කිරීමේ පුස්තකාලයේ TreeBidiMap නමින් විසඳුමක් අඩංගු වේ . නැතහොත්, ඔබට ගූගල් එකතු කිරීමේ API දෙස බැලිය හැකිය. ඔබට භාවිතා කළ හැකි TreeMultimap එහි ඇත .

ඔබට මෙම රාමුව භාවිතා කිරීමට අවශ්‍ය නැතිනම් ... ඒවා ප්‍රභව කේත සමඟ පැමිණේ.


ඔබ කොමන්ස් එකතුව භාවිතා කළ යුතු නැත. ජාවා තමන්ගේම java.util.TreeMap සමඟ පැමිණේ.
යොලිහෝ

2
ඔව්, නමුත් සිතියම්වල අගය කොටස අනුව වර්ග කිරීමේදී ට්‍රීමැප් නම්යශීලී නොවේ.
p3t0r

9
බිඩිමැප් හි ඇති කරදරය නම්, සම්බන්ධතාවය ප්‍රතිලෝමව සිදු කිරීම සඳහා යතුරු සහ අගයන් අතර 1: 1 සම්බන්ධතා බාධකයක් එක් කිරීමයි (එනම් යතුරු සහ අගයන් දෙකම අද්විතීය විය යුතුය). මෙයින් අදහස් කරන්නේ වචන ගණන් කිරීමේ වස්තුවක් වැනි දෙයක් ගබඩා කිරීමට ඔබට මෙය භාවිතා කළ නොහැකි බැවින් බොහෝ වචන එකම ගණන් ඇති බැවිනි.
ඩග්

26

මම දී ඇති පිළිතුරු දෙස බැලුවෙමි, නමුත් ඒවායින් බොහොමයක් අවශ්‍යතාවයට වඩා සංකීර්ණ හෝ යතුරු කිහිපයකට එකම අගයක් ඇති විට සිතියම් අංග ඉවත් කරන්න.

මෙන්න වඩා සුදුසු යැයි මා සිතන විසඳුමක්:

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

සිතියම ඉහළම අගයේ සිට පහළම දක්වා වර්ග කර ඇති බව සලකන්න.


6
ගැටලුව: ඔබට පසුව ආපසු ලබා දුන් සිතියම භාවිතා කිරීමට අවශ්‍ය නම්, උදාහරණයක් ලෙස එහි කිසියම් මූලද්‍රව්‍යයක් තිබේදැයි පරීක්ෂා කිරීමට, ඔබේ අභිරුචි සංසන්දකය නිසා ඔබ සැමවිටම අසත්‍ය වනු ඇත! හැකි විසඳුමක්: අවසාන පේළිය ආදේශ කරන්න: නව LinkedHashMap <K, V> (sortedByValues) ආපසු එවන්න;
එරල් සේගල්-හලේවි

@ErelSegalHalevi පෙන්වා දුන් කාරණය හැරුණු විට මෙය මට පිරිසිදු විසඳුමක් ලෙස පෙනේ, ඔබ සංසන්දකයා නියම කළ පරිදි සිතියමේ අගයන් තිබේදැයි පරීක්ෂා කිරීම කළ නොහැකි වනු ඇත. map.put ("1", "එක්"); map.put ("2", "දෙක"); map.put ("3", "තුන"); map.put ("4", "හතර"); map.put ("5", "පහ"); map.containsKey ("1") සෑම විටම සාවද්‍ය වනු ඇත, ඔබ ශ්‍රිතයේ නව වස්තුවක් ආපසු හරවන්නේ නම් sortByValues ​​() නව TreeMap <K, V> (sortedByValues) වැනි; ගැටළුව විසඳයි. ස්තූතියි අභි
අභි

පරිශීලක 157196 සහ කාටර් පේජ්ගේ පිළිතුරට බොහෝ සෙයින් සමාන ය. කාටර් පේජ් හි LinkedHashMap fix
Kirby

විසඳුමේ 4 වන පේළිය int සංසන්දනය කළ යුතුය = map.get (k1) .compareTo (map.get (k2)); ඔබට නැගීමේ ඇණවුමක් අවශ්‍ය නම්
www.Decompiler.com

19

ජාවා 8 හි නව අංග සමඟ මෙය ඉටු කිරීම සඳහා:

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

ලබා දී ඇති සංසන්දකය භාවිතා කර ඇතුළත් කිරීම් ඒවායේ අගයන් අනුව ඇණවුම් කරනු ලැබේ. විකල්පයක් ලෙස, ඔබේ අගයන් අන්‍යෝන්‍ය වශයෙන් සැසඳිය හැකි නම්, පැහැදිලි සංසන්දකයෙකු අවශ්‍ය නොවේ:

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

ආපසු ලබා දුන් ලැයිස්තුව මෙම ක්‍රමය හැඳින්වූ අවස්ථාවේ දී ලබා දුන් සිතියමේ කෙටි සටහනකි, එබැවින් අනෙකාට පසුව සිදුවන වෙනස්කම් පිළිබිඹු නොවේ. සිතියම සජීවීව නැරඹිය හැකි දර්ශනයක් සඳහා:

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

ආපසු ලබා දුන් නැවත ලබා ගත හැකි සෑම අවස්ථාවකම එය ලබා දුන් සිතියමේ නැවුම් ඡායාරූපයක් නිර්මාණය කරයි, එබැවින් සමගාමී වෙනස් කිරීම හැර, එය සැමවිටම සිතියමේ වත්මන් තත්වය පිළිබිඹු කරයි.


මෙය අගය අනුව වර්ග කළ සිතියමකට වඩා ඇතුළත් කිරීම් ලැයිස්තුවක් ලබා දෙයි. සිතියමක් ලබා දෙන වෙනත් අනුවාදය: stackoverflow.com/a/22132422/829571
assylias

17

අභිරුචි කරන ලද සංසන්දකය සාදන්න සහ නව TreeMap වස්තුවක් නිර්මාණය කිරීමේදී එය භාවිතා කරන්න.

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

    }
}

ඔබගේ ප්‍රධාන විනෝදයේදී පහත කේතය භාවිතා කරන්න

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

ප්‍රතිදානය:

{B=75, D=50, C=50, A=35}

අගයන් සමාන නම්, යතුරු සංසන්දනය කිරීම සඳහා මම "ආපසු 1" රේඛාව වෙනස් කළෙමි: "ආපසු ((නූල්) o1) .කොම්පෙටෝ ((සංගීත) o2);"
gjgjgj

14

සිතියමක් වර්ග කිරීමේ නිරන්තර අවශ්‍යතාවය ගඳක් බව මම එකඟ වන අතර, පහත දැක්වෙන කේතය වෙනත් දත්ත ව්‍යුහයක් භාවිතා නොකර එය කිරීමට පහසුම ක්‍රමය යැයි මම සිතමි.

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

}

අපහසුතාවයට පත් අසම්පූර්ණ ඒකක පරීක්ෂණයක් මෙන්න:

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

}

ප්‍රති result ලය වන්නේ සිතියම් වර්ග කළ ලැයිස්තුවකි.එන්ට්‍රි වස්තු, එයින් ඔබට යතුරු සහ අගයන් ලබා ගත හැකිය.


සිතියම <V, ලැයිස්තු <K>> වස්තුවක් සෑදීමට වඩා මෙම ක්‍රමය වඩා පහසු හා වඩා බුද්ධිමත් ය. අගයන් සැබවින්ම සිතියම් වස්තුවක යතුරු විය යුතු නැත, ඔබ සැබවින්ම සොයන්නේ මෙම තත්වයේ ලැයිස්තුවක් වන IMHO.
ජෙෆ් වු

මෙම විසඳුම බොහෝ අගයන් සමඟ ක්‍රියා නොකරයි, එය මගේ ගණන් සමඟ ඉස්කුරුප්පු කර ඇත (එක් එක් යතුර සමඟ සම්බන්ධිත අගය)
සෑම් ලෙවින්

1
ඒක අමුතුයි. ඔබට විස්තර කළ හැකිද? ඔබේ ප්‍රතිදානය කුමක්ද සහ ඔබ අපේක්ෂා කළ ප්‍රතිදානය කුමක්ද?
ලියුඩ්මිල්

12

වැනි සාමාන්‍ය සංසන්දකයෙකු භාවිතා කරන්න:

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

ඔබට සමාන අයිතම 2 ක් ඇති විට වැඩිපුරම ඡන්දය දුන් පිළිතුර ක්‍රියා නොකරයි. TreeMap සමාන අගයන් පිට කරයි.

exmaple: වර්ගීකරණය නොකළ සිතියම

යතුර / අගය: ඩී / 67.3
යතුර / අගය: A / 99.5
යතුර / අගය: බී / 67.4
යතුර / අගය: සී / 67.5
යතුර / අගය: ඊ / 99.5

ප්රතිපල

යතුර / අගය: A / 99.5
යතුර / අගය: සී / 67.5
යතුර / අගය: බී / 67.4
යතුර / අගය: ඩී / 67.3

ඉතින් ඊ !!

මට නම් එය සංසන්දකය සකස් කිරීම සඳහා හොඳින් ක්‍රියා කළේය, එය සමාන නම් 0 නොව -1.

උදාහරණයක් ලෙස:

පන්තියේ අගය සංසන්දකය සංසන්දකය ක්‍රියාත්මක කරයි {

සිතියම් පදනම; public ValueComparator (සිතියම් පදනම) {this.base = base; }

public int සංසන්දනය කරන්න (වස්තුව a, වස්තුව 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;
}

}}

දැන් එය නැවත පැමිණේ:

වර්ග නොකළ සිතියම:

යතුර / අගය: ඩී / 67.3
යතුර / අගය: A / 99.5
යතුර / අගය: බී / 67.4
යතුර / අගය: සී / 67.5
යතුර / අගය: ඊ / 99.5

ප්රතිපල:

යතුර / අගය: A / 99.5
යතුර / අගය: ඊ / 99.5
යතුර / අගය: සී / 67.5
යතුර / අගය: බී / 67.4
යතුර / අගය: ඩී / 67.3

පිටසක්වල ජීවීන්ට ප්‍රතිචාරයක් ලෙස (2011 නොවැ. 22): මම මෙම විසඳුම භාවිතා කරන්නේ පූර්ණ සංඛ්‍යා හැඳුනුම්පත් සහ නම් සිතියමක් සඳහා ය, නමුත් අදහස එක හා සමාන ය, එබැවින් ඉහත කේතය නිවැරදි නොවිය හැකිය (මම එය පරීක්ෂණයකින් ලියමි ඔබට නිවැරදි කේතය ලබා දෙන්න), ඉහත විසඳුම මත පදනම්ව සිතියම් වර්ග කිරීම සඳහා වන කේතය මෙයයි:

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


}

මෙය පරීක්ෂණ පන්තියයි (මම එය අත්හදා බැලුවෙමි, මෙය පූර්ණ සංඛ්‍යා, සංගීත සිතියම සඳහා ක්‍රියා කරයි:

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

සිතියමක සංසන්දකයා සඳහා කේතය මෙන්න:

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

මේ සඳහා වන පරීක්ෂණය මෙයයි:

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

ඇත්තෙන්ම ඔබට මෙය වඩාත් සාමාන්‍ය දෙයක් බවට පත් කළ හැකිය, නමුත් මට එය අවශ්‍ය වූයේ 1 අවස්ථාව සඳහා පමණි (සිතියම)


ඔබ හරි, මම මුලින් දුන් කේතයේ යම් දෝෂයක් ඇති විය! මගේ මෑත සංස්කරණය ඔබට උපකාරී වනු ඇතැයි මම බලාපොරොත්තු වෙමි.
michel.iamit

9

Collections.sortසමහරක් ලෙස භාවිතා කරනවා වෙනුවට මම යෝජනා කරන්නේ භාවිතා කිරීමට ය Arrays.sort. ඇත්තටම Collections.sortකරන්නේ මේ වගේ දෙයක්:

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

එය toArrayලැයිස්තුවට ඇමතුමක් ලබා දී පසුව භාවිතා කරයි Arrays.sort. මේ ආකාරයෙන් සියලුම සිතියම් ඇතුළත් කිරීම් තුන් වරක් පිටපත් කරනු ලැබේ: එක් වරක් සිතියමේ සිට තාවකාලික ලැයිස්තුවට (එය සම්බන්ධක ලැයිස්තුවක් හෝ අරා ලැයිස්තුවක් වේවා), පසුව තාවකාලික අරාව සහ අවසානයේ නව සිතියම වෙත.

මගේ විසඳුම අනවශ්‍ය සබැඳි ලැයිස්තුවක් නිර්මාණය නොකරන බැවින් මෙම එක් පියවරක් මග හැරේ. මෙන්න කේතය, සාමාන්‍ය-හිතකාමී සහ කාර්ය සාධනය-ප්‍රශස්ත:

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

8

මෙය ඇන්තනිගේ පිළිතුරේ විචලනයකි, අනුපිටපත් අගයන් තිබේ නම් එය ක්‍රියා නොකරයි:

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

ශුන්‍යයන් හැසිරවිය යුතු ආකාරය වාතයේ තරමක් ඉහළ මට්ටමක පවතින බව සලකන්න.

මෙම ප්‍රවේශයේ එක් වැදගත් වාසියක් නම්, මෙහි ඉදිරිපත් කර ඇති වෙනත් විසඳුම් මෙන් නොව එය සැබවින්ම සිතියමක් ලබා දීමයි.


එය වැරදියි, අනුපිටපත් අගයන් තිබේ නම් මගේ ක්‍රමය ක්‍රියාත්මක වේ. "1" අගය සහිත යතුරු 100 කට වඩා ඇති සිතියම් සමඟ මම එය භාවිතා කර ඇත්තෙමි.
ඇන්තනි

8

හොඳම ප්‍රවේශය

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

8

සිතියම ලබා දී ඇත

   Map<String, Integer> wordCounts = new HashMap<>();
    wordCounts.put("USA", 100);
    wordCounts.put("jobs", 200);
    wordCounts.put("software", 50);
    wordCounts.put("technology", 70);
    wordCounts.put("opportunity", 200);

ආරෝහණ අනුපිළිවෙලෙහි අගය මත පදනම්ව සිතියම වර්ග කරන්න

Map<String,Integer>  sortedMap =  wordCounts.entrySet().
                                                stream().
                                                sorted(Map.Entry.comparingByValue()).
        collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    System.out.println(sortedMap);

අවරෝහණ අනුපිළිවෙලෙහි වටිනාකම මත පදනම්ව සිතියම වර්ග කරන්න

Map<String,Integer>  sortedMapReverseOrder =  wordCounts.entrySet().
            stream().
            sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).
            collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    System.out.println(sortedMapReverseOrder);

ප්‍රතිදානය:

{මෘදුකාංග = 50, තාක්‍ෂණය = 70, ඇමරිකා එක්සත් ජනපදය = 100, රැකියා = 200, අවස්ථාව = 200}

{රැකියා = 200, අවස්ථාව = 200, ඇමරිකා එක්සත් ජනපදය = 100, තාක්‍ෂණය = 70, මෘදුකාංග = 50}


එය ක්‍රියාත්මක වන නමුත් හැෂ්මැප් එකක මූලද්‍රව්‍ය අනුපිළිවෙල ක්‍රියාත්මක වන්නේ කෙසේදැයි මට තේරෙන්නේ නැත?
අලි ටූ

7

ප්රධාන ගැටළුව. ඔබ පළමු පිළිතුර භාවිතා කරන්නේ නම් (ගූගල් ඔබව මෙහි ගෙන යයි), සමාන වගන්තියක් එක් කිරීමට සංසන්දකය වෙනස් කරන්න, එසේ නොමැතිනම් ඔබට යතුරු මගින් sorted_map වෙතින් අගයන් ලබා ගත නොහැක:

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
    }

දැන් ඔබ සමාන අගයන් සහිත ඇතුළත් කිරීම් දෙකක් එකතු කළ විට ඒවා ඒකාබද්ධ වනු ඇත. ඔබ ආපසු එවිය යුත්තේ වස්තූන් එක සමාන බව ඔබට විශ්වාස නම් (සමාන)
Masood_mj

7

මෙම ප්‍රශ්නයට මේ වන විටත් පිළිතුරු රාශියක් ඇත, නමුත් මා සොයන දේ කිසිවෙකු මට ලබා දී නැත, සිතියම් ක්‍රියාත්මක කිරීම මඟින් යතුරු සහ ඇතුළත් කිරීම් ආශ්‍රිත අගය අනුව වර්ග කර සිතියමෙහි යතුරු සහ අගයන් වෙනස් කර ඇති බැවින් මෙම දේපල නඩත්තු කරයි. තවත් ප්‍රශ්න දෙකක් මෙය විශේෂයෙන් අසයි.

මෙම භාවිත අවස්ථාව විසඳන සාමාන්‍ය මිත්‍රශීලී උදාහරණයක් මම පිසුවෙමි. මෙම ක්‍රියාවට නැංවීම සිතියම් අතුරුමුහුණතේ සියලුම කොන්ත්‍රාත්තු වලට ගරු නොකරයි, එනම් කට්ටලවල අගය වෙනස්වීම් සහ ඉවත් කිරීම් පිළිබිඹු කිරීම, මුල් වස්තුවෙහි යතුරු කට්ටලය () සහ එන්ට්‍රිසෙට් () වෙතින් ආපසු පැමිණේ. එවැනි විසඳුමක් තොග පිටාර ගැලීමේ පිළිතුරකට ඇතුළත් කිරීමට නොහැකි තරම් විශාල වනු ඇතැයි මට හැඟුණි. මම වඩාත් සම්පූර්ණ ක්‍රියාත්මක කිරීමක් නිර්මාණය කිරීමට සමත් වුවහොත්, සමහර විට මම එය ගිතූබ් වෙත පළ කර මෙම පිළිතුරේ යාවත්කාලීන කළ අනුවාදයකට එය සම්බන්ධ කරමි.

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

ප්‍රමාද ප්‍රවේශය.

ජාවා -8 පැමිණීමත් සමඟ අපට දත්ත හැසිරවීම සඳහා ඉතා පහසු / සංක්ෂිප්ත ආකාරයකින් ධාරාවන් භාවිතා කළ හැකිය. සිතියම් ඇතුළත් කිරීම් අගය අනුව වර්ග කිරීමට සහ ඇතුළත් කිරීම්-ඇණවුම් පුනරාවර්තනය ආරක්ෂා කරන LinkedHashMap නිර්මාණය කිරීමට ඔබට ධාරාවන් භාවිතා කළ හැකිය .

උදා:

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

ආපසු හැරවීම සඳහා, ප්රතිස්ථාපනය කරන්න:

comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey)

සමග

comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey).reversed()

මෙම අදහස් දැක්වූ අනුවාදයට ස්තූතියි. එක ප්රශ්නයක්: භාවිතා ඇති වෙනස කුමක්ද Entry.comparingByValue()(ඉහත assylias පිළිතුර ලෙස stackoverflow.com/a/22132422/1480587 ) හෝcomparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey) ඔබ භාවිතා කුමක්ද? අගයන් සමාන නම් ඔබත් යතුරු සංසන්දනය කරන බව මට තේරෙනවා නේද? වර්ග කිරීම එකම අගයක් සහිත මූලද්‍රව්‍ය අනුපිළිවෙලක් තබා ඇති බව මම දුටුවෙමි - එබැවින් යතුරු දැනටමත් වර්ග කර තිබේ නම් යතුරු මගින් වර්ග කිරීම අවශ්‍යද?
පීටර් ටී.

5

සන්දර්භය මත පදනම්ව java.util.LinkedHashMap<T>, සිතියම තුළ අයිතම තැන්පත් කර ඇති අනුපිළිවෙල මතකයට නංවන දේ භාවිතා කිරීම. එසේ නොමැතිනම්, ඒවායේ ස්වාභාවික අනුපිළිවෙල මත පදනම්ව ඔබට අගයන් වර්ග කිරීමට අවශ්‍ය නම්, ඒ අනුව වර්ග කළ හැකි වෙනම ලැයිස්තුවක් පවත්වා ගැනීමට මම නිර්දේශ කරමි Collections.sort().


මෙය -1 වූයේ මන්දැයි මට නොපෙනේ, මෙතෙක් LinkedHashMap මට හොඳම විසඳුම විය හැකිය, මම උත්සාහ කරන්නේ ඉවත දමා නව LinkedHashMap නිර්මාණය කිරීම කොතරම් මිල අධිකද යන්න සොයා ගැනීමටය.
NobleUplift

5

සිට TreeMap <> වැඩ කරන්නේ නැහැ සමාන විය හැකි බව වටිනාකම් සඳහා, මම මේ භාවිතා:

private <K, V extends Comparable<? super V>> List<Entry<K, V>> sort(Map<K, V> map)     {
    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
            return o1.getValue().compareTo(o2.getValue());
        }
    });

    return list;
}

ඔබට LinkedHashMap හි ලැයිස්තුවක් තැබීමට අවශ්‍ය විය හැකිය , නමුත් ඔබ ඒ යන්නේ නම්, එය අතිරික්තය ...


එය හරි නමුත් ඔබේ සංසන්දකයා සමාන අගයන් නඩත්තු නොකරයි
සෙබස්තියන් ලෝර්බර්

5

මෙය ඉතා සංකීර්ණයි. සිතියම් අගය අනුව ඒවා වර්ග කිරීම වැනි කාර්යයක් කිරීමට බලාපොරොත්තු නොවීය. පහසුම ක්‍රමය වන්නේ ඔබේ අවශ්‍යතාවයට සරිලන පරිදි ඔබේම පන්තියක් නිර්මාණය කිරීමයි.

උදාහරණයක් ලෙස පහළ ඔබ * සිටින ස්ථානයේ TreeMap සංසන්දකයෙකු එක් කළ යුතුය. නමුත් ජාවා ඒපීඅයි මගින් එය ලබා දෙන්නේ සංසන්දකයාට යතුරු පමණක් මිස අගයන් නොවේ. මෙහි දක්වා ඇති සියලුම උදාහරණ සිතියම් 2 මත පදනම් වේ. එක් හෑෂ් එකක් සහ නව ගසක්. අමුතුයි.

උදාහරණය:

Map<Driver driver, Float time> map = new TreeMap<Driver driver, Float time>(*);

එබැවින් සිතියම මේ ආකාරයෙන් කට්ටලයක් බවට වෙනස් කරන්න:

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

4

Vin ඩෙවින්මූර් කේතය මත පදනම්ව, සිතියම් වර්ග කිරීම ජනක විද්‍යාව භාවිතා කරමින් සහ නැගීමේ සහ බැසීමේ අනුපිළිවෙලට සහාය වේ.

/**
 * 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
}

නැවත වරක් වඩා හොඳ විසඳුමක් වනුයේ ස්වයං වර්ග කිරීමේ සිතියමක් භාවිතා කිරීමයි, එසේ නම් org.apache.commons.collections.bidimap.TreeBidiMap
මැක්සිම් වෙක්ස්ලර්

4

මෙන්න OO විසඳුමක් (එනම් staticක්‍රම භාවිතා නොකරයි ):

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class SortableValueMap<K, V extends Comparable<V>>
  extends LinkedHashMap<K, V> {
  public SortableValueMap() { }

  public SortableValueMap( Map<K, V> map ) {
    super( map );
  }

  public void sortByValue() {
    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>( entrySet() );

    Collections.sort( list, new Comparator<Map.Entry<K, V>>() {
      public int compare( Map.Entry<K, V> entry1, Map.Entry<K, V> entry2 ) {
        return entry1.getValue().compareTo( entry2.getValue() );
      }
    });

    clear();

    for( Map.Entry<K, V> entry : list ) {
      put( entry.getKey(), entry.getValue() );
    }
  }

  private static void print( String text, Map<String, Double> map ) {
    System.out.println( text );

    for( String key : map.keySet() ) {
      System.out.println( "key/value: " + key + "/" + map.get( key ) );
    }
  }

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

    map.put( "A", 67.5 );
    map.put( "B", 99.5 );
    map.put( "C", 82.4 );
    map.put( "D", 42.0 );

    print( "Unsorted map", map );
    map.sortByValue();
    print( "Sorted map", map );
  }
}

මෙයින් පොදු වසමට පරිත්‍යාග කරනු ලැබේ.


4

අෆයික් වඩාත්ම පිරිසිදු ක්‍රමය වන්නේ අගය මත සිතියම වර්ග කිරීම සඳහා එකතු කිරීම් භාවිතා කිරීමයි:

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

4

අනුපිටපත් අගයන් ඇති යුගල සමඟ වර්ග කළ සිතියමක් ලබා ගැනීම සඳහා සරල වෙනස්කම් කිහිපයක්. සංසන්දනය කිරීමේ ක්‍රමයේදී (පන්ති අගය සංයුක්තකය) අගයන් සමාන වන විට 0 ආපසු නොයන නමුත් යතුරු 2 සංසන්දනය කිරීමේ ප්‍රති return ලය ලබා දෙන්න. යතුරු සිතියමක එකිනෙකට වෙනස් බැවින් අනුපිටපත් අගයන් තබා ගැනීමට ඔබ සමත් වේ (ඒවා යතුරු මගින් වර්ග කර ඇත). එබැවින් ඉහත උදාහරණය මේ ආකාරයෙන් වෙනස් කළ හැකිය:

    public int compare(Object a, Object b) {

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

4

ස්ටීවන්ගේ විසඳුම ඇත්තෙන්ම විශිෂ්ටයි, නමුත් ගුවා භාවිතා කළ නොහැකි අයට:

සිතියමක් අගය අනුව වර්ග කිරීම සඳහා මගේ විසඳුම මෙන්න. මෙම විසඳුම සමාන අගයක් මෙන් දෙගුණයක් ඇති අවස්ථාවන් හසුරුවයි ...

// If you want to sort a map by value, and if there can be twice the same value:

// here is your original map
Map<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 value
Set<Map.Entry<String,Integer>> set = new TreeSet<Map.Entry<String,Integer>>(
        new Comparator<Map.Entry<String,Integer>>(){
            @Override
            public 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 hashmap
Map<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

ක්‍රියාත්මක කිරීම: http://www.ideone.com/dq3Lu

ප්‍රතිදානය:

Set entries: E -> -1
Set entries: B -> 1
Set entries: A -> 3
Set entries: C -> 3
Set entries: D -> 5
Set entries: H -> 15
Set entries: G -> 79
Set entries: F -> 1000
Added to result map entries: E -1
Added to result map entries: B 1
Added to result map entries: A 3
Added to result map entries: C 3
Added to result map entries: D 5
Added to result map entries: H 15
Added to result map entries: G 79
Added to result map entries: F 1000
Result map values: 5
Result map values: -1
Result map values: 1000
Result map values: 79
Result map values: 3
Result map values: 1
Result map values: 3
Result map values: 15
Result map entries: D -> 5
Result map entries: E -> -1
Result map entries: F -> 1000
Result map entries: G -> 79
Result map entries: A -> 3
Result map entries: B -> 1
Result map entries: C -> 3
Result map entries: H -> 15

එය සමහර පුද්ගලයින්ට උපකාරී වනු ඇතැයි සිතමි


3

ඔබට අනුපිටපත් යතුරු සහ කුඩා දත්ත කට්ටලයක් (<1000) සහ ඔබේ කේතය කාර්ය සාධනය තීරණාත්මක නොවේ නම් ඔබට පහත සඳහන් දෑ කළ හැකිය:

Map<String,Integer> tempMap=new HashMap<String,Integer>(inputUnsortedMap);
LinkedHashMap<String,Integer> sortedOutputMap=new LinkedHashMap<String,Integer>();

for(int i=0;i<inputUnsortedMap.size();i++){
    Map.Entry<String,Integer> maxEntry=null;
    Integer maxValue=-1;
    for(Map.Entry<String,Integer> entry:tempMap.entrySet()){
        if(entry.getValue()>maxValue){
            maxValue=entry.getValue();
            maxEntry=entry;
        }
    }
    tempMap.remove(maxEntry.getKey());
    sortedOutputMap.put(maxEntry.getKey(),maxEntry.getValue());
}

inputUnsortedMap යනු කේතයට ආදානයයි .

විචලනය කරන ලද ඕට්පුට්මැප් හි දත්ත නැවත නැවත ක්‍රියාත්මක වන විට අක්‍රීය අනුපිළිවෙලෙහි අඩංගු වේ. අනුපිළිවෙල වෙනස් කිරීමට> if ප්‍රකාශයේ <ලෙස වෙනස් කරන්න.

වේගවත්ම වර්ග කිරීම නොව අතිරේක පරායත්තතාවයකින් තොරව කාර්යය ඉටු කරයි.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.