Расширение массива?

Я знаю, что вы не можете динамически расширять нормальный массив, но является ли это правильным способом?

public int size = 0;    
public String[] OrigArray = new String[size+1]; 

public void expand(){


            String[] tempArray = new String[size+1];    

            tempArray = (String[])OrigArray.clone();

            OrigArray = new String[size+1];

            OrigArray = (String[])tempArray.clone();    

            size++;         

    }

Я знаю гораздо лучшие методы, чем пытаюсь использовать обычный массив, но я хотел бы это понять, просто используя обычный массив.

Мое желание состоит в том, что он начинается с OrigArray, равным 0 + 1 (так 1), и когда expand() вызывается, создается новый tempArray, который имеет тот же размер, что и OrigArray, и тогда это выполняется OrigArray, а OrigArray снова объявляется с помощью size+1, затем tempArray копируется обратно в новый размер OrigArray. Это имеет смысл для меня, но я все время ухожу из связанного исключения?

Ответ 1

Метод не меняет значение OrigArray; все, что он делает, это хранить клон клона в нем, поэтому по сути значение не изменяется.

Я думаю, что вы хотите:

public void expand() {
    String[] newArray = new String[OrigArray.length + 1];
    System.arraycopy(OrigArray, 0, newArray, 0, OrigArray.length);

    //an alternative to using System.arraycopy would be a for-loop:
    // for(int i = 0; i < OrigArray.length; i++)
    //     newArray[i] = OrigArray[i];
    OrigArray = newArray;
}

Это создает массив с размером 1 больше, чем OrigArray, копирует содержимое OrigArray в него и присваивает этот массив OrigArray. Если вы не хотите помнить, сколько раз expand() было вызвано, не должно быть причин иметь переменную size.

EDIT: Если вы действительно хотите знать способ разумного внедрения функциональности, которую вы просили, вы можете пойти с тем, что сказал @Óscar López и использовали ArrayList.

Ответ 2

Что вы пытаетесь выполнить вручную, это в значительной степени то, что ArrayList делает для вас - вместо этого используйте этот класс.

Под капотом ArrayList используется Object[] для хранения элементов под определенным ограничением емкости. Когда массив заполняется (по мере добавления новых элементов), создается новый массив с удвоенным размером и копируются все элементы исходного массива. Все это происходит автоматически и прозрачно для программиста.

Учитывая, что в образце кода вы храните массив объектов (строки), разница в производительности будет незначительной, если вы используете ArrayList для их хранения, поэтому нет реальной причины изобретать колесо!

Ответ 3

Нет, это не допустимый способ сделать это. Фактически вы делаете

First create a new larger array
Throw away the newly created array and copy the original array
Create year another new array with larger size
Throw away the newly created array and clone the already cloned array again

Для не примитивных типов я думаю, вы хотите использовать ArrayList

Однако, если вы хотите построить это для примитивных типов, вот как вы это сделаете

public int size = 0;    
public int[] origArray = new int[size+1]; 

public void expand(){
    int[] tempArray = new int[size+1];    
    System.arrayCopy(origArray, 0, tempArray, 0, size);
    origArray = tempArray;
    size++;         
}

Вероятно, вы хотите скрыть данные позади accessors (методы get...()), и вы не хотите просто расширять массив по одному элементу за раз, создание и копирование массивов является дорогостоящим.

Ответ 4

Ваш метод не будет работать, потому что clone() просто переназначает массив в исходный размер. Я бы рекомендовал использовать

System.arraycopy(OrigArray, 0, tempArray, 0, OrigArray.length);

вместо.

Кроме того, наиболее эффективным способом сделать это будет использование ArrayList, поскольку они реализуют практически одно и то же, но часто очищают ваш код.

Единственная проблема заключается в том, когда вам нужно получить регулярный массив типа значения, тогда вам нужно будет сделать это:

String[] asArr = new String[OrigArray.length];

for(int i = 0; i < OrigArray.length; i++)
  asArr[i] = OrigArray.get(i);

Вот Javadoc для ArrayList:

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html

Ответ 5

Это:

OrigArray = new String[size+1];
OrigArray = (String[])tempArray.clone();

по существу эквивалентно только этому:

OrigArray = (String[])tempArray.clone();

тем, что второе присваивание полностью заменяет первое. OrigArray будет иметь тот же размер, что и tempArray, и, следовательно, тот же самый размер, который он изначально имел.

Если вы хотите скопировать элементы в существующий массив, вам нужно либо написать цикл, либо использовать java.lang.System.arrayCopy(...), который обрабатывает цикл для вас; но вызов clone() в массиве всегда будет создавать новый массив, поэтому не поможет.

Ответ 6

Взгляните на System.arraycopy - он копирует один массив в другой (вы также можете сделать это самостоятельно в цикле, хотя arraycopy немного быстрее). Таким образом, общий шаблон заключается в создании нового массива, который больше первого, затем скопируйте первые элементы в более крупный, а затем обновите поле/переменную, чтобы указать на этот новый массив большего размера.

Ответ 7

Постоянное построение и уничтожение объектов в памяти является дорогостоящим и медленным. Я бы написал класс, в котором хранится небольшое дополнительное пространство (возможно, 3-5 дополнительных элементов), подобно тому, как работает List, и когда запрос размера только выводит используемые пробелы и расширяется только при превышении этого буферного пространства. Это может значительно повысить производительность.