java - 是否可以使用 Java Guava 将连接器(收集器、累加器)应用于函数?

标签 java collections guava java-stream joiner

是否可以在分组时通过集合收集字​​符串?这就是它在 Java 8 中的工作方式:

Map<String, String> discountOptions = p.getDiscountOptions().Stream()
    .collect(groupingBy(
        this::getDiscountName,
        Collectors.mapping(this::getValue, Collectors.joining(","))));

我很好奇,在 Google Guava 中是否有简洁的方法来做到这一点?这就是我尝试在 Guava 中复制它的方式:

Map<String, Collection<String>> stringCollectionMap = Multimaps.transformValues(
    Multimaps.index(p.getDiscountOptions(), 
        new Function<DiscountOption, String>() {
            @Override
            public String apply(DiscountOption d) {
                return getDiscountName(d);
            }
        }),
    new Function<DiscountOption, String>() {
        @Override
        public String apply(DiscountOption d) {
            return getValue(d);
        }
    }).asMap();

Map<String, String> discountOptions =  Maps.transformValues(
    stringCollectionMap,
    new Function<Collection<String>, String>() {
        @Override
        public String apply(Collection<String> strings) {
            return Joiner.on(",").join(strings);
        }
    });

最佳答案

你不会得到比 Java 8 流 API 更简洁的东西,因为它存在的原因是改进这些类型的操作。

Java 8 之前的函数式编程可以使用 Guava 的函数式实用程序进行临时装配,但是 as they warn :

As of Java 7, functional programming in Java can only be approximated through awkward and verbose use of anonymous classes.... Excessive use of Guava's functional programming idioms can lead to verbose, confusing, unreadable, and inefficient code.... Imperative code should be your default, your first choice as of Java 7.

这是您的代码的命令式翻译:

private static final Joiner COMMA_JOINER = Joiner.on(",");

ListMultimap<String, String> groupedByDiscountName = ArrayListMultimap.create();
for (DiscountOption option : p.getDiscountOptions()) {
  groupedByDiscountName.put(getDiscountName(option), getValue(option));
}

ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
for (Entry<String, Collection<String>> e : groupedByDiscountName.asMap().entrySet()) {
  builder.put(e.getKey(), COMMA_JOINER.join(e.getValues());
}
Map<String, String> discountOptions = builder.build();

它更短且更易于阅读。鉴于您当前的 API,这大概是您使用 Java 7 所能做的最好的事情。

也就是说,您可能会考虑重新检查您的 API - 特别是您使用静态方法(getDiscountName()getValue())来提取数据很奇怪来自您的 DiscountOption 类的数据 - 这些似乎是实例方法的明确候选者。同样,您可能会考虑创建一个 Discounts 类,其中包含一个或多个 DiscountOption 实例并提供一个返回逗号分隔字符串的 toString()。然后您只需要构造您的 Discounts 对象就可以了。

关于java - 是否可以使用 Java Guava 将连接器(收集器、累加器)应用于函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37588762/

相关文章:

java - 非法参数异常 : Comparison method violates it's general contract

java - 从 Google Collections 中查找 Multiset 中的前 N ​​个元素?

java - setResult 不适用于@EActivity

java - Apache Tomcat : Error

javascript - 需要在 url 访问时登录

访问 hashmap 时出现 java.util.ConcurrentModificationException

java - 两个 Set 包含相同的元素,但它们不相等。为什么是这样的结果?

java - Jackson 和 Guava 数据类型模块 : Ignore missing fields, 但序列化显式空值

java - Guava Hasher 有时对同一对象给出不同的结果

Java 时钟项目 - 勾选方法输出 "0"而不是 "00"分钟和秒,修复 AM PM 的输出