java – 用于转换不可变列表的番石榴一线

我认为必须有一个一线的番石榴解决方案来将一个不可变的列表转换成另一个不可变的列表,但是我找不到.假设我们有以下对象:

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.transform和FluentIterable都不那么有效.

转载注明原文:java – 用于转换不可变列表的番石榴一线 - 代码日志