c++ new 数组里有几个元素

2019-03-08 14:50:33 brahmsjiang 阅读数 4332

如果一个类有默认的构造函数,使用new动态实例化一个对象数组不是件难事,如下代码:

class animal
{
public:
    animal():num(0)
    {}
    ~animal()
    {}
private:
    int num;
};

Animal *ani = new Animal[5];
delete[]ani;

然而 new Obj[n]的形式仅仅适用于不需传入实参的默认构造函数,否则编译器报错。想要初始化对象数组的同时指定各个构造函数的参数,有以下几种解决途径:

1.若初始化对象数组时已知其size,使用诸如 new Obj[n]{(),(),...()} 的形式,大括号内每个小括号对应每个对象的构造函数参数:

class Array1D
{
public:
	Array1D(int len2)
		:len2D(len2)
	{
		plist = new T[len2];
		for (int i = 0; i < len2; i++)
			plist[i] = static_cast<T>(0);
	}
	~Array1D()
	{
		if (nullptr != plist)
			delete[] plist;
	}
private:
	T* plist;
	int len2D;
};

pArray1D = new Array1D[2]{(1),(2)}

 

2.若初始化对象数组时未知其size,需要把分配内存和构建对象的动作分开。可借助C++11的allocator。先使用allocate分配内存并用指针记录这块空间;然后用construct方法对指针所指向内存进行对象构建;当然不再使用对象时用destory方法析构对象;注意,既然分配内存和构建对象动作已分开,那么析构对象和释放内存也要配对,用deallocate释放内存:

class Array2D
{
public:
    //class Array1D
    class Array1D
    {...};

    //Array2D
    Array2D(int len1, int len2)
        :len1D(len1)
    {
        pArray1D = alloc.allocate(len1);
        for (int i = 0; i < len1; i++) {
            alloc.construct(pArray1D + i, len2);
        }
    }
    ~Array2D()
    {
        for (int i = 0; i < len1D; i++) {
            alloc.destroy(pArray1D + i);
        }
        alloc.deallocate(pArray1D, len1D);
    }

private:
    Array1D* pArray1D;
    int len1D;
    allocator<Array1D> alloc;
};

 

3.使用operator new和placement new,与allocator原理类似,分四步走:

class animal
{
public:
    animal():num(0)
	{}
    animal(int _num):num(_num)
    {}
    ~animal()
    {}

    void show() {
        cout << num << endl;
    }

    void* operator new(size_t size, void* p)
    {
        return p;
    }
private:
    int num;
};

int main(int argc, char* argv[])
{
    {
        // operator new
        void* p = operator new(5 * sizeof(animal));
        animal* a = static_cast<animal*>(p);
        // placement new, constructor
        for (int i = 0; i < 4; i++)
        {
            new(a + i) animal(i);
        }
        new(a + 4) animal;
        // use
        for (int i = 0; i < 5; i++) {
            (a + i)->show();
        }
        // destructor
        for (int i = 0; i < 5; i++) {
            (a + i)->~animal();
        }
        // delete
        delete[] p;
    }
    return 0;
}

参考:https://www.cnblogs.com/SimonKly/p/7819147.html

2018-03-20 21:44:21 csdn_chuxuezhe 阅读数 7143

1、使用动态内存分配方法

c++申请动态内存:

int arraySize; //定义元素个数

cin>>arraySize; //输入元素个数

int *p; //指针指向一个数组

p =  new int[arraySize]; //动态分配内存

...

delete []p; //最后释放内存空间

c语言申请动态内存:

int arraySize; //定义元素个数

scanf("%d",&arraySize);//输入元素个数

int *p; //指针指向一个数组

p =  (int *)malloc(arraySize *sizeof(int)) //动态分配内存

...

free(p); //最后释放内存空间

2、使用向量vector

Vector是C++STL中提供的向量

向量的大小可以动态改变

向量可以通过下标访问元素

可以通过push_back向向量中添加元素并改变大小

#include <vector>

vector <int> myArray;

//可以根据数据需求用 myArray.push_back(整数);来添加元素
//可以通过下标访问向量元素


2018-04-15 16:49:15 jpzhu16 阅读数 15051

C++中数组作为函数参数或者返回值



概述


在编程任务中,经常会遇到将数组作为函数参数或者返回值,比如在前一篇的计数排序任务中,需要额外的空间来保存排序后的元素,并且将该数组返回给主函数。本文会介绍几种可行的方案,仅供参考。

数组作为函数参数


数组作为函数函数,在Java中,通过传递数据名即可获取到数组的信息,但是在C++中,这种操作行不通,如下:

#include <iostream>
using namespace std;
int sum(int arr[]){
    int length = sizeof(arr)/sizeof(arr[0]);
    int sum = 0;
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}
int main(){
    int arr[] = {1,3,5,7,9};
    int summary = sum(arr);
    cout << summary << endl;
}

执行上述代码后发现,结果不正确,这是为什么?看下面代码:

#include <iostream>
using namespace std;
int sum(int* arr){
    int length = sizeof(arr)/sizeof(arr[0]);
    int sum = 0;
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}
int main(){
    int arr[] = {1,3,5,7,9};
    int summary = sum(arr);
    cout << summary << endl;
}

对比这两个程序,我们发现,执行结果一直,说明两个问题,首先,数组名是数组的首地址,它被传递了,其次,sum函数内部,并未获取到正确的数组长度。因此,对于数组作为函数参数的情形,我们看采用下面代码:

#include <iostream>
using namespace std;
int sum(int* arr,int length){
    int sum = 0;
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}
int main(){
    int arr[] = {1,3,5,7,9};
    int summary = sum(arr,5);
    cout << summary << endl;
}

C++11给出的替代方案,实际上该方案仍然使用模板参数传递了数组的长度,所以该参数必须要传入。并且编译器请选择:Having g++ following the coming C++0x ISO C++ language standard [-std=c++0x]

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int sum(array<int,SIZE> arr){
    int sum = 0;
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};
    int summary = sum(arr);
    cout << summary << endl;
}

数组作为函数返回值


数组作为函数返回值的情况更加复杂,传统的写法容易造成产生悬挂指针,造成空间浪费。看下面代码:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int* sum(array<int,SIZE> arr){
    int length = arr.size();
    int* returnArr = new int[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    int* summary = sum(arr);
    for (int i = 0 ; i < arr.size(); i++){
        cout << summary[i] << " ";
    }
    delete[] summary;
    return 0;
}

可替代代码:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int* sum(array<int,SIZE> arr){
    int length = arr.size();
    static int returnArr[SIZE];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    int* summary = sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << summary[i] << " ";
    }
    return 0;
}

下面两段代码都是错误的,因为函数在返回后退出时,局部变量returnArr已经被删除,因此返回的结果是错误的,代码如下:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int* sum(array<int,SIZE> arr){
    int length = arr.size();
    int returnArr[SIZE];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    int* summary = sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << summary[i] << " ";
    }
    return 0;
}
#include <iostream>
using namespace std;
int* sum(int* arr,int length){
    int returnArr[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    int arr[] = {1,3,5,7,9};
    int length = sizeof(arr)/sizeof(arr[0]);
    int* summary = sum(arr,length);
    for (int i = 0 ; i < length; i++){
        cout << summary[i] << " ";
    }
}

下面代码在int returnArr[length]前增加了static,这保证了数组在返回后没有被删除,但是此时报错:|error: storage size of ‘returnArr’ isn’t constant|

#include <iostream>
using namespace std;
int* sum(int* arr,int length){
    static int returnArr[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    int arr[] = {1,3,5,7,9};
    int length = sizeof(arr)/sizeof(arr[0]);
    int* summary = sum(arr,length);
    for (int i = 0 ; i < length; i++){
        cout << summary[i] << " ";
    }
}

下面的代码能够解决上述问题:

#include <iostream>
using namespace std;
int* sum(int* arr,int length){
    int* returnArr = new int[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    int arr[] = {1,3,5,7,9};
    int length = sizeof(arr)/sizeof(arr[0]);
    int* summary = sum(arr,length);
    for (int i = 0 ; i < length; i++){
        cout << summary[i] << " ";
    }
    delete[] summary;
    return 0;
}

其它可行方案


在刘汝佳的《算法竞赛入门经典》教材中指出,当需要返回数组时,可以将将需要返回的数组提前作为参数传递进来,最后通过获取该数组的内容来获取其内容,这是可行的,但是该参数必要要使用引用的形式传递,否则会造成错误,代码如下:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE> arr,array<int,SIZE>& returnArr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    array<int,5> returnArr;
    sum(arr,returnArr);
    for (unsigned int i = 0 ; i < returnArr.size(); i++){
        cout << returnArr[i] << " ";
    }
    return 0;
}

错误代码如下,returnArr在传递时没有以引用形式传递:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE> arr,array<int,SIZE> returnArr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    array<int,5> returnArr;
    sum(arr,returnArr);
    for (unsigned int i = 0 ; i < returnArr.size(); i++){
        cout << returnArr[i] << " ";
    }
    return 0;
}

从上面的代码中,我们可以看到,std::array在出传递过程中,是以值方式传递,因此,想要在函数内部改变它,并且将结果返回给主调函数,必须用引用方式传值:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE> arr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        arr[i] = 0;
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    return 0;
}
//输出结果为: 1 3 5 7 9

如果改成引用传值:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE>& arr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        arr[i] = 0;
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    return 0;
}
//输出结果: 0 0 0 0 0

总结


数组作为函数参数或函数返回值,如何将数组的长度返回决定了函数执行正确与否,本文给出了合适的替换方案,并且给出了示例代码,需要指出,我们应该重视C++ 11中引入的array的使用。最后,如果数组常长度不确定,建议采用vector,这在C++ 11中被认为是可变长度的数组。

  • 在std::array中,由于使用了template参数,使得在编译时获取到数组的长度,因此加static关键字即可返回正确的数组内容
  • 在传统的语法中,只能在堆区分配空间才能解决数组作为参数返回问题,但是要注意释放指针空间,否则会造成悬挂指针。
  • 如果长度不确定,可以考虑vector作为替代
  • std::array采用按值传递方式,如果想要改变其值,需要采用引用方式传值

参考资料


  1. std::array http://en.cppreference.com/w/cpp/container/array
  2. 我的github: https://github.com/JunpengCode?tab=repositories
2018-06-12 21:27:36 u013407012 阅读数 29585

C++ 中的创建和删除数组(new/delete 和 new[]/delete[])

已有 4122 次阅读 2017-4-17 16:33|个人分类:C++|系统分类:科研笔记|关键词:C++,数组,动态数组|数组, 动态数组

在 C++ 中,我们也许经常使用需要建立数组和释放内存的问题,在动态分配内存的时候一般有两种方式,一个是malloc和new两种形式。

比如使用malloc的时候,一般形式如下:


har *Ptr = NULL;
Ptr = (char *)malloc(100 * sizeof(char));
if (NULL == Ptr)
{
exit (1);
}
gets(Ptr);
free(Ptr);

在使用new的时候,一般的形式如下:

1. 删除单变量地址空间

      int *a = new int;

      delete a;   //释放单个int的空间

2. 删除数组空间

      int *a = new int[5];

      delete []a;    //释放int数组空间


new 和 delete 来动态申请和释放内存,但你可曾想过以下问题呢?
   new 和 delete 是函数吗?
   new [] 和 delete [] 又是什么?什么时候用它们?
   你知道 operator new 和 operator delete 吗?
   为什么 new [] 出来的数组有时可以用 delete 释放有时又不行?
如果你对这些问题都有疑问的话,不妨看看我这篇文章。
new 和 delete 到底是什么?
如果找工作的同学看一些面试的书,我相信都会遇到这样的题:sizeof 不是函数,然后举出一堆的理由来证明 sizeof 不是函数。在这里,和 sizeof 类似,new 和 delete 也不是函数,它们都是 C++ 定义的关键字,通过特定的语法可以组成表达式。和 sizeof 不同的是,sizeof 在编译时候就可以确定其返回值,new 和 delete 背后的机制则比较复杂。
继续往下之前,请你想想你认为 new 应该要做些什么?也许你第一反应是,new 不就和 C 语言中的 malloc 函数一样嘛,就用来动态申请空间的。你答对了一半,看看下面语句:

string *ps = new string("hello world");

你就可以看出 new 和 malloc 还是有点不同的,malloc 申请完空间之后不会对内存进行必要的初始化,而 new 可以。所以 new expression 背后要做的事情不是你想象的那么简单。在我用实例来解释 new 背后的机制之前,你需要知道 operator new 和 operator delete 是什么玩意。
operator new 和 operator delete

这两个其实是 C++ 语言标准库的库函数,原型分别如下:

void *operator new(size_t);     //allocate an object
void *operator delete(void *);    //free an object
void *operator new[](size_t);     //allocate an array
void *operator delete[](void *);    //free an array

后面两个你可以先不看,后面再介绍。前面两个均是 C++ 标准库函数,你可能会觉得这是函数吗?请不要怀疑,这就是函数!C++ Primer 一书上说这不是重载 new 和 delete 表达式(如 operator= 就是重载 = 操作符),因为 new 和 delete 是不允许重载的。但我还没搞清楚为什么要用 operator new 和 operator delete 来命名,比较费解。我们只要知道它们的意思就可以了,这两个函数和 C 语言中的 malloc 和 free 函数有点像了,都是用来申请和释放内存的,并且 operator new 申请内存之后不对内存进行初始化,直接返回申请内存的指针。

我们可以直接在我们的程序中使用这几个函数。
new 和 delete 背后机制

知道上面两个函数之后,我们用一个实例来解释 new 和 delete 背后的机制:
我们不用简单的 C++ 内置类型来举例,使用复杂一点的类类型,定义一个类 A:

class A
{
public:
   A(int v) : var(v)
   {
       fopen_s(&file, "test", "r");
   }
   ~A()
   {
       fclose(file);
   }

private:
   int var;
   FILE *file;
};

很简单,类 A 中有两个私有成员,有一个构造函数和一个析构函数,构造函数中初始化私有变量 var 以及打开一个文件,析构函数关闭打开的文件。

我们使用

class *pA = new A(10);

来创建一个类的对象,返回其指针 pA。如下图所示 new 背后完成的工作:
https://github-camo.global.ssl.fastly.net/48182649501319d27121ede912b19be491b1b0a2/687474703a2f2f692e696d6775722e636f6d2f454a736e6b4a342e6a7067
简单总结一下:
   首先需要调用上面提到的 operator new 标准库函数,传入的参数为 class A 的大小,这里为 8 个字节,至于为什么是 8 个字节,你可以看看《深入 C++ 对象模型》一书,这里不做多解释。这样函数返回的是分配内存的起始地址,这里假设是 0x007da290。
   上面分配的内存是未初始化的,也是未类型化的,第二步就在这一块原始的内存上对类对象进行初始化,调用的是相应的构造函数,这里是调用 A:A(10); 这个函数,从图中也可以看到对这块申请的内存进行了初始化,var=10, file 指向打开的文件。
   最后一步就是返回新分配并构造好的对象的指针,这里 pA 就指向 0x007da290 这块内存,pA 的类型为类 A 对象的指针。
所有这三步,你都可以通过反汇编找到相应的汇编代码,在这里我就不列出了。
好了,那么 delete 都干了什么呢?还是接着上面的例子,如果这时想释放掉申请的类的对象怎么办?当然我们可以使用下面的语句来完成:

delete pA;

delete 所做的事情如下图所示:
https://github-camo.global.ssl.fastly.net/8bfb4701b5c270dc3b27c86bce57f2d31562d82f/687474703a2f2f692e696d6775722e636f6d2f3156767239467a2e6a7067
delete 就做了两件事情:
   调用 pA 指向对象的析构函数,对打开的文件进行关闭。
   通过上面提到的标准库函数 operator delete 来释放该对象的内存,传入函数的参数为 pA 的值,也就是 0x007d290。
好了,解释完了 new 和 delete 背后所做的事情了,是不是觉得也很简单?不就多了一个构造函数和析构函数的调用嘛。
如何申请和释放一个数组?
我们经常要用到动态分配一个数组,也许是这样的:

string *psa = new string[10];      //array of 10 empty strings
int *pia = new int[10];           //array of 10 uninitialized ints

上面在申请一个数组时都用到了 new [] 这个表达式来完成,按照我们上面讲到的 new 和 delete 知识,第一个数组是 string 类型,分配了保存对象的内存空间之后,将调用 string 类型的默认构造函数依次初始化数组中每个元素;第二个是申请具有内置类型的数组,分配了存储 10 个 int 对象的内存空间,但并没有初始化。
如果我们想释放空间了,可以用下面两条语句:

delete [] psa;
delete [] pia;

都用到 delete [] 表达式,注意这地方的 [] 一般情况下不能漏掉!我们也可以想象这两个语句分别干了什么:第一个对 10 个 string 对象分别调用析构函数,然后再释放掉为对象分配的所有内存空间;第二个因为是内置类型不存在析构函数,直接释放为 10 个 int 型分配的所有内存空间。
这里对于第一种情况就有一个问题了:我们如何知道 psa 指向对象的数组的大小?怎么知道调用几次析构函数?
这个问题直接导致我们需要在 new [] 一个对象数组时,需要保存数组的维度,C++ 的做法是在分配数组空间时多分配了 4 个字节的大小,专门保存数组的大小,在 delete [] 时就可以取出这个保存的数,就知道了需要调用析构函数多少次了。
还是用图来说明比较清楚,我们定义了一个类 A,但不具体描述类的内容,这个类中有显示的构造函数、析构函数等。那么 当我们调用

class A *pAa = new A[3];

时需要做的事情如下:
https://github-camo.global.ssl.fastly.net/1a2da83d54ac0110f8cdb13a6645dd5f9240e760/687474703a2f2f692e696d6775722e636f6d2f366857304431702e6a7067
从这个图中我们可以看到申请时在数组对象的上面还多分配了 4 个字节用来保存数组的大小,但是最终返回的是对象数组的指针,而不是所有分配空间的起始地址。
这样的话,释放就很简单了:

