【问题标题】:filter and sort list using google collections使用谷歌收藏过滤和排序列表
【发布时间】:2011-01-19 17:58:58
【问题描述】:

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

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

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

【问题讨论】:

    标签: java sorting filter guava


    【解决方案1】:

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

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

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

    【讨论】:

    • 在其他情况下,throw new IllegalArgumentException()return 3 更好。
    【解决方案2】:

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

    诚然,这会返回一个 Set。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-04
          • 1970-01-01
          • 2020-10-20
          • 2017-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多