1

分组时是否可以通过收集收集字符串?这就是它在 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);
        }
    });
4

1 回答 1

3

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

Java 8 之前的函数式编程可以与 Guava 的函数式实用程序一起使用,但正如他们警告的那样:

从 Java 7 开始,Java 中的函数式编程只能通过笨拙和冗长地使用匿名类来近似......过度使用 Guava 的函数式编程习惯会导致冗长、混乱、不可读和低效的代码......命令式代码应该是您的默认值,从 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对象就可以了。

于 2016-06-02T15:46:23.493 回答