System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
是一个本地方法。
这个方法的时间复杂度是多少?
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
是一个本地方法。
这个方法的时间复杂度是多少?
要完成这个操作,必须遍历数组中的所有元素。 数组是一种特殊的数据结构,在初始化时必须指定大小。在大O表示法中,其顺序将是源数组的大小或O(length)。
实际上,在ArrayList中会内部执行此操作。 ArrayList包装了一个数组。虽然ArrayList看起来像是一个动态增长的集合,但是在内部当它需要扩展时,它执行的是arraycopy操作。
否则,如果以下任一条件成立,则抛出ArrayStoreException…°src参数是具有原始组件类型的数组,而dest参数是具有引用组件类型的数组 °...
- user85421我进行了一些调查后,决定编写测试代码,以下是我的代码。
我的测试代码如下:
import org.junit.Test;
public class ArrayCopyTest {
@Test
public void testCopy() {
for (int count = 0; count < 3; count++) {
int size = 0x00ffffff;
long start, end;
Integer[] integers = new Integer[size];
Integer[] loopCopy = new Integer[size];
Integer[] systemCopy = new Integer[size];
for (int i = 0; i < size; i++) {
integers[i] = i;
}
start = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
loopCopy[i] = integers[i];
}
end = System.currentTimeMillis();
System.out.println("for loop: " + (end - start));
start = System.currentTimeMillis();
System.arraycopy(integers, 0, systemCopy, 0, size);
end = System.currentTimeMillis();
System.out.println("System.arrayCopy: " + (end - start));
}
}
}
for loop: 47
System.arrayCopy: 24
for loop: 31
System.arrayCopy: 22
for loop: 36
System.arrayCopy: 22
arraycopy()
的实现可能会依赖于平台。 - Rudi KershawO(?)
是什么呢?显然我的性能分析并不完美;-)我很想知道。深入挖掘JDK源代码可能会有帮助。你有什么想法吗? - Kowser// Either oop or narrowOop depending on UseCompressedOops.
template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src,
arrayOop d, T* dst, int length, TRAPS) {
BarrierSet* bs = Universe::heap()->barrier_set();
// For performance reasons, we assume we are that the write barrier we
// are using has optimized modes for arrays of references. At least one
// of the asserts below will fail if this is not the case.
assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
if (s == d) {
// since source and destination are equal we do not need conversion checks.
assert(length > 0, "sanity check");
bs->write_ref_array_pre(dst, length);
Copy::conjoint_oops_atomic(src, dst, length);
} else {
// We have to make sure all elements conform to the destination array
Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass();
Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass();
if (stype == bound || stype->is_subtype_of(bound)) {
// elements are guaranteed to be subtypes, so no check necessary
bs->write_ref_array_pre(dst, length);
Copy::conjoint_oops_atomic(src, dst, length);
} else {
// slow case: need individual subtype checks
// note: don't use obj_at_put below because it includes a redundant store check
T* from = src;
T* end = from + length;
for (T* p = dst; from < end; from++, p++) {
// XXX this is going to be slow.
T element = *from;
// even slower now
bool element_is_null = oopDesc::is_null(element);
oop new_val = element_is_null ? oop(NULL)
: oopDesc::decode_heap_oop_not_null(element);
if (element_is_null ||
(new_val->klass())->is_subtype_of(bound)) {
bs->write_ref_field_pre(p, new_val);
*p = *from;
} else {
// We must do a barrier to cover the partial copy.
const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);
// pointer delta is scaled to number of elements (length field in
// objArrayOop) which we assume is 32 bit.
assert(pd == (size_t)(int)pd, "length field overflow");
bs->write_ref_array((HeapWord*)dst, pd);
THROW(vmSymbols::java_lang_ArrayStoreException());
return;
}
}
}
}
bs->write_ref_array((HeapWord*)dst, length);
}
总结另一个问题的相关评论(标记为本问题的重复)。
当然,只需将所有条目添加到新数组中即可。 这将是O(n),其中n 是要添加的值的数量。
bragboy的答案当然也同意,但我曾经认为获得确定答案的唯一方法是找到源代码以获得规范答案,但这是不可能的。 这里是System.arraycopy()
的声明。
public static native void arraycopy(Object src, int src_position,
Object dst, int dst_position,
int length);
这段代码是使用操作系统的语言编写的 native
,这意味着 arraycopy()
的实现取决于平台。
因此,总的来说时间复杂度可能是 O(n),但也有可能不是。
我不明白Kowser的回答如何回答他自己的问题。我认为要检查算法的时间复杂度,你需要比较不同大小的输入所需的运行时间,就像这样:
import org.junit.Test;
public class ArrayCopyTest {
@Test
public void testCopy() {
int size = 5000000;
for (int count = 0; count < 5; count++) {
size = size * 2;
long start, end;
Integer[] integers = new Integer[size];
Integer[] systemCopy = new Integer[size];
start = System.currentTimeMillis();
System.arraycopy(integers, 0, systemCopy, 0, size);
end = System.currentTimeMillis();
System.out.println(end - start);
}
}
}
输出:
10
22
42
87
147