Что более эффективно: система.arraycopy против массивов.копия?
метод toArray в ArrayList, Bloch использует обе системы.arraycopy и массивы.копия, чтобы скопировать массив .
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
Как сравнить эти два метода копирования , когда какую использовать?
8 ответов:
разница в том, что
Arrays.copyOfне только копирует элементы, но и создает новый массив.System.arrayCopyкопирует в существующий массив.вот источник для
Arrays.copyOf, Как вы можете видеть, он используетSystem.arraycopyвнутренне, чтобы заполнить новый массив.public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
пока
System.arraycopyреализуется изначально, и поэтому может быть1 быстрее, чем цикл Java, это не всегда так быстро, как вы могли бы ожидать. Рассмотрим следующий пример:Object[] foo = new Object[]{...}; String[] bar = new String[foo.length]; System.arraycopy(foo, 0, bar, 0, bar.length);в этом случае базовый тип
fooиbarмассивы имеют разные базовые типы, поэтому реализацияarraycopyдолжен проверить тип каждой скопированной ссылки, чтобы убедиться, что это на самом деле ссылка на экземпляр строки. Это значительно медленнее, что простая c-образная memcopy содержимого массива.другой момент заключается в том, что
Arrays.copyOfиспользуетSystem.arraycopyпод капотом, поэтому экономия достигается путем создания нового массива и заполнения его самостоятельно с помощьюarraycopyбудет минимальным. Предполагаю, что это то, что вы пытаетесь сделать ...мой совет был бы использовать версию, которая делает ваш код легче читать, и только беспокоиться о том, какой из них быстрее, если профилирования говорит вам, что это вопросы.
1 - это может быть быстрее, но это и возможно что JIT-компилятор делает такую хорошую работу по оптимизации цикла ручного кода, что нет никакой разницы.
если вы хотите точно копия массива (скажем, если вы хотите сделать защитную копию), наиболее эффективным способом копирования массива, вероятно, является использование объекта массива
clone()способ:class C { private int[] arr; public C(int[] values){ this.arr = values.clone(); } }Я не потрудился проверить его производительность, но у него есть хороший шанс быть довольно быстрым, так как все это родное (выделение и копирование в вызове), а клонирование-это особый благословенный способ копирования объектов JVM (и это в основном зло для других целей) и вероятно, вы сможете взять некоторые "ярлыки".
лично я бы все-таки использовать
cloneесли он был медленнее, чем любой другой способ копирования, потому что это легче читать и почти невозможно испортить при написании.System.arrayCopy, С другой стороны...
вы смотрели на реализацию солнечных массивов.копия()?
public static int[] copyOf(int[] original, int newLength) { int[] copy = new int[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }Как видно, он использует
System.arraycopy()внутренне, так что производительность будет такой же.
System.arrayCopyреализуется изначально, и, следовательно, будет быстрее, чем любой код Java. Я рекомендую вам использовать его.
class ArrayCopyDemo { public static void main(String[] args) { char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' }; char[] copyTo = new char[7]; System.arraycopy(copyFrom, 2, copyTo, 0, 7); System.out.println(new String(copyTo)); } }
вместо обсуждения, это фактические результаты. Очевидно, ваш выбор будет зависеть от того, сколько данных вы хотите скопировать.
byte [] copy performance test
10,000,000 итераций 40b матрица.copyOfRange: 135ms системный.arraycopy: 141ms
10,000,000 итераций 1000b матрица.copyOfRange: 1861ms системный.arraycopy: 2211ms
10,000,000 итераций 4000b матрица.copyOfRange: 6315ms системный.arraycopy: 5251ms
1,000,000 итерации 100,000 b матрица.copyOfRange: 15,198 ms системный.arraycopy: 14783ms
Comments