Java 用于转换不可变列表的Guava one liner

Java 用于转换不可变列表的Guava one liner,java,guava,Java,Guava,我认为一定有一个单行番石榴解决方案可以将一个不可变列表转换为另一个不可变列表,但我找不到它。假设我们有以下对象: ImmutableList<String> input = ImmutableList.of("a", "b", "c"); Function<String, String> function = new Function<String, String>() { @Override public String apply(Strin

我认为一定有一个单行番石榴解决方案可以将一个不可变列表转换为另一个不可变列表,但我找不到它。假设我们有以下对象:

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;
    }
};
ImmutableList输入=ImmutableList.of(“a”、“b”、“c”);
函数=新函数(){
@凌驾
公共字符串应用(字符串输入){
返回输入+输入;
}
};
这种转变可以这样实现:

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);
Iterable transformedIt=Iterables.transform(输入,函数);
ImmutableList输出=ImmutableList.builder().addAll(transformedIt.build();
或者像这样:

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);
List transformedList=List.transform(输入,函数);
ImmutableList output2=ImmutableList.copyOf(transformedList);

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

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

您只需删除构建器并将其内联即可获得(稍长的)一行程序

ImmutableList<String> output =
    ImmutableList.copyOf(Iterables.transform(input, function));
和一个手卷的环

更新 虽然第一种方法肯定是最具可读性的方法,但它会为调整数组大小和最终缩小到所需大小带来一些分配。对于长度为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));
ImmutableList输出=
ImmutableList.copyOf(list.transform(输入,函数));

因为它不包括数组复制。这是
列表的结果。transform
是一个惰性集合,并且
不可变列表。copyOf
查询其大小以分配适当大小的数组。请注意,
Iterables.transform
fluenterable
都没有那么有效。

我想
input.stream().collect(toImmutableList())
是您所需要的。请参阅

在java 8中使用闭包是可能的,但不确定Guava。@EugenHalca在java 8中有不可变的集合吗?(我指的是真正不可变的,而不是不可修改的包装)。或者,如果我在Java8中使用Guava ImmutableList,是否可以将ImmutableList转换为ImmutableList?请注意,转换为简单列表是在我的问题中完成的(参见第二个示例),我问的是如何转换为不可变列表。实际上,
ImmutableList.copyOf(list.transform(input,function))
应该完全避免调整数组的大小。@Louis Wasserman:我明白了。所以我可以用这个替换我的第二个片段。我想OP的观点是,总是存在一些复制,这可以通过
ImmutableList.copyOfWithCapacity(迭代器,容量)
之类的方法避免。为Iterable添加相同的值;需要两个丑陋的重载。@maaartinus我的观点是,如果我问“什么是一个不可变列表的转换?”我认为直观的答案是“另一个不可变列表”,所以应该有一个转换方法可以做到这一点。我不得不调用ImmutableList.copyOf,这感觉很不自然,它的性能不能像立即创建ImmutableList那样好(尽管在我的情况下,性能并不重要)。我接受了你的回答,因为“这是番石榴中缺失的,这是你能做的最好的解决办法”@user1954847:我完全同意你的看法。我认为应该有
fluenterable.from(input).transform(function).toImmutableList()
@maaartinus,这里有一个问题。我已经回答了一些更多的讨论: