Ahmad AlKhazraji
Ahmad AlKhazraji

Reputation: 1

How to sort Hashmultimap based on value?

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]}

Upvotes: 0

Views: 820

Answers (1)

Jeff
Jeff

Reputation: 3892

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());
    }
}

Upvotes: 1

Related Questions