0

Is there a data structure such that I can input all the objects to it and then it will return the objects according to the number of occurrence (e.g. in descending order). All I can think of is using a hash map. The key of the hash map is the object and the value is the occurrence of the object. Every time I input an object, I increment the value of the corresponding key. However, in this way, if I want to output the objects according to the descending order of the occurrence, I need to traverse the hash map once. Is there a more efficient way to implement this in Java?

ZigZagZebra
  • 1,349
  • 3
  • 14
  • 25
  • Another nice solution can be found [here](http://www.programcreek.com/2013/03/java-sort-map-by-value/) – Nir Alfasi Mar 24 '17 at 01:18
  • 1
    Here's another option using Guava: http://stackoverflow.com/questions/4345633/simplest-way-to-iterate-through-a-multiset-in-the-order-of-element-frequency – shmosel Mar 24 '17 at 01:19

1 Answers1

0

SortedMap may be your best bet. You can write your own comparator to keep it sorted the way you'd like.

Edit: since there seems to be confusion, here's an example that orders by descending value as requested.

import java.util.*;
public class TestSortedMap {

    private static class CountComparator implements Comparator<String> {

        Map<String, Integer> map;
        public CountComparator(Map<String, Integer> map) {
            this.map = map;
        }

        public int compare(String a, String b) {
            if (map.get(a) < map.get(b)) return 1;
            else if (map.get(a) > map.get(b)) return -1;
            return 0;
        }
    }

    public static void main(String[] args) {

        Map<String, Integer> testInput = new HashMap<>();
        testInput.put("Hello", 10);
        testInput.put("World", 0);
        testInput.put("Let's", 40);
        testInput.put("Party", 30);
        System.out.println("Unordered:");
        for (String key: testInput.keySet()) {
            System.out.println("Key: " + key + " | Value: " + testInput.get(key));
        }

        CountComparator countComparator = new CountComparator(testInput);
        SortedMap<String, Integer> sortedMap = new TreeMap<>(countComparator);
        sortedMap.putAll(testInput);

        System.out.println("Ordered:");
        for (String key: sortedMap.keySet()) {
            System.out.println("Key: " + key + " | Value: " + sortedMap.get(key));
        }
    }
}

Result set:

Unordered:
Key: Party | Value: 30
Key: Hello | Value: 10
Key: Let's | Value: 40
Key: World | Value: 0
Ordered:
Key: Let's | Value: 40
Key: Party | Value: 30
Key: Hello | Value: 10
Key: World | Value: 0
Paul Back
  • 1,269
  • 16
  • 23
  • 1
    Nope, I've made the same mistake: SortedMap and TreeMap are sorted by keys, the OP is looking for a data-structure that sorts by values – Nir Alfasi Mar 24 '17 at 01:12
  • From the documentation: The map is ordered according to the natural ordering of its keys, or by a Comparator typically provided at sorted map creation time. – Paul Back Mar 24 '17 at 01:13
  • Indeed, that's what I wrote... – Nir Alfasi Mar 24 '17 at 01:14
  • Can you please clarify? You were correct initially, what would stop you from writing a Comparator that sorted by values for SortedMap or TreeMap? – Paul Back Mar 24 '17 at 01:18
  • The comparator will be activated on the keys not on the values. – Nir Alfasi Mar 24 '17 at 01:19
  • Sorry to beat on what is (correctly) marked as a duplicate question, but the behavior of the Comparator is dictated by whatever is in your compare method, and OP can obtain his/her desired functionality simply by writing a quick comparator. I've updated my answer showing this. – Paul Back Mar 25 '17 at 19:46