java基础之数组

一、数组定义

数组是编程语言中最为常见的一种数据结构,用于存储多个数据,可以通过数组元素的索引来访问数组元素。Java要求所有的宿主元素具有相同的类型,即一个数组只能存储一种数据类型的数据。

二、初始化数组

数组一旦完成初始化后,数组所占用的内存大小也随之确定下来不可改变,即数组的长度不可以更改。

1.定义数组

Java支持两种语法来定义数组

① type [] arrayName;
② type arrayName [];

我们通常使用第一种格式,因为第一种具有较高的可读性。

数组是一种引用型变量,使用它定义一个变量时,仅仅表示定义了一个“指针”,这个“指针”还未指向任何有效的内存,所以只有在数组完成初始化之后才可以使用。

2.静态初始化数组

语法格式:

type [] arrayName = new type[]{element1,element2 ...}
type [] arrayName ={element1,element2 ...}

静态初始化:初始化时不可以指定数组长度,且要显式指定数组中的每个元素的初始值,由系统自动确定数组长度。

3.动态初始化数组

语法格式:

type [] arrayName = new type[length];

动态初始化:初始化时只指定数组长度,有系统为每个数组元素指定初始值。其中length为int类型参数。
执行动态初始化时,我们只需要为数组指定长度,也就是维数组指定所占内存空间的大小即可,系统会自动根据不同类型的数组为数组元素分配初始值。

①数组类型为byte,short,int,long则系统指定数组元素初始值为0
②数组类型为float,double则系统指定元素初始值为0.0
③数组类型为char则系统指定元素初始值为‘\u0000’(空格)
④数组类型为Boolean则系统指定元素初始值为false
⑤数组类型为引用类型(类,接口,数组)则系统指定元素初始值为null

!不要在数组进行初始化时既指定数组长度,同时又为数组元素赋初始值。

三、数组使用

数组最常用的就是访问数组元素,包括对数组进行取值和赋值。
语法格式:

①取值:type str = arrayName[index]
②赋值:arrayName[index] = str

其中index表示数组下标 type表示数组类型即str需要与素组的定义类型相同。数组下标是从0开始,也就是说数组长度如果是5的话那么数组下标最大为4。
如果index小于0或者大于等于数组长度时将会引发异常:java.lang.ArrayIndexOutBoundesException(数组下标越界异常)。

代码示例:

public class ArrayExceptionDemo{    
    public static void main(String [] args){
        //初始化数组,数组长度为5
        int [] arr = {1,2,3,4,5};
        //访问数组下标为5的元素
        System.out.println(arr[5]);
    }
}
运行结果:报错java.lang.ArrayIndexOutBoundsException

四、数组遍历

所有的数组都提供了一个length属性,通过这个属性可以访问到数组长度,一旦获取了数组长度我们就可以通过循环来遍历数组元素。

1.普通循环遍历

代码示例:

public class TraversalArrayDemo{
    public static void main(String [] args){
        int [] arr = {1,2,3,4,5};
        int len = arr.length;
        for(int i=0; i<len; i++){
            System.out.println(arr[i]);
        }
        System.out.println("遍历结束");
    }
}
运行结果:1,2,3,4,5 遍历结束
2.使用foreach遍历

自Java5之后,Java提供了一种更为简便的循环foreach循环,这中循环遍历数组以及集合更加简单。使用foreach循环遍历数组集合时无须获得数组和集合的长度,也无须根据索引来访问数组以及集合中的元素,foreach会自动遍历数组以及集合的每个元素。

语法格式:

for(type strName : arrayName){
    strName
}

其中type是数组类型,strName为形参名用于接收数组中的元素值。

代码示例:

public class ForeachDemo{
    public static void main(String [] args){
        int [] arr ={1,2,3,4,5};
        for(int a : arr){
            System.out.println(a);
        }
        System.out.println("遍历结束");
    }
}
运行结果:1,2,3,4,5 遍历结束

当时用foreach遍历数组时,foreach中的循环变量即上面代码中的a是临时变量,系统会自动把数组中的元素值依次赋给该临时变量,所以不能通过给a赋值来改变数组元素。如果希望改变数组元素得值则不能使用foreach循环。

五、深入数组

当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法里定义的变量将会逐个的被放入到这个内存栈中,即所有在方法中被定义的的局部变量都是放在栈内存中。
数组引用变量只是一个引用,这个引用变量可以指向任何有效的内存,只有当它指向有效的内存后,才可以通过该数组来访问数组元素。
实际的数组对象被存储在堆内存中(heap)无法被直接访问,而我们声明的数组引用变量则是存储在栈内存(stack)中只有通过数组的引用变量才可以访问实际的数组对象。数组在内存中存储结构如图所示。
数组存储示意图
栈内存只是存储一个堆内存中的地址,通过该地址才能访问实际的数组对象。

