java 按值排序 LinkedHashMap
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27114691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sorting LinkedHashMap by value
提问by user3922757
How can you sort a LinkedHashMap using the value ?
如何使用值对 LinkedHashMap 进行排序?
Is there a way to insert entries into a LinkedHashMap so that they are inserted in order based on their value ?
有没有办法将条目插入 LinkedHashMap 以便根据它们的值按顺序插入它们?
回答by Radiodef
How can you sort a LinkedHashMap using the value?
如何使用值对 LinkedHashMap 进行排序?
LinkedHashMap
is not sorted, it is orderedby order of insertion.
LinkedHashMap
没有排序,它是有序的通过插入的顺序。
If your goal is to reorderthe Map, you might do something like
如果您的目标是重新排序地图,您可能会执行类似的操作
static <K, V> void orderByValue(
LinkedHashMap<K, V> m, final Comparator<? super V> c) {
List<Map.Entry<K, V>> entries = new ArrayList<>(m.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> lhs, Map.Entry<K, V> rhs) {
return c.compare(lhs.getValue(), rhs.getValue());
}
});
m.clear();
for(Map.Entry<K, V> e : entries) {
m.put(e.getKey(), e.getValue());
}
}
We put all the entries in a List, sort the List, then put the entries back in the Map in the new order.
我们将所有条目放入一个 List 中,对 List 进行排序,然后将条目以新的顺序放回 Map 中。
Here's a Java 8 translation for those inclined:
这是针对那些倾向的 Java 8 翻译:
static <K, V> void orderByValue(
LinkedHashMap<K, V> m, Comparator<? super V> c) {
List<Map.Entry<K, V>> entries = new ArrayList<>(m.entrySet());
m.clear();
entries.stream()
.sorted(Comparator.comparing(Map.Entry::getValue, c))
.forEachOrdered(e -> m.put(e.getKey(), e.getValue()));
}
(Which, out of curiosity, can be condensed to, although it is less efficient):
(出于好奇,可以将其浓缩为,尽管效率较低):
static <K, V> void orderByValue(
LinkedHashMap<K, V> m, Comparator<? super V> c) {
new ArrayList<>(m.keySet()).stream()
.sorted(Comparator.comparing(m::get, c))
.forEachOrdered(k -> m.put(k, m.remove(k)));
}
Is there a way to insert entries into a LinkedHashMap so that they are inserted in order based on their value?
有没有办法将条目插入到 LinkedHashMap 中,以便根据它们的值按顺序插入它们?
No. See above. LinkedHashMap
is not sorted.
不,见上文。LinkedHashMap
没有排序。
If your goal is to keep the Map sorted, you need to use a TreeMap
; however there are problems with doing so. Entries in the Map need to have unique values. See hereand here.
如果您的目标是保持 Map 排序,则需要使用TreeMap
; 但是这样做有问题。Map 中的条目需要具有唯一值。请参阅此处和此处。
回答by ajb
I think the best way to sort a LinkedHashMap
by value is to write a comparator that compares two Map.Entry<K,V>
objects by value, then
我认为LinkedHashMap
按值排序的最佳方法是编写一个比较器,Map.Entry<K,V>
按值比较两个对象,然后
Map.Entry<K,V>[] entries = (Map.Entry<K,V>[])map.entrySet().toArray();
Arrays.sort(entries, comparator);
The comparator would look something like
比较器看起来像
Comparator<Map.Entry<K,V>> comparator = new Comparator<Map.Entry<K,V>>() {
@Override
public int compare(Map.Entry<K,V> o1, Map.Entry<K,V> o2) {
return o1.getValue().compareTo(o2.getValue());
}
};
Basically, it's the obvious thing: create an array of all the key/value pairs in the map, and then sort it. NOTE:I haven't tested this.
基本上,这是显而易见的事情:创建映射中所有键/值对的数组,然后对其进行排序。 注意:我没有测试过这个。
As for the second question: this would require a special data structure that maintains the values in order. When you insert an element, it would set up the hash table andmaintain a doubly-linked list of the elements in insertion order andset up some sort of AVL tree to keep the values in order like TreeSet
. I don't think Java defines a class like this, but maybe there's one in a third-party library. It might be easiest to maintain two separate structures, a LinkedHashMap<K,V>
and a TreeSet<Map.Entry<K,V>>
.
至于第二个问题:这需要一个特殊的数据结构来按顺序维护值。当你插入一个元素时,它会建立一个哈希表,并按照插入顺序维护一个元素的双向链表,并建立某种 AVL 树来保持值的顺序,如TreeSet
. 我不认为 Java 定义了这样的类,但第三方库中可能有一个。维护两个独立的结构 aLinkedHashMap<K,V>
和 a可能是最简单的TreeSet<Map.Entry<K,V>>
。
回答by SeahawksRdaBest
Like the answer before me suggested a LinkedHashMap is not sorted it only holds the insertion order. You have to manually create your comparator.
就像我之前的答案建议 LinkedHashMap 没有排序它只保存插入顺序。您必须手动创建比较器。
now the question is what do you what to sort the Map by ? By an integer key...
现在的问题是你用什么对地图进行排序?通过整数键...
Here is a example: (Tree Map)
这是一个例子:(树图)
Default Compare
默认比较
// Create a hash map
TreeMap tm = new TreeMap();
// Put elements to the map
tm.put("person1", new Double(1));
tm.put("person2", new Double(2));
tm.put("person3", new Double(3));
tm.put("person4", new Double(4));
tm.put("person5", new Double(5));
// Get a set of the entries
Set set = tm.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
// Deposit 1000 into person5's account
double balance = ((Double)tm.get("person5")).doubleValue();
tm.put("person5", new Double(balance + 1000));
System.out.println("person5's new balance: " +
tm.get("person5"));
This tree will sort in the natural order of the keys. i.e. person1 threw person5
这棵树将按键的自然顺序排序。即 person1 扔了 person5
person1: 1.00
person2: 2.00
person3: 3.00
person4: 4.00
person5: 5.00
person5's new balance: 1005.00
Use a custom comparator:
使用自定义比较器:
public class MyTMCompUserDefine {
public static void main(String a[]){
//By using name comparator (String comparison)
TreeMap<Empl,String> tm = new TreeMap<Empl, String>(new MyNameComp());
tm.put(new Empl("Ram",3000), "RAM");
tm.put(new Empl("John",6000), "JOHN");
tm.put(new Empl("Crish",2000), "CRISH");
tm.put(new Empl("Tom",2400), "TOM");
Set<Empl> keys = tm.keySet();
for(Empl key:keys){
System.out.println(key+" ==> "+tm.get(key));
}
System.out.println("===================================");
//By using salary comparator (int comparison)
TreeMap<Empl,String> trmap = new TreeMap<Empl, String>(new MySalaryComp());
trmap.put(new Empl("Ram",3000), "RAM");
trmap.put(new Empl("John",6000), "JOHN");
trmap.put(new Empl("Crish",2000), "CRISH");
trmap.put(new Empl("Tom",2400), "TOM");
Set<Empl> ks = trmap.keySet();
for(Empl key:ks){
System.out.println(key+" ==> "+trmap.get(key));
}
}
}
class MyNameComp implements Comparator<Empl>{
@Override
public int compare(Empl e1, Empl e2) {
return e1.getName().compareTo(e2.getName());
}
}
class MySalaryComp implements Comparator<Empl>{
@Override
public int compare(Empl e1, Empl e2) {
if(e1.getSalary() > e2.getSalary()){
return 1;
} else {
return -1;
}
}
}
class Empl{
private String name;
private int salary;
public Empl(String n, int s){
this.name = n;
this.salary = s;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String toString(){
return "Name: "+this.name+"-- Salary: "+this.salary;
}
}
Output:
Name: Crish-- Salary: 2000 ==> CRISH
Name: John-- Salary: 6000 ==> JOHN
Name: Ram-- Salary: 3000 ==> RAM
Name: Tom-- Salary: 2400 ==> TOM
===================================
Name: Crish-- Salary: 2000 ==> CRISH
Name: Tom-- Salary: 2400 ==> TOM
Name: Ram-- Salary: 3000 ==> RAM
Name: John-- Salary: 6000 ==> JOHN