如何使用值?
对LinkedHashMap进行排序有没有办法将条目插入LinkedHashMap,以便根据它们的值按顺序插入?
答案 0 :(得分:13)
如何使用值?
对LinkedHashMap进行排序
LinkedHashMap
未按排序,按插入顺序排序。
如果您的目标是重新排序地图,您可能会执行类似
的操作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());
}
}
我们将所有条目放入List中,对List进行排序,然后以新顺序将条目放回Map中。
这里是倾向于那些人的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()));
}
(出于好奇,可以将其浓缩,尽管效率较低):
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)));
}
有没有办法将条目插入LinkedHashMap,以便根据它们的值按顺序插入?
没有。往上看。 LinkedHashMap
未排序。
如果您的目标是保持地图排序,则需要使用TreeMap
;但这样做有问题。地图中的条目需要具有唯一值。请参阅here和here。
答案 1 :(得分:2)
我认为按值排序LinkedHashMap
的最佳方法是编写一个比较器,按值比较两个Map.Entry<K,V>
个对象,然后
Map.Entry<K,V>[] entries = (Map.Entry<K,V>[])map.entrySet().toArray();
Arrays.sort(entries, comparator);
比较器看起来像
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());
}
};
基本上,显而易见的事情是:在地图中创建一个包含所有键/值对的数组,然后对其进行排序。 注意:我没有测试过这个。
关于第二个问题:这需要一个特殊的数据结构来维持值的顺序。当你插入一个元素时,它会设置哈希表和维护一个双重链接的元素列表,按照插入顺序和设置某种AVL树来保持像TreeSet
那样的值。我不认为Java定义了这样的类,但也许在第三方库中有一个。维护两个单独的结构可能是最简单的,LinkedHashMap<K,V>
和TreeSet<Map.Entry<K,V>>
。
答案 2 :(得分:1)
就像我之前的答案所建议的那样,LinkedHashMap没有排序,它只保存插入顺序。您必须手动创建比较器。
现在问题是你如何对Map进行排序?用整数键......
这是一个例子:(树图)
// 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"));
此树将按键的自然顺序排序。即person1扔人5
person1: 1.00
person2: 2.00
person3: 3.00
person4: 4.00
person5: 5.00
person5's new balance: 1005.00
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