Üç adet 1 satırlık cevap ...
Bunu yapmak için Google Koleksiyonlar Guava'yı kullanırdım - değerleriniz varsa Comparable
kullanabilirsiniz
valueComparator = Ordering.natural().onResultOf(Functions.forMap(map))
Bu da harita için [anahtarlardan herhangi birini girdi olarak alan, ilgili değeri döndüren] bir işlev (nesne) oluşturacak ve sonra onlara [değerler] doğal (karşılaştırılabilir) sıralaması uygulayacaktır.
Eğer karşılaştırılamazlarsa, o zaman
valueComparator = Ordering.from(comparator).onResultOf(Functions.forMap(map))
Bunlar, bir TreeMap (şekilde tatbik edilebilir Ordering
uzanır Comparator
) veya bir ayırma sonrası LinkedHashMap
Not : Bir TreeMap kullanacaksanız, bir karşılaştırma == 0 ise, öğenin zaten listede olduğunu (aynı olan birden fazla değeriniz varsa olur) unutmayın. Bunu hafifletmek için anahtarınızı karşılaştırıcıya şu şekilde ekleyebilirsiniz (anahtarlarınızın ve değerlerinizin olduğu varsayılarak Comparable
):
valueComparator = Ordering.natural().onResultOf(Functions.forMap(map)).compound(Ordering.natural())
= Anahtarla eşlenen değere doğal sıralama uygulayın ve anahtarın doğal sırasına göre birleştirin
Bu hala tuşları 0'a karşılaştırmak, ancak bu çoğu için yeterli olmalıdır eğer çalışmaz Not comparable
öğeleri (aynı hashCode
, equals
ve compareTo
senkronize genellikle ...)
Bkz. Ordering.onResultOf () ve Functions.forMap () .
uygulama
Şimdi istediğimizi yapan bir karşılaştırıcıya sahip olduğumuza göre, bundan bir sonuç almamız gerekiyor.
map = ImmutableSortedMap.copyOf(myOriginalMap, valueComparator);
Şimdi bu muhtemelen işe yarayacak, ancak:
- tamamlanmış bir harita verildiğinde yapılması gerekenler
- Yukarıdaki karşılaştırıcılar bir üzerinde denemeyin
TreeMap
; yerleştirilen bir anahtarı koymadan sonra değere sahip olmadığında karşılaştırmaya çalışmanın bir anlamı yoktur, yani, gerçekten hızlı kırılır
Nokta 1 benim için bir anlaşma kırıcı; google koleksiyonları inanılmaz derecede tembeldir (bu iyidir: hemen hemen her işlemi yapabilirsiniz; gerçek çalışma sonucu kullanmaya başladığınızda yapılır) ve bu tüm haritayı kopyalamayı gerektirir !
"Tam" cevap / Değerlere göre canlı sıralanmış harita
Endişelenmeyin; bu şekilde sıralanmış bir "canlı" haritaya sahip olmak konusunda yeterince takıntılı olsaydınız, yukarıdaki sorunlardan birini değil, her ikisini de (!) aşağıdaki gibi çılgın bir şeyle çözebilirsiniz:
Not: Bu, Haziran 2012'de önemli ölçüde değişti - önceki kod asla işe yaramadı: TreeMap.get()
-> compare()
ve compare()
-> arasında sonsuz bir döngü oluşturmadan değerleri aramak için dahili bir HashMap gerekirget()
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"));
}
}
Koyduğumuzda, karma haritasının karşılaştırıcı için değere sahip olduğundan emin oluruz ve sonra sıralama için TreeSet'e koyarız. Ancak bundan önce, anahtarın aslında bir kopya olmadığını görmek için karma haritayı kontrol ediyoruz. Ayrıca, oluşturduğumuz karşılaştırıcı anahtar da içerecek, böylece yinelenen değerler yinelenmeyen anahtarları silmeyecektir (== karşılaştırma nedeniyle). Bu 2 madde , harita sözleşmesinin yapılmasını sağlamak için hayati öneme sahiptir ; bunu istemediğinizi düşünüyorsanız, haritayı neredeyse tamamen tersine çevirme noktasındasınız demektir Map<V,K>
.
Yapıcı olarak adlandırılmalıdır
new ValueComparableMap(Ordering.natural());
//or
new ValueComparableMap(Ordering.from(comparator));
List<Map.Entry<...>> list =new LinkedList(map.entrySet())
veCollections.sort ....
bunun bu şekilde.