简体   繁体   中英

sorting a 2d data structure in java

I need to sort a 2d key/value pair by the value. I have read many references about this on the web and have ended up writing my own class to do this using HashMaps(see below). I put the code into a condensed working class that reproduces the problem with the minimum amount of code so that you can just cut and paste it into your IDE for quick diagnostics.

As you can see, the method that I wrote is correctly sorting the values before they are entered into sortedMap. However, for some reason, they values are then again unordered in a different way when I try to subsequently iterate through sortedMap.

Can anyone show me how to fix the code below so that I iterate through a resulting 2D data object that gives me my data in descending order?


EDIT: Re-wrote using TreeMaps, and am still getting a similar problem. Here is the re-written code:

import java.util.*;

public class HashMapDemo {
    public static void main(String args[]) {

        // Code that creates and populates the unordered HashMap:
        TreeMap<Integer, Double> unSortedMap = new TreeMap<Integer, Double>();
        unSortedMap.put(1343, 0.521851);
        unSortedMap.put(1950, -0.301208);
        unSortedMap.put(3667, -0.0280762);
        unSortedMap.put(3879, 0.154724);
        unSortedMap.put(4124, 0.022583);

        // Code that calls the ordering method:
        TreeMap<Integer, Double> sortedMap = new TreeMap<Integer, Double>(
                sortTreeMap(unSortedMap));

        // Code that iterates through the "sorted" hashmap.
        System.out.println("now iterate through sortedMap: ");
        for (Integer key : sortedMap.keySet()) {
            System.out.println("key, sortedMap.get(key) are:  " + key + ", "
                    + sortedMap.get(key));
        }
    }

    // Code for the ordering method. Note that the println tests indicate that
    // this method is correctly sorting the key/value pairs in the hashmap:
    private static TreeMap<Integer, Double> sortTreeMap(
            TreeMap<Integer, Double> input) {

        System.out
                .println("input.size() upon entering sortHasMap() function is: "
                        + input.size());
        int startSize = input.size();

        // create a hashmap to store sorted output
        TreeMap<Integer, Double> sortedMap = new TreeMap<Integer, Double>();

        // repeat the following process once for every key/value pair in the
        // hashmap
        for (int i = 0; i < startSize; i++) {
            int mySize = input.size();
            System.out.println("mySize is: " + mySize);
            double maxVal = Double.NEGATIVE_INFINITY;
            int maxKey = 0;

            // iterate through each key in hashmap to find key/value of max
            // value
            for (Integer key : input.keySet()) {
                if (maxVal < input.get(key)) {
                    maxVal = input.get(key);
                    maxKey = key;
                }
            }

            // add key/value of max of that iteration to sorted map and remove
            // from input before next iteration
            sortedMap.put(maxKey, maxVal);

            input.remove(maxKey);

            System.out.println("sortedMap.put(maxKey, maxVal) are: " + maxKey
                    + ", " + maxVal);
        }
        return sortedMap;
    }
}

You need only two lines to achieve what you want. Here are those two lines:

    Map<Integer, Double> sortedMap = new TreeMap<Integer, Double>(new Comparator<Integer>() {
        public int compare(Integer o1, Integer o2) {
            return map.get(o2).compareTo(map.get(o1)); // reverse order of values
        }
    });
    sortedMap.putAll(map);

Here's the complete runnable code:

public static void main(String[] args) {
    final Map<Integer, Double> map = new HashMap<Integer, Double>();
    map.put(1343, 0.521851);
    map.put(1950, -0.301208);
    map.put(3667, -0.0280762);
    map.put(3879, 0.154724);
    map.put(4124, 0.022583);
    Map<Integer, Double> sortedMap = sortMap(map);

    for (Map.Entry<Integer, Double> entry : sortedMap.entrySet()) {
        System.out.println(entry.getKey() + ", " + entry.getValue());
    }
}

public static Map<Integer, Double> sortMap(final Map<Integer, Double> map) {
    Map<Integer, Double> sortedMap = new TreeMap<Integer, Double>(new Comparator<Integer>() {
        public int compare(Integer o1, Integer o2) {
            return map.get(o2).compareTo(map.get(o1));
        }
    });
    sortedMap.putAll(map);
    return sortedMap;
}

Output:

1343, 0.521851
3879, 0.154724
4124, 0.022583
3667, -0.0280762
1950, -0.301208

Notes: You specify how you want entries ordered in a TreeSet by passing the Comparator you want to use into the constructor. The TreeSet implementation does the rest.

Other notes:

  • The best way to iterate over the keys/values of a map is by iterating over Map.entrySet()
  • Always use the abstract type for your variables - eg Map<?, ?> myMap not the concrete implementation (ie HashMap<?, ?> myMap )

Here's the generic version of the sortMap method that will sort any suitable map based on the reverse order of the values:

public static <K, V extends Comparable<V>> Map<K, V> sortMap2(final Map<K, V> map) {
    Map<K, V> sortedMap = new TreeMap<K, V>(new Comparator<K>() {
        public int compare(K o1, K o2) {
            return map.get(o2).compareTo(map.get(o1));
        }
    });
    sortedMap.putAll(map);
    return sortedMap;
}

Use a TreeMap . Its a SortedMap that uses the natural ordering of keys. In your case, it will order by the Integer key.

It does the sorting for you.

java.util.HashMap is unordered.

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

EDIT After reading the question correctly

Use a Comparator for the TreeMap constructor that compares the values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM