Tiga jawaban 1 baris ...
Saya akan menggunakan Google Collections Guava untuk melakukan ini - jika nilai Comparable
Anda maka Anda dapat menggunakannya
valueComparator = Ordering.natural().onResultOf(Functions.forMap(map))
Yang akan membuat fungsi (objek) untuk peta [yang mengambil salah satu kunci sebagai input, mengembalikan nilai masing-masing], dan kemudian menerapkan urutan alami (sebanding) dengan mereka [nilai-nilai].
Jika mereka tidak sebanding, maka Anda harus melakukan sesuatu di sepanjang garis
valueComparator = Ordering.from(comparator).onResultOf(Functions.forMap(map))
Ini dapat diterapkan ke TreeMap (sebagai Ordering
ekstensi Comparator
), atau LinkedHashMap setelah pengurutan
NB : Jika Anda akan menggunakan TreeMap, ingatlah bahwa jika perbandingan == 0, maka item tersebut sudah ada dalam daftar (yang akan terjadi jika Anda memiliki beberapa nilai yang membandingkan yang sama). Untuk meringankan ini, Anda dapat menambahkan kunci Anda ke komparator seperti itu (dengan anggapan bahwa kunci dan nilai Anda Comparable
):
valueComparator = Ordering.natural().onResultOf(Functions.forMap(map)).compound(Ordering.natural())
= Terapkan pemesanan alami untuk nilai yang dipetakan oleh kunci, dan gabungkan bahwa dengan pemesanan alami kunci
Perhatikan bahwa ini masih tidak berfungsi jika kunci Anda dibandingkan dengan 0, tetapi ini harus cukup untuk sebagian besar comparable
item (seperti hashCode
, equals
dancompareTo
sering disinkronkan ...)
Lihat Memesan.onResultOf () dan Functions.forMap () .
Penerapan
Jadi sekarang kita memiliki pembanding yang melakukan apa yang kita inginkan, kita perlu mendapatkan hasil darinya.
map = ImmutableSortedMap.copyOf(myOriginalMap, valueComparator);
Sekarang ini kemungkinan besar akan berhasil, tetapi:
- perlu dilakukan mengingat peta selesai yang lengkap
- Jangan coba pembanding di atas pada
TreeMap
; tidak ada gunanya mencoba membandingkan kunci yang dimasukkan ketika tidak memiliki nilai sampai setelah put, yaitu, itu akan pecah sangat cepat
Poin 1 adalah sedikit pemecah kesepakatan bagi saya; koleksi google sangat malas (yang bagus: Anda dapat melakukan hampir semua operasi dalam sekejap; pekerjaan nyata dilakukan ketika Anda mulai menggunakan hasilnya), dan ini membutuhkan penyalinan secara keseluruhan peta!
Jawaban "Lengkap" / Peta yang disortir langsung berdasarkan nilai
Jangan khawatir; jika Anda cukup terobsesi untuk memiliki peta "langsung" yang diurutkan dengan cara ini, Anda tidak dapat menyelesaikan tidak satu tetapi keduanya (!) dari masalah di atas dengan sesuatu yang gila seperti berikut:
Catatan: Ini telah berubah secara signifikan pada Juni 2012 - kode sebelumnya tidak pernah bisa berfungsi: HashMap internal diperlukan untuk mencari nilai-nilai tanpa membuat loop tak terbatas antara TreeMap.get()
-> compare()
dan 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"));
}
}
Ketika kami meletakkan, kami memastikan bahwa peta hash memiliki nilai untuk komparator, dan kemudian dimasukkan ke TreeSet untuk disortir. Tapi sebelum itu kita periksa peta hash untuk melihat bahwa kuncinya sebenarnya bukan duplikat. Selain itu, pembanding yang kami buat juga akan menyertakan kunci sehingga nilai duplikat tidak menghapus kunci non-duplikat (karena perbandingan ==). 2 item ini sangat penting untuk memastikan kontrak peta disimpan; jika Anda pikir Anda tidak menginginkan itu, maka Anda hampir pada titik membalikkan peta sepenuhnya (ke Map<V,K>
).
Konstruktor perlu disebut sebagai
new ValueComparableMap(Ordering.natural());
//or
new ValueComparableMap(Ordering.from(comparator));
List<Map.Entry<...>> list =new LinkedList(map.entrySet())
dan sepertiCollections.sort ....
itu.