class RankSorter {

    public static <T> List<T> sort(Collection<T> items, int[] itemRanks) {
        Guard.argumentNotNull(items, "items");
        Guard.argumentNotNull(itemRanks, "itemRanks");

        int lastObserverdRank = 0;
        boolean needToSort = false;

        for (int currentRank : itemRanks) {
            // We're expecting ranks to go up (e.g. 1, 2, 2, 3, ...)
            // If it goes down, then we've got to sort it.
            if (currentRank < lastObserverdRank) {
                needToSort = true;
                break;
            }

            lastObserverdRank = currentRank;
        }

        // Don't bother doing more work, it's already in a good order
        if (!needToSort) return new ArrayList<T>(items);

        // Get the existing items as an indexable list.
        List<T> itemsInList = new ArrayList<T>(items);

        // item -> rank
        final Map<T, Integer> itemToRank = new HashMap<T, Integer>();
        for (int i = 0; i < itemsInList.size(); i++)
            itemToRank.put(itemsInList.get(i), itemRanks[i]);

        Collections.sort(itemsInList, new Comparator<T>() {
            public int compare(T o1, T o2) {
                return itemToRank.get(o1).compareTo(itemToRank.get(o2));
            }
        });

        Arrays.sort(itemRanks);
        return itemsInList;
    }

}