【问题标题】:Can I decorate Joiner class of Guava我可以装饰番石榴的木匠类吗
【发布时间】:2011-02-18 11:44:32
【问题描述】:

我有一个List<String>,我们正在使用 Joiner 来获取该列表的逗号分隔表示,但现在我们需要做一些改进,我们需要将列表中的值大写。现在代码是 -

String str = Joiner.on(',').skipNulls().join(myValueList);

但是现在我需要将值中存在的字符串大写,我需要先对其进行迭代以大写,然后传递给 Joiner 以加入,但我认为这不是一个好方法,因为它会迭代 List 两次, 一个大写,然后 Joiner 将迭代到 Join。
是否有任何其他我遗漏的实用方法可以在一次迭代中做到这一点。

您将如何使用 Guava?

【问题讨论】:

    标签: java guava


    【解决方案1】:

    您可以使用Iterables.transform()

    Iterable<String> upperStrings = Iterables.transform(myValueList, new Function<String,String>() {
      public String apply(String input) {
        // any transformation possible here.
        return (input == null) ? null : input.toUpperCase();
      }
    });
    Str str = Joiner.on(',').skipNulls().join(upperStrings);
    

    【讨论】:

    • 我不质疑你的回答。只是一个评论 - 它比简单的 for 循环迭代字符串列表更好吗? Guava 方法的可读性很差。
    • @Grzegorz:一个优点是您不需要创建myValueList 的副本。返回的Iterable 懒惰地调用指定的方法,因此可以潜在地保护相当多的内存。我同意代码看起来不太好。不幸的是,Java 中的闭包不会很快到来。
    • 我这样写的主要原因是这个问题明确要求使用番石榴解决方案,'虽然;-)
    • @Sean Patrick Floyd +1,@Joachim +1,是的,但我都喜欢,而且考虑到在加入呼叫时转换会延迟发生,性能将是相同的.. 对?
    • @Premraj 几乎是对的。就我而言,枚举只会创建一次,而匿名函数将在每次调用时创建一次。但我们在这里谈论的是纳秒。
    【解决方案2】:

    关于 Joachim Sauer 的回答:

    如果你将函数移动到一个可以重复使用的地方,它可以变得不那么冗长,在 Guava 中,典型的场景是使用枚举:

    public enum StringTransformations implements Function<String, String>{
        LOWERCASE{
    
            @Override
            protected String process(final String input){
                return input.toLowerCase();
            }
        },
        UPPERCASE{
            @Override
            protected String process(final String input){
                return input.toUpperCase();
            }
        }
        // possibly more transformations here
        ;
    
        @Override
        public String apply(final String input){
            return input == null ? null : process(input);
        }
    
        protected abstract String process(String input);
    
    }
    

    现在客户端代码如下所示:

    String str =
        Joiner
            .on(',')
            .skipNulls()
            .join(
                Iterables.transform(myValueList,
                    StringTransformations.UPPERCASE));
    

    我认为它更具可读性。

    当然,如果你为你的 Joiner 引入一个常量会更好(在内存使用和性能方面):

    private static final Joiner COMMA_JOINER = Joiner.on(',').skipNulls();
    
    // ...
    
    String str = COMMA_JOINER.join(
                Iterables.transform(myValueList,
                    StringTransformations.UPPERCASE));
    

    【讨论】:

    • 我喜欢使用enums 的想法!我一直在使用返回 Function 对象的静态方法,但这更干净。
    • 当您需要在某些通用范围内返回函数时,您有时仍需要静态方法。 Guava 的许多静态工厂方法在内部使用枚举,但需要工厂方法只是因为它是泛型的翻译。
    • 我认为最好总是将函数公开为静态工厂,以获得灵活性(无论是否为泛型)。实现通常会使用枚举单例模式,但它是一个实现细节并且可能会改变。另外,使用枚举时,所有函数都必须具有相同的泛型类型(不能在同一个枚举上同时拥有 Function 和 Function )。 Guava 也这样做:code.google.com/p/guava-libraries/source/browse/trunk/src/com/…(参见 toStringFunction() / identity())。
    【解决方案3】:

    下面的呢?

    Joiner.on(',').skipNulls().join(myValueList).toUpperCase()
    

    【讨论】:

    • 没错,但我认为他的意思是大写:每个单词的第一个字母大写(我也弄错了:-))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    相关资源
    最近更新 更多