Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 系统的时间复杂性。阵列副本(…)?_Java_Algorithm_Time Complexity - Fatal编程技术网

Java 系统的时间复杂性。阵列副本(…)?

Java 系统的时间复杂性。阵列副本(…)?,java,algorithm,time-complexity,Java,Algorithm,Time Complexity,System.arraycopy(objectsrc,intsrcpos,objectdest,intdestpos,intlength)是一种本机方法 此方法的时间复杂度是多少?必须遍历数组中的所有元素才能执行此操作。数组是一种独特的数据结构,在初始化时必须指定大小。顺序是源数组的大小,或者用大O表示它的O(长度) 实际上,这在ArrayList内部发生。ArrayList包装一个数组。虽然ArrayList看起来像是一个动态增长的集合,但在内部,当它必须扩展时,它会执行arrycopy操作。

System.arraycopy(objectsrc,intsrcpos,objectdest,intdestpos,intlength)
是一种本机方法


此方法的时间复杂度是多少?

必须遍历数组中的所有元素才能执行此操作。数组是一种独特的数据结构,在初始化时必须指定大小。顺序是源数组的大小,或者用大O表示它的O(长度)


实际上,这在ArrayList内部发生。ArrayList包装一个数组。虽然ArrayList看起来像是一个动态增长的集合,但在内部,当它必须扩展时,它会执行arrycopy操作。

我做了一些调查,后来决定编写一个测试代码,下面是我得到的

我的测试代码如下所示:

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));
    }
  }

}

因此,Bragboy是正确的。

只是总结一下关于另一个问题的相关评论(标记为此问题的副本)

当然,它只是将 其他的?这将是O(n),其中n是要添加的值的数量

bragboy的回答当然同意,但我当时认为获得肯定答案的唯一方法是找到源代码以获得规范答案,但这是不可能的。下面是
System.arraycopy()的声明

它是
本机的
,用操作系统的语言编写,这意味着
arraycopy()
的实现取决于平台


因此,总而言之,它可能是O(n),但可能不是。

以下是来自OpenJDK 8的一些相关源代码(OpenJDK-8-src-b132-03_2014年3月)。我在的帮助下找到了它(注意:那里的说明很混乱;我只是在源代码中搜索相关的标识符)。我认为这是正确的;i、 例如,在(许多)情况下,不需要迭代每个元素。注意,不迭代每个元素并不一定意味着O(1),它只是意味着“更快”。我认为,不管怎样,数组副本基本上必须是O(x),即使x不是数组中的项数;i、 例如,不管你怎么做,数组中的元素越多,复制的成本就越高,如果你有一个非常大的数组,这将花费很长的时间。警告:我不确定这是否是您正在运行的Java的实际源代码;只是这是我在OpenJDK 8源代码中找到的唯一实现。我认为这是一个跨平台的实现,但我可能错了——我肯定还没有弄明白如何构建这段代码。另见:。以下内容来自:/openjdk/hotspot/src/share/vm/oops/objArrayKlass.cpp

// 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);
}
//oop或窄oop取决于UseCompressedOops。
模板void ObjArrayKlass::do_copy(数组操作s、T*src、,
阵列操作d、T*dst、整数长度、陷阱){
BarrierSet*bs=Universe::heap()->barrier_set();
//出于性能方面的原因,我们假设写入障碍
//正在为引用数组使用优化模式。至少一个
//如果情况并非如此,以下所有资产都将失败。
断言(bs->has_write_ref_array_opt(),“屏障集必须has ref array opt”);
断言(bs->has_write_ref_array_pre_opt(),“也用于预屏障”);
如果(s==d){
//因为源和目标是相等的,所以我们不需要进行转换检查。
断言(长度>0,“健全性检查”);
bs->write_ref_array_pre(dst,长度);
Copy::conjoint_oops_atomic(src、dst、length);
}否则{
//我们必须确保所有元素都符合目标数组
Klass*bound=ObjArrayKlass::cast(d->Klass())->element_Klass();
Klass*stype=ObjArrayKlass::cast(s->Klass())->element_Klass();
if(stype==bound | | stype->is_subtype_of(bound)){
//元素保证是子类型,因此无需进行检查
bs->write_ref_array_pre(dst,长度);
Copy::conjoint_oops_atomic(src、dst、length);
}否则{
//慢案例:需要单独的子类型检查
//注意:不要使用下面列出的obj_,因为它包含冗余存储检查
T*from=src;
T*end=from+length;
for(T*p=dst;fromklass())->是(绑定的)的子类型{
bs->write_ref_field_pre(p,new_val);
*p=*来自;
}否则{
//我们必须做一个屏障来覆盖部分副本。
const size_t pd=指针δ(p,dst,(size_t)heapOopSize);
//指针增量按元素数缩放(字段中的长度
//我们假设它是32位的。
断言(pd==(size_t)(int)pd,“长度字段溢出”);
bs->write_ref_数组((HeapWord*)dst,pd);
抛出(vmSymbols::java_lang_ArrayStoreException());
返回;
}
}
}
}
bs->write_ref_数组((HeapWord*)dst,长度);
}

我不明白科瑟的回答如何回答他自己的问题。我认为要检查算法的时间复杂度,必须比较不同大小输入的运行时间,如下所示:

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);
    }
  }

}

O(n)足够接近了,但实际上我认为它只是O(长度),即要复制的长度,而不是源数组的长度。@alex c-你能给出一个从int到string的转换示例吗?我认为arraycopy不会进行任何转换,也不会根据文档进行转换:
否则,如果以下任何一项为真,就会引发ArrayStoreException。。。°src参数指的是具有基本组件类型的数组,dest参数指的是具有参考组件类型的数组。…
响应不正确!system.arrayCopy是一种本地方法
// 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);
}
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