引用类型数组的存储方式

引用类型的数组存储方式和数组一样,只不过是堆内存中的实际数组对象里面存储的依然是一个指向堆内存中的地址而已。
比如,我们定义一个person类,具体代码如下所示:

public class Person{
    public int age;
    public String name;
    public void PrintMethod{
        System.out.println("年龄为:"+age+",姓名为:"+name);
    }
}

然后我们定义一个person数组,对其进行初始化,里面存储的类型为person类型,代码如下:

public class ArrayPerson{
    public static void main(String [] args){
        //定义存储类型为person的数组,数组长度为2
        Person [] p = new Person[2];
        //创建person实例
        Person tutu = new Person();
        tutu.age = 23;
        tutu.name ="suntutu";
        //将Person实例赋给person数组
        p[0] = tutu;

        Person rui = new Person();
        rui.age = 22;
        rui.name = "xiaoruirui";
        p[1] =rui;
        //输出相同
        rui.info();
        p[1].info();

    }

}

以上代码的存储结构示意图如图所示:存储示意图

多维数组

Java里提供了支持多维数组的语法,但其实并没有什么多维数组,多维数组只不过是一个数组里的元素保存另一个数组所在的地址而已。其存储结构和引用类型的数组的存储结构相同,只不过数组里存的不是对象的引用,而是数组的引用罢了。
语法格式:

type [][] arrName = new type[length][length]

示例代码:

public class ArrDemo{
    public static void main(String [] args){
        int [][] arr = new int [2][2];
        for(int j=0; j<arr.length; j++){
            for(int k=0; k<arr[j].length; k++){
                arr[j][k] = k+j+4;
                System.out.println(a[j][k])
            }
        }
    }
}
运行结果:4,5,6,7

六、Arrays方法

binarySearch(type[] a, int fromIndex,int endIndex, type key) : 使用二分法查询key元素值在a数组里fromIndex 到 endIndex索引中key出现的索引值,如果a数组中不包含key则返回负数。返回值为int类型。fromIndex与endIndex可以不加,不加则搜索整个a数组。调用该方法时要求a数组中的元素已经按照升序排列。

copyOf(type [] a , int length , int form , int end):将a数组中的from索引到end索引的元素复制成为一个新数组,其中length是新数组的长度,如果length小于a数组的长度则新数组是a数组的前面length个元素,如果大于a数组的长度则新数组前面的元素就是a数组的元素,后面根据类型不同自动补充0(数值类型)、false(布尔类型)、null(引用类型)。from与end可以不加,不加则复制整个a数组。返回值为数组。

equals(type [] a,type [] b):如果a数组与b数组长度相同且a数组与b数组的数组源于也一 一相同则返回true。

fill(type [] a, int fromIndex, int endindex,type val):将a数组从fromIndex到endIndex索引的所有元素都赋值为 val。fromIndex与endIndex可不加,不加则默认将a数组中的所有元素都赋值为val。

sort(type [] a, int fromIndex, int endIndex):将数组a中的fromindex到endIndex索引的元素进行排序。fromindex与endindex可不加,不加则默认对整个a数组进行排序。

toString(type [] a):该方法将a数组按顺序把多个数组元素连接在一起组成一个字符串,元素与元素之间使用英文逗号和空格隔开。

七、Java8增加的Arrays类的方法

parallePrefix(type [] array , typeBinaryOperator op):该方法使用匿名内部类op来指定计算公式,把公式计算得到的结果作为新的数组元素。op计算公式包括left和right两个形参,left代表数组中的前一个索引处的元素,right代表当前索引处的元素。当计算第一个素数元素时,left默认为1。在array与op之间可以增加 int fromIndex , int endindex 表示仅使用公式重新计算此区间内的元素。

setAll(type [] array, IntToXxxFunction generator):该方法使用指定的生成器为所有数组元素赋值,该生成器控制数组元素值的生成算法。

parallelSetAll(type [] array, IntToXxxFunction generator):该方法与上一方法作用相同,只不过该方法增加了并行能力,可以利用多CPU并行来提高性能。

parallelSort(type [] array):作用与Arrays以前有的sort()方法相同,只不过该方法增加了并行能力,可以利用多CPU并行来提高性能。
同样的与sort()方法相同也可以指定方法区间,与sort()方法相同。

Spliterator.OfXxx spliterator (xxx [] array, int fromIndex ,int endIndex):该方法将fromIndex到endIndex之间的数组元素转换成对应的Spliterator对象。后面两个int参数可以不加,不加则默认替换全部数组元素。

XxxStream stream(xxx [] array ,int fromIndex , int endIndex):该方法将fromIndex到endIndex之间的元素转换成Stream。后面两个int参数可以不加,不加则默认转换整个数组元素。

在上面的方法中type与xxx代表不同的数据类型。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值