0

I'm writing a Java program in which I want to sort a set of items and get the N-highest elements of the set. The thing is, though, that I want the elements to be returned grouped by their rank -- so if I want the 3 highest elements, but there is a tie between two elements for third place, then the third result is a collection that contains the two tied elements.

I know I could write this myself, but I'm wondering if it's already been implemented somewhere else. Does anybody know of anything like this?

Masterofpsi
  • 769
  • 6
  • 17

2 Answers2

0

Sounds like the Google Collection's MultiMap might be what you're after.

Use the "rank" as your key when inserting your elements. Then sort the keys.

Jim
  • 1,040
  • 1
  • 10
  • 16
  • That won't work, because the "rank" of each object is unknown before the sorting is done. It's determined by the sorting, not the other way around. – Masterofpsi May 23 '11 at 01:17
  • Ah I see. Nothing I know of then. I'd do a custom implementation that sticks them in a list, sorts them, then walks though creating the required data structure - perhaps using the MultiMap. – Jim May 23 '11 at 20:55
0

This is what I ended up going with:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.common.collect.Ordering;

public final class Sorting {
    private Sorting() {}

    public static <T extends Comparable<? super T>> List<List<T>> rank(
            Iterable<T> iterable, int nRanks) {
        if (nRanks < 0) {
            throw new IllegalArgumentException(Integer.toString(nRanks));
        }
        if (nRanks == 0) {
            return new ArrayList<List<T>>();
        }

        Iterator<T> iter = Ordering.natural().sortedCopy(iterable).iterator();
        List<List<T>> ret = new ArrayList<List<T>>();
        if (iter.hasNext()) {
            T prev = iter.next();
            List<T> group = new ArrayList<T>();
            group.add(prev);
            ret.add(group);

            int rank = 1;
            while (iter.hasNext()) {
                T next = iter.next();
                if (prev.compareTo(next) > 0) {
                    rank++;
                    if (rank > nRanks) {
                        break;
                    }

                    group = new ArrayList<T>();
                    ret.add(group);
                }
                group.add(next);
                prev = next;
            }
        }

        return ret;
    }
}
Masterofpsi
  • 769
  • 6
  • 17