目前我有一个大小为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
我有什么想法可以改进它或至少提示一下?
答案 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;
}
与之前最佳答案相比的一些优势:
for
条件使用的<=
比< ... + 1
更有意义。if
块中的计算次数。(单位测试)
答案 2 :(得分:3)
这里很少有事情要做:
首先,常见约定使用大写字母来启动变量名称,将I
和NewArray
变量分别更改为“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));
希望这对以后的人有帮助!