番石榴:如何从列表和单个元素创建显式排序?

2022-09-04 03:02:11

在番石榴中,给定一个我知道在集合中的类型元素,我想创建一个自定义 Ordering<E>,首先排序,然后排序集合的其余部分。然而,到达那里的方法似乎非常复杂:Collection<E>eEe

Collection<String> values = ImmutableList.of("apples", "oranges", "pears");
String first = "oranges";

List<String> remainingValues = newArrayList(values);  // this
remainingValues.remove(first);                        // seems
Ordering<String> myOrdering =                         // very
    Ordering.explicit(first, remainingValues.toArray( // complicated!
        new String[remainingValues.size()]));         // is there an easier way?

我所希望的是这样的东西:

Ordering.explicit(first);

(我希望这能排序到开头,并保留所有其他元素的顺序,但文档说,生成的排序将抛出一个未明确列出的元素。firstClassCastException

或者像这样:

Ordering.explicit(first, values.toArray(/* etc */));

(但这会失败,因为会是重复值)first

任何人都可以想出一个简洁的方式来做我想做的事情吗?

顺便说一句,它不必是 一个 ,它也可能是在指定顺序中创建一个的解决方法,但同样,这非常复杂:OrderingIterable

Iterable<String> sorted = Iterables.concat(
                             ImmutableList.of(first),
                             Iterables.filter(values, not(equalTo(first))));

答案 1

好吧,这是一种方法,但您可能不会发现它更好。

final String special = "oranges";
Collections.sort(
    list,
    new Comparator<String>() {
      public int compare(String left, String right) {
        return ComparisonChain.start()
            .compareTrueFirst(left.equals(special), right.equals(special))
            .compare(left, right)
            .result();
      }
    });

比较链文档

相关的番石榴功能请求 - 请添加任何详细信息。


答案 2

如果您有更多的特殊值,这将更方便,重复更少:

class PriorityComparator<T> implements Comparator<T> {
    private final List<T> values;

    public PriorityComparator(T... values) {
        this.values = Arrays.asList(values);
    }

    @Override public int compare(T o1, T o2) {
        int idx1 = values.indexOf(o1);
        int idx2 = values.indexOf(o2);
        if (idx1 > -1) {
            return idx2 > -1 ? idx1 - idx2 : -1;
        }
        return idx2 > -1 ? 1 : 0;
    }
}

您可以在比较链中使用它,例如

return ComparisonChain.start()
    .compare(left, right, new PriorityComparator<>("oranges", "apples"))
    .compare(left, right)
    .result();

它将按照 中指定的元素进行排序,其他元素被报告为相等。PriorityComparator

也很容易要求具有可比性并将其用作默认值:T

class PriorityComparator2<T extends Comparable<T>> implements Comparator<T> {
    private final List<T> values;

    public PriorityComparator2(T... values) {
        this.values = Arrays.asList(values);
    }

    @Override public int compare(T o1, T o2) {
        int idx1 = values.indexOf(o1);
        int idx2 = values.indexOf(o2);
        if (idx1 > -1) {
            return idx2 > -1 ? idx1 - idx2 : -1;
        }
        return idx2 > -1 ? 1 : o1.compareTo(o2);
    }
}

推荐