Wie kann man ein Array kürzen? v.5.0

Dies kann durch Umkopieren entstehen. Die statische Methode System.arraycopy() liefert hierzu die notwendige Routine.

Arrays haben fixe Größen. Sie können auf einfache Weise weder verlängert noch gekürzt werden. Eine Längenänderung erfordert somit ein klein Wenig mehr Aufwand und kann nur durch ein Kopieren der relevanten Inhalte erfolgen.

Die einfachste Form besteht wohl darin, die Anzahl der neu zu speichernden Elemente auszulesen und ein neues Array dieser Länge zu erzeugen, in das die Werte anschließend eingelesen werden. Diese Methode ist bei bei primitiven Datentypen ausreichend schnell.

Im Beispiel wird ein int -Array der Größe 10 erstellt, von dem nur die geraden Werte in einem entsprechend kürzeren Array gespeichert werden sollen. Hierzu wird die Länge des benötigten Arrays in einer Schleife durch eine Zählvariable ermittelt, ein zweites dieser Länge erstellt und anschließend die Daten eingelesen.

public class ArrayKuerzen {

    public static void main(String[] args) {
        int[] longArr = {5, 17, 23, 8, 18, 36, 56, 9, 10, 12};
        int count = 0;
        for(int i : longArr) {
            if(i%2==0)
                count++;
        }
        int[] shortArr = new int[count];
        int k=0;
        for(int i : longArr) {
            if(i%2==0) {
                shortArr[k] = i;
                k++;
            }
        }
        for(int i : shortArr)
            System.out.println(i); 
    }
}

Im zweiten Beispiel wird zunächst ein leeres temporäres Array identischer Länge erstellt. In einer for-Schleife wird das Ausgangs-Array ebenfalls durchlaufen und alle geraden Werte der Reihe nach im temporären Array gespeichert. Wie oben erfasst dabei die Zählvariable count nach Beendigung der Schleife die Länge des kurzen Zielarrays.
Im nächsten Schritt wird das Zielarray als leeres Array gleichen Typs mit Hilfe der Zählvariablen erstellt. Es besitzt somit nur die gewünschte kürzere Länge. Die statische Methode arraycopy() der Klasse System erstellt schließlich das endgültige gekürzte Array. Hierzu werden ihr fünf Parameter übergeben. Der Reihe nach sind dies:

Die Methode erstellt schließlich eine Kopie des gewünschten Arrays, deren Werte im Beispiel ausgegeben werden.

public class ArrayKuerzen1 {

    public static void main(String[] args) {
        int[] longArr = {5, 17, 23, 8, 18, 36, 56, 9, 10, 12};
        int[] evenArr = new int[longArr.length];
        int count = 0;
        for(int i : longArr) {
            if(i%2==0)
                evenArr[count++] = i;
        }
        int[] shortArr = new int[count];
        System.arraycopy(evenArr, 0, shortArr, 0, count);

        for(int i : shortArr)
            System.out.println(i);
    }
}

Beide Varianten nehmen sich nicht viel hinsichtlich ihrer Geschwindigkeit, wenn es um primitive Datentypen geht. Vergleicht man das Tempo jedoch bei beiden Varianten z.B. für String -Arrays großer Länge, so besitzt die zweite Möglichkeit erhebliche Geschwindigkeitsvorteile.

Die beiden folgenden Beispiele beruhen darauf, dass zunächst ein Array der Größe 10000000 mit Pseudo-Zufalls-Strings der Länge 4 erzeugt wird. Dies geschieht bei beiden identisch über den Umweg der Generierung von Character-Arrays, die den Bereich der lateinischen Kleinbuchstaben abdecken. Nach deren Fertigstellung beginnt die Zeitmessung. Wie auch beim Beispiel mit primitiven int -Typen wird über den Stringvergleich die Anzahl der zum Kopieren relevanten Elemente ermittelt, ein entsprechendes verkürztes Array erstellt und dann die Werte dort eingelesen. Nach Abschluss dieses Vorgangs wird die Zeitmessung gestoppt. Bei mehreren Versuchen ergaben sich hierbei Laufzeiten von ca. 130 ms.

import java.util.Random;

public class ArrayKuerzen2 {

    public static void main(String[] args) {
        String[] longArr = new String[10000000];
        char[] cArr;
        for(int i=0; i< longArr.length; i++){
            cArr = new char[4];
            for(int j=0; j< cArr.length; j++)
                cArr[j] = (char) (new Random().nextInt(26) + 97);
            longArr[i] = new String(cArr);
        }
        int count = 0;
        final long timeStart = System.currentTimeMillis(); 
        for(String s : longArr) {
            if(s.equals("abcd"))
                count++;
        }
        String[] shortArr = new String[count];
        int k=0;
        for(String s : longArr) {
            if(s.equals("abcd")) {
                shortArr[k++] = s;
            }
        }
        final long timeEnd = System.currentTimeMillis();
        System.out.println("Verlaufszeit des Kopierens: " + (timeEnd - timeStart) + " Millisek."); 
        System.out.println("L\u00e4nge des neuen Arrays: " + count);  
    }
}

Das letzte Beispiel entspricht, abgesehen vom oben geschilderten Erzeugen des Ausgangsarrays, dem analogen Beispiel mit int -Werten. Wie bei diesem wird hier die Methode System.arraycopy() verwendet. Die Laufzeit beträgt bei Versuchen hier ca. 70 bis 90 ms und ist somit signifikant kürzer. Man beachte, dass der String-Vergleich mit equals() bei den beiden letzten Beispielen identisch ist, sodass der zeitliche Unterschied auf den Kopiervorgang zurückzuführen ist.

import java.util.Random;

public class ArrayKuerzen3 {

    public static void main(String[] args) {
        String[] longArr = new String[10000000];
        String[] evenArr = new String[longArr.length];
        char[] cArr;
        for (int i = 0; i < longArr.length; i++) {
            cArr = new char[4];
            for (int j = 0; j < cArr.length; j++)
                cArr[j] = (char) (new Random().nextInt(26) + 97);
            longArr[i] = new String(cArr);
        }
        int count = 0;
        final long timeStart = System.currentTimeMillis();
        for (String s : longArr) {
            if (s.equals("abcd")) {
                evenArr[count++] = s;
            }
        }
        String[] shortArr = new String[count];
        System.arraycopy(evenArr, 0, shortArr, 0, count);
        final long timeEnd = System.currentTimeMillis();
        System.out.println("Verlaufszeit des Kopierens: "
                + (timeEnd - timeStart) + " Millisek.");
        System.out.println("L\u00e4nge des neuen Arrays: " + count);
    }
}