Java 将数组拆分为 X 长度的片段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19237371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Split array into pieces of X length
提问by Brandon
Currently I have an array of size N. I'm trying to copy every X amount of bytes from the array.
目前我有一个大小为 N 的数组。我试图从数组中复制每 X 个字节。
Example if the array is size 10 and I want arrays of size 3. I'd copy the first 3 elements then the next 3 and the last 1.
例如,如果数组大小为 10,而我想要大小为 3 的数组。我将复制前 3 个元素,然后复制接下来的 3 个和最后一个 1。
Currently I'm using the following algorithm:
目前我正在使用以下算法:
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.
Is there a more efficient or a more decent way of doing the what I want? This algorithm looks pretty bad =l
有没有更有效或更体面的方式来做我想做的事?这个算法看起来很糟糕=l
Any ideas how I can improve it or at least a hint?
任何想法如何改进它或至少是一个提示?
采纳答案by arshajii
What about this:
那这个呢:
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);
回答by henderso
You can use split with a special regular expression:
您可以将 split 与特殊的正则表达式一起使用:
System.out.println(Arrays.toString(
"Thisismystringiwanttosplitintogroupswith4chareach".split("(?<=\G.{4})")
));
Credit to earlier postby Alan Moore. Please visit and vote up.
归功于Alan Moore 的早期帖子。请访问并投票。
回答by rolfl
Few things to do here:
这里要做的事情很少:
First, common conventions frown apon using capitals to start variable names, change the I
and NewArray
variables to 'i' and 'newArray' respectively.
首先,常见的约定不赞成使用大写字母作为变量名的开头,将变量I
和NewArray
变量分别更改为 'i' 和 'newArray'。
Then, your code does not work because your first time through the loop, i-3
will lead to an IndexOutOfBounds exception.....
然后,您的代码不起作用,因为您第一次通过循环,i-3
将导致 IndexOutOfBounds 异常.....
Finally, you do not show how you set the size of the newArray array.
最后,您没有展示如何设置 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 --;
}
回答by leventov
If actually you need quite big chunks, and don't want to modify their contents independently, consider reusing the same initial array by means of ByteBuffer.wrap()
and then slice()
repeatedly. This would prevent unnecessary copying and memory waste.
如果实际上您需要相当大的块,并且不想单独修改它们的内容,请考虑通过ByteBuffer.wrap()
然后slice()
重复使用相同的初始数组。这将防止不必要的复制和内存浪费。
回答by Gubatron
Here's my implementation for this, it will split your array in sub-arrays of up to a maximum size you decide on, and put the sub-arrays into a list of arrays. The last array will be smaller if the size of the array is not a multiple of the maximum size chosen.
这是我对此的实现,它会将您的数组拆分为您决定的最大大小的子数组,并将子数组放入数组列表中。如果数组的大小不是所选最大大小的倍数,则最后一个数组将更小。
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;
}
回答by Evan Hu
Here is a function to split arrays, you can use below main method to test it.
这是一个拆分数组的函数,您可以使用下面的主要方法来测试它。
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;
}
Testing method:
测试方法:
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));
}
}
回答by bvdb
Here's a convenient methodthat converts a byte[]
to an array of byte[]
's. So, the result is a byte[][]
.
这是将 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;
}
Some advantages compared to the previous best answer:
与之前的最佳答案相比,有一些优势:
- The
for
condition uses a<=
which makes more sense than< ... + 1
. - Putting the stop-index in a temporary field reduces the number of calculations in the last
if
block.
- 该
for
条件使用<=
,这使得比更有意义< ... + 1
。 - 将停止索引放在临时字段中会减少最后一个
if
块中的计算次数。
(Unit tested)
(单元测试)
回答by Splash
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();
}
}
回答by CtrlX
I know that this question is pretty old but hey, someone could search for another clean Java answer for this common question. It you are working with List (Java 7), there is a pretty simple and clean method to get a portion of a list : List.subList( fromIndex, toIndex )
我知道这个问题已经很老了,但是嘿,有人可以为这个常见问题搜索另一个干净的 Java 答案。如果您正在使用 List (Java 7),有一个非常简单和干净的方法来获取列表的一部分:List.subList( fromIndex, toIndex )
It's straightforward to use. If I take the question example, it would be like :
使用起来很简单。如果我以问题为例,那就是:
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
To get ride of the 'counter', some could change the way NewArray is build for a Listapproach as well, with something like :
为了摆脱“计数器”,有些人还可以改变为List方法构建 NewArray 的方式,例如:
// NewArray must be a List<List<Byte>>
NewArray.addAll(byteList.subList(fromIndex, toIndex));
Hope this will help someone in the future !
希望这会在将来对某人有所帮助!