欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

关于JAVA 数组的使用介绍

程序员文章站 2023-12-01 13:57:34
java数组与容器类主要有三方面的区别:效率、类型和保存基本类型的能力。在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性数列,这使...

java数组与容器类主要有三方面的区别:效率、类型和保存基本类型的能力。在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性数列,这使得元素访问非常快速。但是为此付出的代价却是数组的大小被固定,并且在其生命周期中不可改变。

由于范型和自动包装机制的出现,容器已经可以与数组几乎一样方便地用于基本类型中了。数组和容器都可以一定程度上防止你滥用他们,如果越界,就会得到runtimeexception异常。数组硕果仅存的优势便是效率,然而,如果要解决更一般化的问题,那数组可能会受到过多的限制,因此这种情况下大部分还是会选择容器。

因此,如果使用最近的java版本,应该优先选择容器而不是数组。只有在已证明性能已成为问题,并且切换到数组可以提高性能时,才应该重构程序为数组。

【初始化】
java对数组初始化有很严格的规定,这样可以有效地防止滥用数组。如果初始化错误,会直接得到compileexception而不是runtimeexception。在未对数组正确初始化之前,无法用此数组引用做任何事情。
数组定义有int[] array 和int array[],一般采用第一种风格,可以将类型与变量名分开。
数组的初始化有两种方式,静态初始化和动态初始化。初始化的时候必须指定长度,多维数组第一维的长度必须指出,同时必须由高维向低维定义。初始化动作可以在代码的任何地方,而用{}方式只能在创建数组的地方出现。具体初始化方式见程序:

复制代码 代码如下:

public class javaarrayinit{
    public static void main(string args[]){
        int[] arraya; //未初始化
        int[] arrayb = new int[5]; //静态初始化
        //system.out.println(arraya.length);  //compileexception
        system.out.println("arrayb length: " + arrayb.length); //无法得到实际保存的元素个数

        arraya = new int[10]; //动态初始化
        system.out.println("arraya length: " + arraya.length);

        int[] arrayc = new int[]{1,2,3,4};
        system.out.println("arrayc length: " + arrayc.length);

        //int[] arrayd = new int[1]{1}; //错误的初始化,不能同时定义维和初始化值

        int[][] arraye = new int[1][];
        system.out.println("arraye length: " + arraye.length);

        //int[][] arrayf = new int[][2]; //应先指定高维的长度

        int[][] arrayg = new int[][]{{1,2,3,4},{5,6,7},{7,24,23,24}};
        system.out.println("arrayg length: " + arrayg.length);

        int[][][] arrayh = new int[][][]{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}}};
        system.out.println("arrayh length: " + arrayh.length);

        dummyarray[] arrayi = {new dummyarray(),new dummyarray()}; //自定义数组类型
        system.out.println("arrayi length: " + arrayi.length);
        system.out.println("arrayi[1]: " + arrayi[1].getvalue());

        dummyarray[] arrayk = new dummyarray[5];
        system.out.println("arrayk[0]: " + arrayk[0]); //null
        for(int i = 0; i < arrayk.length; i++){
            arrayk[i] = new dummyarray();
        }
        system.out.println("arrayk[0]: " + arrayk[0].getvalue()); //2
    }
}
class dummyarray{
    private static int temp;
    private final int arrayvalue = temp++;
    public int getvalue(){
        return arrayvalue;
    }
}

输出:

arrayb length: 5
arraya length: 10
arrayc length: 4
arraye length: 1
arrayg length: 3
arrayh length: 1
arrayi length: 2
arrayi[1]: 1
arrayk[0]: null
arrayk[0]: 2


【length】
只读成员length是数组对象的一部分(虽然实际上api里面并没有声明这个变量,是运行时动态生成),这是唯一一个可以访问的字段或方法。而[]语法是访问数组对象的唯一方式,容器是通过get()方法访问。可以使用array.length来得到数组的大小,注意与string类型的string.length()区分。array使用的是成员变量的方式,而string使用的是成员方法的方式。同时,array.length只能得到数组的大小,而无法得到数组实际有多少元素。多维数组的length只计算第一维的长度。
复制代码 代码如下:

public class javaarraylength{
    public static void main(string args[]){
        int[] arraya = new int[15];
        arraya[1] = 1;
        arraya[2] = 2;
        arraya[3] = 3;
        system.out.println("arraya length: " + arraya.length);

        int[][] arrayb = new int[10][];
        system.out.println("arrayb length: " + arrayb.length);

        int[][] arrayc = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7},};//注意后面的逗号
        system.out.println("arrayc length: " + arrayc.length);

        int[][] arrayd = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7},{}};
        system.out.println("arrayd length: " + arrayd.length);
    }
}
输出:

arraya length: 15
arrayb length: 10
arrayc length: 3
arrayd length: 4


【arrays.fill】
arrays.fill是一个作用十分有限的方法,因为它只能用同一个值填充各个位置(如果是对象,则复制同一个引用进行填充)。使用arrays.fill可以填充整个数组或者数组的某一个区域,但是由于只能用单一的数值来调用arrays.fill,因此作用并不是很大。

【赋值与引用】
java数组初始化的时候拥有的只是对数组的引用,并没有给数组分配存储空间。因此,数组之间的复制不能简单地用“=”赋值,因为操作的是同一对象。如下程序:
复制代码 代码如下:

public class javaarrayquote{
    public static void main(string args[]){
        string testa = "testa";
        string testb = "testb";
        string[] arraya = new string[]{"arraya"};
        string[] arrayb = new string[]{"arrayb"};
        testb = testa;
        testb = "testb change";
        system.out.println("i'm testa,i have no changed: " + testa);
        arrayb = arraya;
        arrayb[0] = "arrayb have changed";
        system.out.println("i'm arraya, i have no changed: " + arraya[0]);

    }
}
输出:

i'm testa,i have no changed:testa
i'm arraya, i have no changed:arrayb have changed


可以看出,我们改变arrayb[0]的值,改变的是引用的数组,因此我们输出arraya[0],其实和arrayb[0]一样。

【数组复制】
        java中复制数组的方法:

        1.使用for循环复制全部或指定元素,效率较低
        2.使用clone方法,得到数组的值,而不是引用。然而clone不能复制指定元素,灵活性较低
        3.使用system.arraycopy(src, srcpos, dest, destpos, length)方法,java标准类库提供有static方法 system.arraycopy(),用它复制数组要比for循环快很多,system.arraycopy()针对所有类型做了重载,基本类型数组和对象数组都可以用system.arraycopy()复制,但是对象数组只是复制引用,不会出现两份对象的拷贝。这被称作浅复制(shallowcopy)。
               src:源数组;
                srcpos:源数组要复制的起始位置;
                dest:目的数组;
                destpos:目的数组放置的起始位置;
                length:复制的长度.
        注意:system.arraycopy()不会进行自动包装和自动拆包,因此两个数组必须是同类型或者可以转换为同类型的数组。同时,这个方法也可以用于复制数组本身。
        int[] test ={0,1,2,3,4,5,6};
        system.arraycopy(test,0,test,3,3);
        则结果为:{0,1,2,0,1,2,6};
        测试程序如下:
复制代码 代码如下:

public class javaarraycopy{
    public static void main(string args[]){
        int[] array = {1,2,3,4,5,6,7,8,9};
        //for循环方法
        int[] arraya = new int[9];
        for(int i = 0; i < arraya.length; i++){
            arraya[i] = array[i];
            system.out.print(arraya[i] + ",");
        }
        //测试
        system.out.println("");
        arraya[1] = 19;
        for(int i = 0; i < arraya.length; i++){
            system.out.print(arraya[i] + ",");
        }
        system.out.println("");
        for(int i = 0; i < array.length; i++){
            system.out.print(array[i] + ",");
        }
        system.out.println("");

        //clone方法
        int[] arrayb = new int[9];
        arrayb = array.clone();
        //测试
        arrayb[1] = 19;
        for(int i = 0; i < arrayb.length; i++){
            system.out.print(arrayb[i] + ",");
        }
        system.out.println("");
        for(int i = 0; i < array.length; i++){
            system.out.print(array[i] + ",");
        }
        system.out.println("");

        //system.arraycopy 方法
        int[] arrayc = new int[9];
        system.arraycopy(array, 0, arrayc, 0, arrayc.length);
        //测试
        arrayc[1] = 19;
        for(int i = 0; i < arrayc.length; i++){
            system.out.print(arrayc[i] + ",");
        }
        system.out.println("");
        for(int i = 0; i < array.length; i++){
            system.out.print(array[i] + ",");
        }
    }
}

【数组比较】
arrays提供了重载后的equals()方法,针对所有类型和object类型都做了重载,用来比较整个数组。数组相等的条件是元素个数必须相等,并且对应位置的元素也相等。而多维数组的比较用deepequals()方法。array.equals()方法比较的两个数组必须是同类型的数组。
复制代码 代码如下:

import java.util.arrays;
public class javaarrayequals{
    public static void main(string args[]){
        int[] arraya = {1,2,3};
        int[] arrayb = {1,2,3,};
        int[] arrayc = new int[4]; //if int[] arrayc = new int[3],return true
        arrayc[0] = 1;
        arrayc[1] = 2;
        arrayc[2] = 3;
        system.out.println(arrays.equals(arraya, arrayb));
        system.out.println(arrays.equals(arraya, arrayc));

        string[][] arrayd = {{"a","b"},{"c","d"}};
        string[][] arraye = {{"a","b"},{"c","d"}};
        system.out.println(arrays.deepequals(arrayd, arraye));
    }
}

