27

假设我有一个列表(或集合):

List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");

我想取回一个 ImmutableList(Set),它按自然顺序对术语进行排序/分组,其中以“src”开头的术语是第一个,“assoc”第二个,“dest”最后。如果一个术语不包含那些,那么它应该从结果列表中删除。

因此这里的结果是“srcB”、“srcT”、“assocX”、“destA”。

我想我可以通过 Iterables.filter 或 Predicates 的某种组合来做到这一点,但只是看不到它。我认为必须有一种简洁的方法。

编辑:代替列表的集合也可以。

4

4 回答 4

33

只要这三个前缀是您唯一关心的事情,我建议您这样做:

    Predicate<String> filter = new Predicate<String>() {
        @Override
        public boolean apply(String input) {
            return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest");
        }
    };

    Function<String, Integer> assignWeights = new Function<String, Integer>() {
        @Override
        public Integer apply(String from) {
            if (from.startsWith("src")) {
                return 0;
            } else if (from.startsWith("assoc")) {
                return 1;
            } else if (from.startsWith("dest")) {
                return 2;
            } else {
                /* Shouldn't be possible but have to do something */
                throw new IllegalArgrumentException(from + " is not a valid argument");
            }
        }
    };

    ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
            Ordering.natural().onResultOf(assignWeights).sortedCopy(
                    Iterables.filter(testList, filter)
            )
    );

如果您开始添加更多前缀来过滤或排序,此解决方案肯定不会很好地扩展,因为您必须不断更新过滤器和每个前缀的权重。

于 2010-02-22T18:13:09.900 回答
12

看看这个谷歌收藏示例

Function<Fruit, String> getNameFunction = new Function<Fruit, String>() {
    public String apply(Fruit from) {
        return from.getName();
    }
};

Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction);

ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
    nameOrdering).addAll(fruits).build();

诚然,这会返回一个 Set。

于 2010-02-22T17:57:29.980 回答
0

我认为你必须首先使用谓词来消除你不想要的元素,然后实现一个比较器并对你的列表进行排序。

于 2010-02-22T17:55:09.860 回答
0

通常,像这样整理清楚不同的数据是不好的设计。在您的情况下,当您说“assocX”时,“assoc”与“X”具有不同的含义,但您将它们合并在一起。

所以我建议设计一个有两个字段的类。然后您可以在第一个字段上创建一个排序,在第二个字段上创建另一个,然后将它们组合起来(例如 Ordering#compound())。使用将这些字段合并为字符串的 toString() 方法。作为奖励,这可以通过共享大大减少内存使用量。

因此,您将对此类对象的列表进行排序,如果您想打印它们,只需对它们调用 toString() 即可。

于 2010-03-17T13:35:34.717 回答