使用 java 流将数组拆分为子数组 - 有状态映射器
Splitting an array into subarrays with java streams - stateful mapper
我有一个包含 K*N 个元素的 double[]。我想将其拆分为 N 个大小为 K 的 long[] 数组的流 (list/array/...)。我已经找到了一个解决方案,但它看起来很脏并且需要一个有状态的映射器(我认为它们意味着无国籍):
private class DataToLong implements DoubleFunction<long[]> {
int d = 0;
long[] buf = new long[K];
@Override
public long[] apply(double value) {
buf[d] = BitTools.toSortableLong(value);
d++;
long[] ret = null;
if (d >= K) {
ret = buf;
buf = new long[K];
d = 0;
}
return ret;
}
}
public void load(double[] data, int K) {
Arrays.stream(data).mapToObj(new DataToLong())
.filter((x)-> x != null).forEach((buf)->{
//here we do something with 'buf'
});
}
上面的代码看似可行,但实际上比非流版本的代码要长,而且违反了Mapper的无状态要求。有没有更好的方法可以达到同样的目的?
IntStream.range(0, n).mapToObj(
i -> {
long[] arr = new long[k];
for (int j = 0; j < k; j++) {
arr[j] = BitTools.toSortableLong(data[k * i + j]);
}
return arr;
});
@Louis Wasserman 回答的变体:
IntStream.range(0, n)
// for each int i, derive a DoubleStream that maps each
// j in range(0, k) to the double in data[k * i + j]
.mapToObj(
i -> IntStream.range(0, k)
.mapToDouble(j -> data[k * i + j])
)
// flatMap from Stream<DoubleStream> to DoubleStream
.flatMapToDouble(Function.identity())
// call BitTools::toSortableLong on every double
.mapToLong(BitTools::toSortableLong)
// collect into a long[]
.toArray()
;
这是@Louis Wasserman 回答的另一种变体,整合了@srborlongan 回答的一部分。 Tt 避免了 'new' 和循环:
IntStream.range(0, N)
.mapToObj(
i -> IntStream.range(0, DIM)
.mapToLong(
j -> pre(data[DIM * i + j])
).toArray()
).forEach(buf -> myFunction(buf));
不幸的是,它似乎比@Louis Wasserman 的解决方案慢 10-20%
我有一个包含 K*N 个元素的 double[]。我想将其拆分为 N 个大小为 K 的 long[] 数组的流 (list/array/...)。我已经找到了一个解决方案,但它看起来很脏并且需要一个有状态的映射器(我认为它们意味着无国籍):
private class DataToLong implements DoubleFunction<long[]> {
int d = 0;
long[] buf = new long[K];
@Override
public long[] apply(double value) {
buf[d] = BitTools.toSortableLong(value);
d++;
long[] ret = null;
if (d >= K) {
ret = buf;
buf = new long[K];
d = 0;
}
return ret;
}
}
public void load(double[] data, int K) {
Arrays.stream(data).mapToObj(new DataToLong())
.filter((x)-> x != null).forEach((buf)->{
//here we do something with 'buf'
});
}
上面的代码看似可行,但实际上比非流版本的代码要长,而且违反了Mapper的无状态要求。有没有更好的方法可以达到同样的目的?
IntStream.range(0, n).mapToObj(
i -> {
long[] arr = new long[k];
for (int j = 0; j < k; j++) {
arr[j] = BitTools.toSortableLong(data[k * i + j]);
}
return arr;
});
@Louis Wasserman 回答的变体:
IntStream.range(0, n)
// for each int i, derive a DoubleStream that maps each
// j in range(0, k) to the double in data[k * i + j]
.mapToObj(
i -> IntStream.range(0, k)
.mapToDouble(j -> data[k * i + j])
)
// flatMap from Stream<DoubleStream> to DoubleStream
.flatMapToDouble(Function.identity())
// call BitTools::toSortableLong on every double
.mapToLong(BitTools::toSortableLong)
// collect into a long[]
.toArray()
;
这是@Louis Wasserman 回答的另一种变体,整合了@srborlongan 回答的一部分。 Tt 避免了 'new' 和循环:
IntStream.range(0, N)
.mapToObj(
i -> IntStream.range(0, DIM)
.mapToLong(
j -> pre(data[DIM * i + j])
).toArray()
).forEach(buf -> myFunction(buf));
不幸的是,它似乎比@Louis Wasserman 的解决方案慢 10-20%