将数组拆分为X长度的片段

时间:2013-10-08 01:01:30

标签: java arrays performance algorithm

目前我有一个大小为N的数组。我正在尝试从数组中复制每个X字节数。

示例如果数组大小为10并且我想要大小为3的数组。我将复制前3个元素,然后复制下3个元素和最后1个元素。

目前我正在使用以下算法:

int I = 0;
int sub = bytes.length;
int counter = 0;
for (I = 0; I < bytes.length; ++I) {
    if (I % 3 == 0 && I != 0) {
       NewArray[counter] = Arrays.copyOfRange(bytes, I - 3, I));
        sub -= 3;
        ++counter;
    }
}

NewArray[counter] = Arrays.copyOfRange(bytes, I - sub, I)); //Copy remainder.

是否有更高效或更体面的方式来做我想要的事情?这个算法看起来很糟糕= l

我有什么想法可以改进它或至少提示一下?

9 个答案:

答案 0 :(得分:10)

这个怎么样:

int x = 3;  // chunk size
int len = bytes.length;
int counter = 0;

for (int i = 0; i < len - x + 1; i += x)
    newArray[counter++] = Arrays.copyOfRange(bytes, i, i + x);

if (len % x != 0)
    newArray[counter] = Arrays.copyOfRange(bytes, len - len % x, len);

答案 1 :(得分:7)

这是方便的方法,可将byte[]转换为byte[]的数组。因此,结果是byte[][]

public byte[][] splitBytes(final byte[] data, final int chunkSize)
{
  final int length = data.length;
  final byte[][] dest = new byte[(length + chunkSize - 1)/chunkSize][];
  int destIndex = 0;
  int stopIndex = 0;

  for (int startIndex = 0; startIndex + chunkSize <= length; startIndex += chunkSize)
  {
    stopIndex += chunkSize;
    dest[destIndex++] = Arrays.copyOfRange(data, startIndex, stopIndex);
  }

  if (stopIndex < length)
    dest[destIndex] = Arrays.copyOfRange(data, stopIndex, length);

  return dest;
}

与之前最佳答案相比的一些优势

  1. for条件使用的<=< ... + 1更有意义。
  2. 将stop-index放在临时字段中会减少上一个if块中的计算次数。
  3. (单位测试)

答案 2 :(得分:3)

这里很少有事情要做:

首先,常见约定使用大写字母来启动变量名称,将INewArray变量分别更改为“i”和“newArray”。

然后,您的代码无效,因为您第一次通过循环,i-3将导致IndexOutOfBounds异常.....

最后,您没有展示如何设置newArray数组的大小。

int sublen = 3; // how many elements in each sub array.
int size = ((bytes.length - 1) / sublen) + 1; // how many newArray members we will need
byte[][] newArray = new byte[size][]; 
int to = byte.length;
int cursor = size - 1;
int from = cursor * sublen;
while (cursor >= 0) {
    newArray[cursor] = Arrays.copyOfRange(bytes, from, to);
    to = from;
    from -= sublen;
    cursor --;
}

答案 3 :(得分:2)

这是我的实现,它会将您的数组拆分为您决定的最大大小的子数组,并将子数组放入数组列表中。如果数组的大小不是所选最大大小的倍数,则最后一个数组将更小。

import java.util.Arrays;
...

public static <T> List<T[]> splitArray(T[] items, int maxSubArraySize) {
  List<T[]> result = new ArrayList<T[]>();
  if (items ==null || items.length == 0) {
      return result;
  }

  int from = 0;
  int to = 0;
  int slicedItems = 0;
  while (slicedItems < items.length) {
      to = from + Math.min(maxSubArraySize, items.length - to);
      T[] slice = Arrays.copyOfRange(items, from, to);
      result.add(slice);
      slicedItems += slice.length;
      from = to;
  }
  return result;
}

答案 4 :(得分:0)

您可以使用特殊正则表达式拆分:

 System.out.println(Arrays.toString(
     "Thisismystringiwanttosplitintogroupswith4chareach".split("(?<=\\G.{4})")
 ));

Alan Moore对earlier post的评价。请访问并投票。

答案 5 :(得分:0)

如果实际上您需要相当大的块,并且不想单独修改它们的内容,请考虑重复使用ByteBuffer.wrap()然后slice()重复使用相同的初始数组。这样可以防止不必要的复制和内存浪费。

答案 6 :(得分:0)

这是一个分割数组的函数,你可以使用下面的main方法来测试它。

private static List<Integer[]> splitArray(Integer[] originalArray, int chunkSize) {
List<Integer[]> listOfArrays = new ArrayList<Integer[]>();
int totalSize = originalArray.length;
if(totalSize < chunkSize ){
   chunkSize = totalSize;
}
int from = 0;
int to = chunkSize;

while(from < totalSize){
    Integer[] partArray = Arrays.copyOfRange(originalArray, from, to);
    listOfArrays.add(partArray);

    from+= chunkSize;
    to = from + chunkSize;
    if(to>totalSize){
        to = totalSize;
    }
}
return listOfArrays;
}

测试方法:

public static void main(String[] args) {
List<Integer> testingOriginalList = new ArrayList<Integer>();

for(int i=0;i<200;i++){
    testingOriginalList.add(i);
}

int batchSize = 51;
Integer[] originalArray = testingOriginalList.toArray(new Integer[]{});

List<Integer[]> listOfArrays = splitArray(originalArray, batchSize);


for(Integer[] array : listOfArrays){
    System.out.print(array.length + ", ");
    System.out.println(Arrays.toString(array));
}
}

答案 7 :(得分:0)

import java.util.Arrays;

public class Test {

    private void run() {
        try {

            byte[] cfsObjIds = "abcdefghij".getBytes();
            System.out.println(Arrays.toString(cfsObjIds));

            final int chunkSize = 4;
            System.out.println("Split by " + chunkSize + ":");
            int objQty = cfsObjIds.length;
            for (int i = 0; i < objQty; i += chunkSize) {
                int chunkUpperLimit = Math.min(objQty, i + chunkSize);
                byte[] cfsIdsChunk = Arrays.copyOfRange(cfsObjIds, i, chunkUpperLimit);

                System.out.println(Arrays.toString(cfsIdsChunk));
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        new Test().run();
    }
}

答案 8 :(得分:0)

我知道这个问题已经很老了,但是,有人可以为这个常见问题搜索另一个干净的Java答案。 如果您正在使用List(Java 7),则有一种非常简单干净的方法来获取列表的一部分:List.subList( fromIndex, toIndex )

易于使用。如果我以问题示例为例,则为:

int chunkSize = 3;
int counter = 0;
// bytes must be a List like an ArrayList
List<Byte> byteList = Arrays.asList(bytes);
int length = byteList.size(); 
for (int fromIndex = 0; fromIndex < length; fromIndex += chunkSize) {
   int toIndex = fromIndex + chunkSize;
   if(toIndex > length){
      toIndex = length;
   }
   NewArray[counter] = byteList.subList(fromIndex, toIndex);
   counter++;
}
// Now NewArray[] contain sub array and the last one is of the remaining length

要驾驭“计数器”,有些人还可以使用类似的方法来更改为List方法构建NewArray的方式:

// NewArray must be a List<List<Byte>>
NewArray.addAll(byteList.subList(fromIndex, toIndex));

希望这对以后的人有帮助!