【数组排序与查找】
数组提供了内置的排序方法sort(),可以对任意基本类型数组或者对象数组进行排序(该对象必须实现comparable接口或者具有相关联的comparator)。java对不同的类型提供了不同的排序方法----针对基本类型设计的快速排序,以及针对对象设计的“稳定归并排序”,所以无需担心数组排序的效率问题。
 binarysearch()用于在以排好序的数组中快速查找元素,如果对未排序的数组使用binarysearch(),那么将产生难以预料的结果。

【返回数组】
c和c++不能返回一个数组,只能返回指向数组的指针,因为返回数组使得控制数组的生命周期变得困难,并且容易造成内存泄漏。java允许直接返回一个数组,并且可以由垃圾回收机制回收。

【数组与容器转换】【无法转换基本类型数组】

数组转为list:
复制代码 代码如下:

import java.util.*;
public class arraytolist{
    public static void main(string args[]){
        string[] arraya = {"a","b","c"};
        list lista = java.util.arrays.aslist(arraya);
        system.out.println("lista: " + lista);

        int[] arrayb = {1,2,3};
        list listb = java.util.arrays.aslist(arrayb);
        system.out.println("listb: " + listb);

        integer[] arrayc = {1,2,3};
        list listc = java.util.arrays.aslist(arrayc);
        system.out.println("listc: " + listc);
    }
}
输出:


lista: [a, b, c]
listb: [[i@de6ced]
listc: [1, 2, 3]


为什么int和integer输出会不同呢?

list转为数组
复制代码 代码如下:

import java.util.*;
public class listtoarray{
    public static void main(string args[]){
        list<string> list = new arraylist<string>();
        string[] array;
        list.add("testa");
        list.add("testb");
        list.add("testc");
        system.out.println("list: " + list);

        string[] strings = new string[list.size()];
        array = list.toarray(strings);
        for(int i = 0, j = array.length; i < j; i++){
            system.out.print(array[i] + ",");
        }
    }
}
输出为:

list: [testa, testb, testc]
testa,testb,testc


【去除重复数据】
利用数组和容器转换可以方便地去除数组重复数据,不过如果数组过大,效率是一个问题。
复制代码 代码如下:

import java.util.*;
public class javaarrayunique{
    public static void main(string args[]){
        string[] array = {"a","b","a","a","c","b"};
        arrayunique(array);
        //test
        for(int i = 0, j = arrayunique(array).length; i < j; i++){
            system.out.print(arrayunique(array)[i] + ",");
        }
    }

    public static string[] arrayunique(string[] array){
        list<string> list = new arraylist<string>();
        for(int i = 0, j = array.length; i < j; i++){
            if(!list.contains(array[i])){
                list.add(array[i]);
            }
        }
        string[] strings = new string[list.size()];
        string[] arrayunique = list.toarray(strings);
        return arrayunique;
    }
}

 关于效率问题,我做了一个对比,在我电脑上运行十万数据的数组大概是577ms,而运行一百万数据的数据大约要5663ms。这还跟计算机的运行能力有关,但是明显是随着数组大小递增的。
复制代码 代码如下:

import java.util.*;
public class javaarrayunique{
    public static void main(string args[]){
        double[] array = new double[100000];
        for(int i = 0, j = array.length; i < j; i++){
            array[i] = math.ceil(math.random()*1000);
        }

        double[] arrayb = new double[1000000];
        for(int i = 0, j = arrayb.length; i < j; i++){
            arrayb[i] = math.ceil(math.random()*1000);
        }

        system.out.println("start");
        long starttime = system.currenttimemillis();
        arrayunique(array);
        long endtime = system.currenttimemillis();
        system.out.println("array unique run time: " +(endtime - starttime) +"ms");

        long starttimeb = system.currenttimemillis();
        arrayunique(arrayb);
        long endtimeb = system.currenttimemillis();
        system.out.println("arrayb unique run time: " +(endtimeb - starttimeb) +"ms");
    }

    public static double[] arrayunique(double[] array){
        list<double> list = new arraylist<double>();
        for(int i = 0, j = array.length; i < j; i++){
            if(!list.contains(array[i])){
                list.add(array[i]);
            }
        }
        double[] doubles = new double[list.size()];
        double[] arrayunique = list.toarray(doubles);
        return arrayunique;
    }
}
输出:

start
array unique run time: 577ms
arrayb unique run time: 5663ms