Sorting LinkedHashMap by value

How can you sort the LinkedHashMap by value?

Is there a way to insert records into a LinkedHashMap so that they are inserted in order based on their value?

+3


source to share


3 answers


How can you sort the LinkedHashMap by value?

LinkedHashMap

not sorted, sorted by insertion order.

If your goal is to change the order of the Map, you can 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 records in a list, sort the list, and then put the records back into the Map in a new order.

Here's the Java 8 translation for oblique:



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, albeit 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 records into a LinkedHashMap so that they are inserted in order based on their value?

Not. See above. LinkedHashMap

not sorted.

If your goal is to keep the map sorted, you need to use TreeMap

; however, there are problems with this. The entries on the map must have unique values. See here and here .

+12


source


I think the best way to sort a value LinkedHashMap

by value is to write a comparator that compares two objects Map.Entry<K,V>

by value, then

Map.Entry<K,V>[] entries = (Map.Entry<K,V>[])map.entrySet().toArray();
Arrays.sort(entries, comparator);

      

The comparator would look 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 an obvious thing to do: create an array of all key / value pairs in the map, and then sort it. NOTE: I have not tested this.

Regarding the second question: it will require a special data structure that keeps the values ​​in order. When you insert an item, it sets up a hash table and maintains a doubly linked list of items in insert order, and sets up some kind of AVL tree to keep the values ​​in order like TreeSet

. I don't think Java defines a class like this, but maybe there is one in a third party library. The easiest way would be to maintain two separate structures: LinkedHashMap<K,V>

and TreeSet<Map.Entry<K,V>>

.

+1


source


Like the previous answer, the LinkedHashMap link is not sorted, it only contains the insertion order. You have to manually create your comparator.

Now the question is, what do you need to sort the map? Using an integer key ...

Here's an example: (Treemap)

Default comparison

           // 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 account
          double balance = ((Double)tm.get("person5")).doubleValue();
          tm.put("person5", new Double(balance + 1000));
          System.out.println("person5 new balance: " +
          tm.get("person5"));

      

This tree will be sorted in the natural order of the keys. that is, man1 abandoned man5

    person1: 1.00
    person2: 2.00
    person3: 3.00
    person4: 4.00
    person5: 5.00
    person5 new balance: 1005.00

      

Use your own 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

      

+1


source







All Articles