0

I am using HashMultiMap in my code. My HashMultiMap structure is like,

HashMultimap<String, Integer> map = HashMultimap.create();

map.put("a", 3);
map.put("m", 5);
map.put("l", 1);

System.out.println(map);

actual output:{a=[3], l=[1], m=[5]}

now, i want to sort it based on value:

target output:{m=[5], a=[3], l=[1]}

  • can you do like `map.getValues()`? – bumbumpaw Jul 15 '14 at 00:05
  • yes, i can use this function: public Set get(K k) – Ahmad AlKhazraji Jul 15 '14 at 01:02
  • @AhmadAlKhazraji Why are you using the `HashMultimap`class since a simple `HashMap`can do the job ? – Zakaria Jul 15 '14 at 01:10
  • @Zakaria becasue keys in my case can be repeated.. – Ahmad AlKhazraji Jul 15 '14 at 01:19
  • [similar issue](http://stackoverflow.com/a/17200728/3835388) – Ahmad AlKhazraji Jul 15 '14 at 02:33
  • I'm not sure this makes sense: what if you have {m = [5, 2], a = [3], l = [1]}? Do you want to sort the entries by...what, the highest value they have? Before you work out _how_ to do what you want, you should make sure you fully understand what it is you want... – Louis Wasserman Jul 15 '14 at 02:34
  • @LouisWasserman thank you for your advise.. i think solution is swapping the role of the keys and the values.. – Ahmad AlKhazraji Jul 15 '14 at 02:38
  • @LouisWasserman my problem is: the key is username, the value is user's score. i want to return top n users with highest scores. but in a map, we should sort by key not by value, so the key should be score, the value should be user name, the data structure should be sorted multi-value map: there can be multiple values for a same key, and it's sorted by key. – Ahmad AlKhazraji Jul 15 '14 at 02:49
  • Since you're now twisting keys and values, I suggest you take a look at [this earlier similar question](http://stackoverflow.com/questions/5501468/having-a-multimap-sorted-on-keys-only-in-java). – Olivier Grégoire Jul 15 '14 at 08:35

1 Answers1

1

If you actually do want to sort on values the solution would be to extend ForwardingSortedSetMultimap and delegate to TreeMultimap.

The example below expects the Keys and Values to implement Comparable but the class can easily be modified to support supplied Key and Value Comparators.

public class SortedValueTreeMultimap<K extends Comparable<K>, V extends Comparable<V>> extends
        ForwardingSortedSetMultimap<K, V> {

    private final Ordering<Map.Entry<K, Collection<V>>> mapEntryOrdering = new Ordering<Map.Entry<K, Collection<V>>>() {

        @Override
        public int compare(final Entry<K, Collection<V>> left, final Entry<K, Collection<V>> right) {

            // Safe as we cannot have nulls or empties
            return ComparisonChain.start()
                .compare(left.getValue()
                    .iterator()
                    .next(), right.getValue()
                    .iterator()
                    .next())
                .compare(left.getKey(), right.getKey())
                .result();

        }
    };

    public final Ordering<Entry<K, V>> entryOrdering = new Ordering<Map.Entry<K, V>>() {

        @Override
        public int compare(final Entry<K, V> left, final Entry<K, V> right) {

            return ComparisonChain.start()
                    .compare(left.getValue(), right.getValue())
                    .compare(left.getKey(), right.getKey())
                    .result();
        }

    };

    public final Comparator<Entry<K, V>> entryOrderingReverse = Collections.reverseOrder(this.entryOrdering);

    private final SortedSetMultimap<K, V> delegate = TreeMultimap.create();

    @Override
    protected SortedSetMultimap<K, V> delegate() {

        return this.delegate;
    }

    @Override
    public Set<Entry<K, V>> entries() {
        return FluentIterable.from(super.entries())
            .toSortedSet(this.entryOrdering);

    }

    public Set<Entry<K, V>> reverseEntries() {
        return FluentIterable.from(super.entries())
                .toSortedSet(this.entryOrderingReverse);
    }

    @Override
    public String toString() {
        return FluentIterable.from(this.asMap()
            .entrySet())
            .toSortedSet(this.mapEntryOrdering)
            .toString();

    }

    public static void main(final String... args) {

        final SortedValueTreeMultimap<String, Integer> sortedMap = new SortedValueTreeMultimap<String, Integer>();

        sortedMap.put("a", 7);
        sortedMap.put("a", 3);
        sortedMap.put("a", 7);
        sortedMap.put("m", 5);
        sortedMap.put("m", 4);
        sortedMap.put("m", 4);
        sortedMap.put("k", 1);
        sortedMap.put("j", 1);

        // [j=[1], k=[1], m=[4, 5], a=[7]]
        System.out.println(sortedMap);

        // [j=1, k=1, a=3, m=4, m=5, a=7]
        System.out.println(sortedMap.entries());

        // [a=7, m=5, m=4, a=3, k=1, j=1]
        System.out.println(sortedMap.reverseEntries());
    }
}
Jeff
  • 3,712
  • 2
  • 22
  • 24