Незважаючи на те 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
повинна перевірити тип кожного скопійованого посилання, щоб переконатися, що це насправді посилання на екземпляр String. Це значно повільніше, ніж простий C-стиль memcopy
вмісту масиву.
Інший момент - Arrays.copyOf
використання System.arraycopy
під капотом. Тому System.arraycopy
це на обличчі його не повинно бути менше 2 , ніж Arrays.copyOf
. Але ви можете бачити (з наведеного вище коду ), що Arrays.copyOf
в деяких випадках використовуватиме відображення для створення нового масиву. Тож порівняння продуктивності не є простим.
У цьому аналізі є кілька недоліків.
Ми розглядаємо код реалізації з конкретної версії Java. Ці методи можуть змінюватися, скасовуючи попередні припущення щодо ефективності.
Ми ігноруємо можливість того, що компілятор JIT міг би виконати розумну оптимізацію особливих випадків для цих методів. І, мабуть, це трапляється з Arrays.copyOf
; див. Чому Arrays.copyOf в 2 рази швидше, ніж System.arraycopy для малих масивів? . Цей метод є "властивим" у реалізаціях Java поточного покоління, що означає, що компілятор JIT буде ігнорувати те, що міститься у вихідному коді Java!
Але в будь-якому випадку, різниця між двома версіями є O(1)
(тобто не залежить від розміру масиву) і відносно невелика. Тому моєю порадою буде використовувати версію, яка полегшує читання вашого коду, і турбуватися про те, яка з них швидша, лише якщо профілювання говорить вам, що це важливо.
1 - Це може бути швидше, але також можливо, що компілятор JIT робить настільки гарну роботу з оптимізації ручно закодованого циклу, що різниці немає.