繁体   English   中英

用于转换不可变列表的番石榴单行程序

[英]Guava one-liner for transforming immutable lists

我认为必须有一个单行的Guava解决方案,用于将不可变列表转换为另一个不可变列表,但我找不到它。 假设我们有以下对象:

ImmutableList<String> input = ImmutableList.of("a", "b", "c");
Function<String, String> function = new Function<String, String>() {
    @Override
    public String apply(String input) {
        return input + input;
    }
};

转换可以像这样实现:

Iterable<String> transformedIt = Iterables.transform(input, function);
ImmutableList<String> output = ImmutableList.<String>builder().addAll(transformedIt).build();

或者像这样:

List<String> transformedList = Lists.transform(input, function);
ImmutableList<String> output2 = ImmutableList.copyOf(transformedList);

但我认为必须有一个性能优化的单线程用于这种转换,没有中间对象,我只是找不到它。 它在哪里?

您可以简单地删除您的构建器并将其内联以获得(更长的)单行

ImmutableList<String> output =
    ImmutableList.copyOf(Iterables.transform(input, function));

由于Iterables.transform是惰性的,所以这种方法是最优的,因此不会分配临时列表。 AFAIK有一些轻微的低效率:

  • 分配FluentIterable
  • 调整用于结果的数组的大小

如果你真的非常关心速度,你可以对它进行基准测试并与之比较

ArrayList<String> tmp = Lists.newArrayListWithCapacity(input.size());
Iterables.addAll(tmp, Iterables.transform(input, function));
ImmutableList<String> output = ImmutableList.copyOf(tmp);

和一个手动循环。

UPDATE

虽然第一种方法肯定是最具可读性的方法,但它会产生一些用于数组大小调整的分配以及最终缩小到所需大小的方法。 使用长度为1234567的列表,有以下调整大小步骤:

4 - > 7 - > 11 - > 17 - > 26 - > 40 - > 61 - > 92 - > 139 - > 209 - > 314 - > 472 - > 709 - > 1064 - > 1597 - > 2396 - > 3595 - > 5393 - > 8090 - > 12136 - > 18205 - > 27308 - > 40963 - > 61445 - > 92168 - > 138253 - > 207380 - > 311071 - > 466607 - > 699911 - > 1049867 - > 1574801

并最终萎缩

1574801 - > 1234567

更新2

正如路易斯和克里斯所说,最佳解决方案是

ImmutableList<String> output =
    ImmutableList.copyOf(Lists.transform(input, function));

因为它不包括阵列复制。 这可以作为Lists.transform的结果是一个惰性集合,而ImmutableList.copyOf查询它的大小,以便分配一个正确大小的数组。 请注意, Iterables.transformFluentIterable是那么有效。

我想你已经写了几个这样的单行的例子。 转换是在最少的新对象创建的情况下完成的。 事实上,Guava以懒惰的方式工作:它不会遍历您的列表,创建其他元素并将其放到另一个列表中。 它创建了一个惰性列表,只要需要它的元素就可以填充它,例如,当您迭代新列表时。 我认为带有闭包的java 8对于这个用例来说不会太快,因为它会执行类似的字节代码,但语法会更短。

我想input.stream().collect(toImmutableList())就是你所需要的。 文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM