使用java流将数组拆分为子数组 - 有状态映射器

时间:2015-03-20 17:08:24

标签: java arrays lambda java-8 java-stream

我有一个带K * N元素的double []。我想将它拆分为N长[]数组大小为K的流(list / array / ...)。我已经找到了一个解决方案,但它看起来很脏,需要一个有状态的Mapper(我认为它们的意思是无国籍):

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的无状态要求。有没有更好的方法来实现同样的目标?

3 个答案:

答案 0 :(得分:2)

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;
   });

答案 1 :(得分:0)

@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()
   ;

答案 2 :(得分:0)

这是@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%