Ответ 1
Вы можете использовать System.arraycopy()
int[] src = new int[]{1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy( src, 0, dest, 0, src.length );
У меня есть массив, который постоянно обновляется. a
Скажем, a = [1,2,3,4,5]
. Мне нужно сделать точную копию a
и назвать его b
. Если a
изменить на [6,7,8,9,10]
, b
все равно должно быть [1,2,3,4,5]
. Каков наилучший способ сделать это? Я попытался for
цикла, как:
for(int i=0; i<5; i++) {
b[i]=a[i]
}
но это, кажется, не работает правильно. Пожалуйста, не используйте расширенные термины, такие как глубокий текст и т.д., Потому что я не знаю, что это значит.
Вы можете использовать System.arraycopy()
int[] src = new int[]{1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy( src, 0, dest, 0, src.length );
вы можете использовать
int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();
.
Если вы хотите сделать копию:
int[] a = {1,2,3,4,5};
Это путь:
int[] b = Arrays.copyOf(a, a.length);
Arrays.copyOf
может быть быстрее, чем a.clone()
на небольших массивах. Оба элемента копирования одинаково быстры, но clone() возвращает Object
, поэтому компилятор должен вставить неявный листинг в int[]
. Вы можете увидеть его в байт-коде, что-то вроде этого:
ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
Хорошее объяснение от http://www.journaldev.com/753/how-to-copy-arrays-in-java
Методы копирования массивов Java
Object.clone(): класс объекта предоставляет метод clone(), и поскольку массив в java также является объектом, вы можете использовать этот метод для достижения полного массив. Этот метод вам не подходит, если вы хотите получить частичную копию массив.
System.arraycopy(): класс системы arraycopy() - лучший способ сделать частичная копия массива. Это дает вам простой способ указать общее количество элементов для копирования и исходный и целевой массив индексные позиции. Например System.arraycopy(источник, 3, пункт назначения, 2, 5) скопирует 5 элементов из источника в пункт назначения, начиная с 3-й индекс источника для второго индекса места назначения.
Arrays.copyOf(): Если вы хотите скопировать первые несколько элементов массива или полная копия массива, вы можете использовать этот метод. Очевидно, что это не универсальный, как System.arraycopy(), но его также не путать и легко для использования.
Arrays.copyOfRange(). Если вы хотите, чтобы несколько элементов массива были скопирован, где начальный индекс не равен 0, вы можете использовать этот метод для копирования частичный массив.
У меня такое ощущение, что все эти "лучшие способы копирования массива" на самом деле не помогут решить вашу проблему.
Вы говорите
Я пробовал цикл for, подобный [...], но похоже, что он работает некорректно?
Глядя на этот цикл, там нет очевидной причины, чтобы он не работал... если:
a
и b
(например, a
и b
относятся к одному и тому же массиву) илиa
.В любом случае альтернативные способы выполнения копирования не решают основной проблемы.
Исправление для первого сценария очевидно. Для второго сценария вам нужно будет выяснить способ синхронизации потоков. Атомные массивы классов не помогают, потому что у них нет конструкторов атомной копии или методов клонирования, но синхронизация с использованием примитивного мьютекса сделает трюк.
(В вашем вопросе есть намеки, которые заставляют меня думать, что это действительно связанное с потоком, например, ваше утверждение, что a
постоянно меняется.)
Все решения, которые вызывают длину из массива, добавьте код избыточного нулевого элемента checkersconsider:
int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
//What if array a comes as local parameter? You need to use null check:
public void someMethod(int[] a) {
if (a!=null) {
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
}
}
Я рекомендую вам не изобретать колесо и использовать служебный класс, где все необходимые проверки уже выполнены. Рассмотрим ArrayUtils из сообщества apache. Вы становитесь короче:
public void someMethod(int[] a) {
int[] b = ArrayUtils.clone(a);
}
В Apache вы можете найти там
Вы также можете использовать Arrays.copyOfRange
.
Пример:
public static void main(String[] args) {
int[] a = {1,2,3};
int[] b = Arrays.copyOfRange(a, 0, a.length);
a[0] = 5;
System.out.println(Arrays.toString(a)); // [5,2,3]
System.out.println(Arrays.toString(b)); // [1,2,3]
}
Этот метод похож на Arrays.copyOf
, но он более гибкий. Оба используют System.arraycopy
под капотом.
См
Вы можете попробовать использовать Arrays.copyOf() в Java
int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
Если вы должны работать с необработанными массивами, а не ArrayList
, то Arrays
имеет то, что вам нужно. Если вы посмотрите на исходный код, это абсолютно лучшие способы получить копию массива. У них действительно есть хорошее защитное программирование, потому что метод System.arraycopy()
выдает множество исключенных исключений, если вы кормите его нелогичными параметрами.
Вы можете использовать Arrays.copyOf()
, который скопирует из первого в Nth
элемент в новый более короткий массив.
public static <T> T[] copyOf(T[] original, int newLength)
Копирует указанный массив, обрезает или заполняет нулями (если необходимо), поэтому копия имеет указанную длину. Для всех индексов, которые действительны как в исходном массиве, так и в копии, два массива будут содержат одинаковые значения. Для любых индексов, которые действительны в копии но не оригинал, копия будет содержать нуль. Такие индексы будут существуют тогда и только тогда, когда указанная длина больше, чем указанная оригинальный массив. Полученный массив имеет тот же класс, что и исходный массив.
2770
2771 public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772 T[] copy = ((Object)newType == (Object)Object[].class)
2773 ? (T[]) new Object[newLength]
2774 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775 System.arraycopy(original, 0, copy, 0,
2776 Math.min(original.length, newLength));
2777 return copy;
2778 }
или Arrays.copyOfRange()
также выполнит трюк:
public static <T> T[] copyOfRange(T[] original, int from, int to)
Копирует указанный диапазон указанного массива в новый массив. Начальный индекс диапазона (from) должен лежать между нулем и original.length, включительно. Значение в оригинале [из] помещается в исходный элемент копии (если только из == original.length или от == до). Значения от последующих элементов в исходном массиве помещенный в последующие элементы в копии. Окончательный индекс диапазон (to), который должен быть больше или равен, может быть больше, чем original.length, и в этом случае нуль помещается во все элементы копии, индекс которых больше или равен оригинальный .l длина - из. Длина возвращаемого массива будет равна - из. Получившийся массив имеет тот же класс, что и исходный массив.
3035 public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036 int newLength = to - from;
3037 if (newLength < 0)
3038 throw new IllegalArgumentException(from + " > " + to);
3039 T[] copy = ((Object)newType == (Object)Object[].class)
3040 ? (T[]) new Object[newLength]
3041 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042 System.arraycopy(original, from, copy, 0,
3043 Math.min(original.length - from, newLength));
3044 return copy;
3045 }
Как вы можете видеть, обе эти функции являются только оболочными функциями над System.arraycopy
с защитной логикой, что то, что вы пытаетесь сделать, действительно.
System.arraycopy
является самым быстрым способом копирования массивов.
Для нуль-безопасной копии массива вы также можете использовать опцию с методом Object.clone()
, представленным в этом .
int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);