使用谷歌集合过滤和排序列表

发布于 2024-08-22 03:07:14 字数 438 浏览 5 评论 0原文

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

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 的某种组合来做到这一点,但只是没有看到它。我认为必须有一种简洁的方法来做到这一点。

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

Suppose I have a list (or Set):

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

I would like to get back an ImmutableList(Set) that sorts/groups terms in natural order where terms that begin with "src" are first, "assoc" second and "dest" last. If a term does not contain those then it should be removed from the resulting list.

Therefore the result here is "srcB", "srcT", "assocX", "destA".

I think I can do this with some combination of Iterables.filter or Predicates but just not seeing it. There must be a succinct way of doing it I think.

EDIT: A set in place of a list works as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

迷离° 2024-08-29 03:07:14

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

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

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

As long as those three prefixes are the only things you care about, I'd suggest something like this:

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

This solution definitely wouldn't scale out incredibly well if you start adding more prefixes to filter out or sort by, since you'd have to continually update both the filter and the weight of each prefix.

花伊自在美 2024-08-29 03:07:14

请查看此 Google 收藏集示例

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。

Have a look at This Google Collections example.

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

Though this, admittedly, returns a Set.

鼻尖触碰 2024-08-29 03:07:14

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

I think you'll have first to use the predicate to eliminate elements you don't want, and the implement a Comparator and sort your list.

你在我安 2024-08-29 03:07:14

通常,像这样整理不同的数据是糟糕的设计。就您而言,当您说“assocX”时,“assoc”与“X”具有不同的含义,但您将它们合并在一起。

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

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

Usually it's bad design to collate clearly distinct data like this. In your case, when you say "assocX", "assoc" has a separate meaning from "X", yet you merge them together.

So I would suggest designing a class with two fields. Then you can create an ordering on the first field, another on the second, and combine them (e.g. Ordering#compound()). With a toString() method that does merge these fields into a string. As a bonus, this may greatly reduce memory usage via sharing.

So you would be sorting a list of such objects, and if you wanted to print them, you would just call toString() on them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文