15

目前我有一个大小为 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

任何想法我可以如何改进它或至少一个提示?

4

9 回答 9

13

那这个呢:

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);
于 2013-10-08T01:05:56.273 回答
7

这是一种将 a 转换为's数组的便捷方法。所以,结果是一个。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条件使用 a比<=更有意义< ... + 1
  2. 将停止索引放在临时字段中可以减少最后一个if块中的计算次数。

(单元测试)

于 2015-08-24T09:43:44.543 回答
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 --;
}
于 2013-10-08T01:26:57.293 回答
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;
}
于 2015-01-22T22:10:44.623 回答
2

这是一个拆分数组的函数,您可以使用下面的 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));
}
}
于 2015-05-07T08:19:37.837 回答
1

我知道这个问题已经很老了,但是嘿,有人可以为这个常见问题搜索另一个干净的 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

为了摆脱“计数器”,有些人也可以改变 NewArray 为List方法构建的方式,例如:

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

希望这对将来的人有所帮助!

于 2019-01-04T01:23:14.343 回答
0

您可以将 split 与特殊的正则表达式一起使用:

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

归功于Alan Moore之前的帖子。请访问并投票。

于 2013-10-08T01:11:58.063 回答
0

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

于 2013-10-08T06:47:20.227 回答
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();
    }
}
于 2017-03-15T10:01:17.000 回答