delete [] pAa;
https://github-camo.global.ssl.fastly.net/db76cce60aaa6f0ad3ab65cd00b0ca26a5271547/687474703a2f2f692e696d6775722e636f6d2f3155425444316c2e6a7067
这里要注意的两点是:
   调用析构函数的次数是从数组对象指针前面的 4 个字节中取出;
传入 operator delete[] 函数的参数不是数组对象的指针 pAa,而是 pAa 的值减 4。
为什么 new/delete 、new []/delete[] 要配对使用?
其实说了这么多,还没到我写这篇文章的最原始意图。从上面解释的你应该懂了 new/delete、new[]/delete[] 的工作原理了,因为它们之间有差别,所以需要配对使用。但偏偏问题不是这么简单,这也是我遇到的问题,如下这段代码:

int *pia = new int[10];
delete []pia;

这肯定是没问题的,但如果把 delete []pia; 换成 delete pia; 的话,会出问题吗?
这就涉及到上面一节没提到的问题了。上面我提到了在 new [] 时多分配 4 个字节的缘由,因为析构时需要知道数组的大小,但如果不调用析构函数呢(如内置类型,这里的 int 数组)?我们在 new [] 时就没必要多分配那 4 个字节, delete [] 时直接到第二步释放为 int 数组分配的空间。如果这里使用 delete pia;那么将会调用 operator delete 函数,传入的参数是分配给数组的起始地址,所做的事情就是释放掉这块内存空间。不存在问题的。
这里说的使用 new [] 用 delete 来释放对象的提前是:对象的类型是内置类型或者是无自定义的析构函数的类类型!
我们看看如果是带有自定义析构函数的类类型,用 new [] 来创建类对象数组,而用 delete 来释放会发生什么?用上面的例子来说明:

class A *pAa = new class A[3];
delete pAa;

那么 delete pAa; 做了两件事:
调用一次 pAa 指向的对象的析构函数;
调用 operator delete(pAa); 释放内存。
显然,这里只对数组的第一个类对象调用了析构函数,后面的两个对象均没调用析构函数,如果类对象中申请了大量的内存需要在析构函数中释放,而你却在销毁数组对象时少调用了析构函数,这会造成内存泄漏。
上面的问题你如果说没关系的话,那么第二点就是致命的了!直接释放 pAa 指向的内存空间,这个总是会造成严重的段错误,程序必然会奔溃!因为分配的空间的起始地址是 pAa 指向的地方减去 4 个字节的地方。你应该传入参数设为那个地址!
同理,你可以分析如果使用 new 来分配,用 delete [] 来释放会出现什么问题?是不是总会导致程序错误?
总的来说,记住一点即可:new/delete、new[]/delete[] 要配套使用总是没错的!

参考网址:http://blog.csdn.net/hazir/article/details/21413833#t0  


2015-11-12 15:42:02 lululove19870526 阅读数 2313

如何快速的判断数组中是否有某个特定元素

   判断数组中是否有某个特定元素有多种方法,但是时间复杂度是差别很大的。各种方法的实现如下:

   1.使用List

  public static boolean useList(String[] arr, String targetValue) {

    return Arrays.asList(arr).contains(targetValue);
}
  2.使用Set

public static boolean useSet(String[] arr, String targetValue) {
    Set<String> set = new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);
}
3.使用一个简单的循环

public static boolean useLoop(String[] arr, String targetValue) {
    for(String s: arr){
        if(s.equals(targetValue))
            return true;
    }
    return false;
}

4.使用Arrays.binarySearch(),但是binarySearch()只能用于已排好序的数组中
public static boolean useArraysBinarySearch(String[] arr, String targetValue) { 
    int a =  Arrays.binarySearch(arr, targetValue);
    if(a > 0)
        return true;
    else
        return false;
}

很明显,使用简单循环的方法比使用其他任何集合效率更高。许多开发者会使用第一种方法,但是它并不是高效的。将数组压入Collection类型中,需要首先将数组元素遍历一遍,然后再使用集合类做其他操作。

如果使用Arrays.binarySearch()方法,数组必须是已排序的。由于上面的数组并没有进行排序,所以该方法不可使用。

实际上,如果你需要借助数组或者集合类高效地检查数组中是否包含特定值,一个已排序的列表或树可以做到时间复杂度为O(log(n)),hashset可以达到O(1)。


C++数组的详细解析

阅读数 5471