Actuellement, j'ai un tableau de taille N. J'essaie de copier chaque X octets du tableau.
Exemple si le tableau est de taille 10 et que je veux des tableaux de taille 3. Je copierais les 3 premiers éléments, puis les 3 suivants et le dernier.
Actuellement, j'utilise l'algorithme suivant:
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.
Existe-t-il un moyen plus efficace ou plus décent de faire ce que je veux? Cet algorithme semble très mauvais = l
Des idées comment je peux l'améliorer ou au moins un indice?
Et ça:
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);
Voici une méthode pratique qui convertit un byte[]
en un tableau de byte[]
. Donc, le résultat est un 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;
}
Quelques avantages par rapport à la précédente meilleure réponse :
for
utilise un <=
qui a plus de sens que < ... + 1
.if
.(Testé à l'unité)
Peu de choses à faire ici:
Premièrement, les conventions courantes fronçant les sourcils après avoir utilisé des majuscules pour commencer les noms de variable, modifiez les variables I
et NewArray
en 'i' et 'newArray' respectivement.
Ensuite, votre code ne fonctionne pas car votre première fois dans la boucle, i-3
mènera à une exception IndexOutOfBounds .....
Enfin, vous n'indiquez pas comment vous définissez la taille du tableau 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 --;
}
Voici mon implémentation pour cela, il divisera votre tableau en sous-tableaux d'une taille maximale que vous déciderez, et placera les sous-tableaux dans une liste de tableaux. Le dernier tableau sera plus petit si sa taille n'est pas un multiple de la taille maximale choisie.
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;
}
Vous pouvez utiliser split avec une expression régulière spéciale:
System.out.println(Arrays.toString(
"Thisismystringiwanttosplitintogroupswith4chareach".split("(?<=\\G.{4})")
));
Crédit à message précédent par Alan Moore. S'il vous plaît visitez et votez.
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();
}
}
Je sais que cette question est assez ancienne, mais bon, quelqu'un pourrait chercher une autre réponse propre à Java pour cette question courante. Si vous travaillez avec List (Java 7), il existe une méthode assez simple et propre pour obtenir une partie d'une liste: List.subList (fromIndex, toIndex)
C'est simple à utiliser. Si je prends l'exemple de la question, ce serait comme:
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
Pour contourner le 'compteur', certains pourraient changer la façon dont NewArray est construit pour une approche List , avec quelque chose comme:
// NewArray must be a List<List<Byte>>
NewArray.addAll(byteList.subList(fromIndex, toIndex));
J'espère que cela aidera quelqu'un dans le futur!
Voici une fonction pour diviser des tableaux, vous pouvez utiliser la méthode principale ci-dessous pour le tester.
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;
}
Méthode d'essai:
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));
}
}
Si vous avez réellement besoin de gros morceaux et que vous ne souhaitez pas modifier leur contenu indépendamment, envisagez de réutiliser le même tableau initial au moyen de ByteBuffer.wrap()
, puis de slice()
à plusieurs reprises. Cela éviterait les copies inutiles et le gaspillage de mémoire.