我有2个班级
A:
public class A {
private int intValue;
private String stringValue;
public A(int intValue, String stringValue) {
this.intValue = intValue;
this.stringValue = stringValue;
}
int getIntValue() {
return intValue;
}
String getStringValue() {
return stringValue;
}
}
和B:
public class B {
private int intValue;
private String stringValue;
B(int intValue, String stringValue) {
this.intValue = intValue;
this.stringValue = stringValue;
}
int getIntValue() {
return intValue;
}
String getStringValue() {
return stringValue;
}
}
和一些非常大的A对象数组。
我希望有效地将A[]
转换为ArrayList<B>
。我知道有几种方法可以做到这一点:
final A[] array = {new A(1, "1"), new A(2, "2")/*...*/};
// 1 - old-school
final List<B> list0 = new ArrayList<>(array.length);
for (A a : array) {
list0.add(new B(a.getIntValue(), a.getStringValue()));
}
// 2 - pretty mush same as 1
final List<B> list1 = new ArrayList<>(array.length);
Arrays.stream(array).forEach(a -> list1.add(new B(a.getIntValue(), a.getStringValue())));
// 3 - lambda-style
final List<B> list2 = Arrays.stream(array).map(a -> new B(a.getIntValue(), a.getStringValue())).collect(Collectors.toList());
// 4 - lambda-style with custom Collector
final List<B> list3 = Arrays.stream(array)
.map(a -> new B(a.getIntValue(), a.getStringValue()))
.collect(Collector.of((Supplier<List<B>>)() -> new ArrayList(array.length), List::add, (left, right) -> {
left.addAll(right);
return left;
}));
AFAIK 1效率最高。但是使用java 8功能可以缩短它。 2与1几乎相同,但foreach
循环由流foreach
替换。不确定它的有效性。 3是最短路径,但默认Collectors.toList()
收集器使用默认的ArrayList::new
构造函数,这意味着如果我们有相当大的初始数组,ArrayList
中的数组将至少调整一次。所以效率不高。 4,正如我所理解的那样(从未使用过这种方式)与3几乎相同,但在ArrayList
中为数组分配了单个内存。但它看起来很难看。
所以,我的问题是。我对这四种方式及其有效性是否正确?还有其他简短有效的方法吗?
答案 0 :(得分:4)
你的#4可能会在短时间内写出来:
final List<B> list4 = Arrays.stream(array)
.map(a -> new B(a.getIntValue(), a.getStringValue()))
.collect(toCollection(() -> new ArrayList<>(array.length)));
您还可以使用单独的方法提取映射:
final List<B> list4 = Arrays.stream(array)
.map(SomeClass::mapA2B)
.collect(toCollection(() -> new ArrayList<>(array.length)));
private static B mapA2B(A a) {
return new B(a.getIntValue(), a.getStringValue());
}
答案 1 :(得分:1)
如果您对最有效的解决方案感兴趣,可以考虑
List<B> list=Arrays.asList(Arrays.stream(array)
.map(a -> new B(a.getIntValue(), a.getStringValue()))
.parallel().toArray(B[]::new));
与使用collect
抽象的Collector
不同,toArray
是Stream
的内在操作。由于Arrays.asList
返回的流具有已知大小,因此实现将创建一个目标数组,并在并行处理时写入该数组的不同区域。相反,collect
将创建多个列表,并行处理它们并在之后合并它们,这不适合像这样简单的操作。
即使是单线程使用,它也可能表现更好,因为它只是填充一个数组(“处理原始金属”)并在之后创建一个轻量级List
视图。