Как я могу сделать массив с изменяемым размером в Java? - PullRequest
12 голосов
/ 06 апреля 2010

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

Ответы [ 10 ]

23 голосов
/ 06 апреля 2010

В качестве альтернативы вы можете использовать ArrayList . Это реализация массива изменяемого размера интерфейса List.

Использование (с использованием строки):

List<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("c");
myList.add("b");

Порядок будет таким же, как вы положили их в: а, с, б.

Вы также можете получить отдельный предмет, подобный этому:

String myString = myList.get(0);

Что даст вам 0-й элемент: "a".

4 голосов
/ 06 апреля 2010

Как Санджо указал: «An array is a static datastructure, so they can't grow». Интерфейс списка может поддерживаться массивом (например, ArrayList , как Кевин указал в своем сообщении ). Когда структура списка заполнена и новый элемент должен быть добавлен в список. Затем структура сначала создает новый массив, который может содержать старые элементы плюс новый элемент, который должен быть добавлен в список.

Интерфейс списка имеет различные реализации, которые имеют свои плюсы и минусы, и вы должны выбрать тот, который наилучшим образом решит ваш набор задач. Ниже я попытаюсь дать краткое резюме, когда использовать какую реализацию:

Не поточно-ориентированные реализации:

  • ArrayList : реализация массива изменяемого размера интерфейса List. Вы должны использовать эту реализацию, когда вы выполняете много операций size, isEmpty, get, set, iterator, and listIterator, выполняемых в постоянное время. Операция add выполняется за амортизированное постоянное время, то есть добавление n элементов требует времени O (n). Я думаю, что вы должны использовать эту реализацию при выполнении большего количества поисков (get()), а затем при добавлении элементов в список (add()).
  • LinkedList : эта реализация не резервируется массивом, а «связывает» узлы вместе. На мой взгляд, вы должны использовать эту реализацию, когда вы делаете больше add(), чем get().

Потокобезопасные реализации:

Имейте в виду, что эти реализации списка не являются поточными -безопасными, что означает, что можно получить условия гонки при доступе к ним из нескольких потоков. Если вы хотите использовать реализации List из нескольких потоков, я бы посоветовал вам изучить пакет java.util.concurrent и использовать реализацию из этого класса.

3 голосов
/ 06 апреля 2010

Вы, вероятно, должны использовать ArrayList вместо Vector по причинам, объясненным в других ответах.

Однако ...

Я пытался использовать Vector, но это сдвигает все элементы, когда вы делаете вставку, и мне нужен массив, который может расти, но элементы остаются на месте.

Когда вы делаете insertElementAt(pos, elem), у вас специально запрашивается смещение элемента. Если вы не хотите, чтобы элементы были смещены, вы должны использовать set(pos, elem). Или, если вы хотите добавить элемент в конце вектора, вы также можете использовать add(elem).

Между прочим, предыдущий абзац применяется ко всем реализациям List, а не только к Vector, хотя детали реализации и производительность варьируются в зависимости от различных типов List.

3 голосов
/ 06 апреля 2010
2 голосов
/ 06 апреля 2010

Проверить ArrayList

1 голос
/ 11 декабря 2013

ArrayList и LinkedList

Сложность пространства:

а) ArrayList: Выделяет часть памяти при инициализации и удваивается каждый раз, когда достигает максимального размера при каждом динамическом добавлении элемента.

б) LinkedList: Он выделяет память только каждый раз, когда вы добавляете элемент в список.

Сложность выполнения:

а) ArrayList: Поиск быстрее, вставка и удаление медленнее по сравнению со связанным списком

б) LinkedList: Вставка и удаление быстрее, поиск медленнее по сравнению со списком массивов

1 голос
/ 06 апреля 2010

Если вы хотите управлять данными массива после того, как все элементы уже вставлены или удалены, есть способ, который пытается создать LinkedList или ArrayList, просто изменив размер, после завершения ввода данных вы можете передать ArrayList Array, затем делайте все, что вы обычно делаете с Array.

1 голос
/ 06 апреля 2010

Я пытался использовать Vector, но это сдвигает все элементы, когда вы делаете вставку, и мне нужен массив, который может расти, но элементы остаются на месте.

Вы, вероятно, хотите использовать ArrayList вместо Vector.

Они оба предоставляют примерно один и тот же интерфейс, и вы можете заменить элементы на них обоих, вызвав set(idx, element). Это не делает никакого перемещения вокруг. Это также не позволяет вам увеличивать массив, хотя: вы можете вставлять только в уже занятые позиции (не выходящие за текущий размер массива), чтобы добавить новые элементы в конце, вы должны использовать add(element).

Разница между ArrayList и Vector заключается в том, что Vector имеет код синхронизации, который вам, скорее всего, не нужен, что делает ArrayList немного быстрее.

0 голосов
/ 07 ноября 2012

Используйте ArrayList или LinkedList.

0 голосов
/ 06 апреля 2010

Использование замечательных классов в среде Collections лучше, чем использование массивов. Но если ваш вопрос с точки зрения «викторины», вот что вы должны сделать. Создайте свой собственный метод изменения размера, например:

  int[] oldArray = {1,2,3};

  int oldSize = java.lang.reflect.Array.getLength(oldArray);
  Class elementType = oldArray.getClass().getComponentType();
  Object newArray = java.lang.reflect.Array.newInstance(
         elementType,newSize);
  int preserveLength = Math.min(oldSize,newSize);
  if (preserveLength > 0)
      System.arraycopy (oldArray,0,newArray,0,preserveLength);

  oldArray = newArray;
...