从零学java day3 第四章 数组

1.数组类型

数组是编程语言中最常见的一种数据结构,可用于存储多个数据,每个数组元素存放一个数据,通常可通过数组元素的索引来访问数组元素,包括为数组元素赋值和取出数组元素的值

理解数组:数组也是一种类型

java的数组要求所有的数组元素具有相同的数据类型,因此在一个数组中,数组元素的类型是唯一的,即一个数组里只能存储一种数据类型的数据,而不能存储多种数据类型的数据。

一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,因此数组的长度将不可改变,即使把某个数组元素的数据清空,但它所占的空间依然被保留。


2.定义数组

java语言支持两种语法格式来定义数组

type[] arrayName;

type arrayName[]; 

对着两种语法格式而言,通常推荐使用第一种格式,因为第一种格式不仅具有更好的语意,而且具有更好的可读性

数组是一种引用类型的变量,因此使用它定义一个变量时,仅仅标识定义了一个引用变量,这个引用变量还未指向任何有效的内存,因此定义数组时不能指定数组的长度,而且由于定义数组只是定义了一个引用变量,并未指向任何有效的内存空间,所以还没有内存空间来存储数组元素,因此这个数组也不能使用,只有对数组进行初始化后才可以使用。

3.数组的初始化

java语言中数组必须先初始化,然后才可以使用,所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始的值。

数组的初始化有两种方式:

静态初始化:初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组长度。

动态初始化:初始化时程序员只能指定数组长度,有系统为数组元素分配初始值。


静态初始化语法格式如下:

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

动态初始化语法格式如下:

arrayName = new type[length];

执行动态初始化时程序员只需要指定数组的长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。

数组元素的类型是基本类型中的整数类型(byte、short、int、long)则数组元素的值是0

数组元素的类型是基本类型中浮点类型(float、double),则数组元素的值是0.0

数组元素的类型是基本类型中字符类型(char),则数组元素的值是'\u0000'

数组元素的类型是基本类型中布尔类型(boolean),则数组元素的值是null

4.使用数组

数组最常用的用法就是访问数组元素,包括对数组元素进行赋值和取出数组元素的值,访问数组元素都是通过在数组引用变量后紧跟一个方括号[],方括号里是数组元素的索引值,这样就可以访问数组元素了,访问到数组元素之后,就可以把一个数组元素当成一个普通变量使用了,包括为该变量赋值和取出该变量的值,这个变量的类型就是定义数组时使用的类型。

java语言的数组索引是从0开始的,也就是说,第一个数组元素的索引值为0,最后一个数组元素的索引值为数组长度减一,

如果访问数组元素时指定的索引值小于0,或者大于等于数组的长度,编译程序不会出现任何错误,但运行时出现异常:java.lang.ArraryIndexOutOfBoundsException:N(数组索引越界异常),异常信息后的N就是程序员试图访问的数组索引。

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


5.foreach循环

从java5之后,java提供了一种更简单的循环:foreach循环,这种循环遍历数组和集合。使用foreach循环遍历数组和集合元素时,

,无需获得数组和集合的长度,无需根据索引来访问数组元素和集合元素,foreach循环自动遍历数组和集合的每个元素。

foreach循环的语法格式如下:

for(type variableName : array | collection)

{

//variableName 自动迭代访问每个元素

}

foreach循环和普通循环不同的是,它无需循环条件,无需循环迭代语句,这些部分都由系统来完成,foreach循环自动迭代数组的每个元素,每当元素都被迭代一次后,foreach循环自动结束。

6.深入数组

1)内存中的数组

数组应用变量是访问堆内存中数组元素的根本方式。

定义并初始化一个数组后,在内存中分配了两个空间,一个用于存放数组的引用变量,另一个用于存放数组本身。

2)基本类型数组的初始化

对于基本类型数组而言,数组元素的值直接存储在对应的数组元素中,因此初始化数组时,先为该数组分配内存空间,然后直接将数组元素的值存入对应数组元素中。

3)引用类型数组的初始化

每个数组元素里存储的还是引用,它指向另一块内存,这块内存里存储了有效数据。

4)没有多维数组

如果从数组底层的运行机制上来看,没有多维数组

java语言里的数组类型是引用类型,因此数组变量其实是一个引用,这个引用指向真实的数组内裤才能。数组元素的类型也可以是引用,如果数组元素的引用再次指向真实的数组内存,这种情形看上去很像多维数组。

java语言采用上面的语法格式来定义二维数组,但它的实质还是一维数组,只是其数组元素也是引用,数组元素里保存的引用指向一维数组。

7.java8增强的工具类:arrays

java提供的arrays类里包含的一些static修饰的方法可以直接操作数组,这个arrays类里包含了如下几个static修饰的方法

int binarySearch(type[] a, type key):使用二分法查询key元素值在a数组中出现的索引;如果a数组不包含key元素值,则返回负数。调用该方法时要求数组中元素已经按升序排列,这样才能得到正确的结果。

int binarySearch(type[] a,int fromIndex,int toIndex ,type key):这个方法和前一个方法类似,但它只搜索a数组中fromIndex到toIndex索引的元素。调用该方法时要求数组中元素已经按升序排列,这样才能得到正确的结果。

type[] copyOf(type[] original,int length):这个方法将会把original数组复制成一个新数组,其中length是新数组的长度。如果length小于original数组的长度,则新数组就是原数组的前面length个元素;

type[] copyOfRange(type[] original,int from,int to):这个方法与前面方法相似,但这个方法只复制original数组的from索引到to索引的元素。

boolean equals(type[] a,type a2):如果a数组和a2数组的长度相等,而且a数组和a2数组的数组元素也一一相同,该方法将返回true。

void fill(type[] a, type val):该方法将会把a数组的所有元素都赋值为val。

void fill(type[] a,int fromIndex,int toIndex,type val)

void sort(type[] a)该方法对a数组进行排序。

void sort(type[] a,int fromIndex,int toIndex)

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

Arrays类处于java.util包下,为了在程序中使用Arrays类,必须在程序中导入java.util.Arrays类。

void parallelPrefix(xxx[] array,XxxBinaryOperator op):该方法使用op参数指定的计算公式计算得到的结果作为新的元素。op计算公式包括left、right两个形参,其中left代表数组中前一个索引处的元素,right代表数组中当前索引处的元素,当计算第一个新数组元素时,left的值默认为1

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

void paralleSetAll(xxx[] array,IntToXxxFunction generator):该方法的功能与上一个方法相同,只是该方法增加了并行能力,可以利用多CPU并行来提高性能

void parallelSort(xxx[] a,int fromIndex,int toIndex):该方法与sort()方法相似,该方法增加了并行能力。

Spliterator.OfXxx spliterator(xxx[] array):将数组的所有元素转换成对应的Spliterator对象。

XxxStream stream(xxx[] array):该方法将数组转换为Stream,Stream是java8新增的流式编程的API

推荐阅读更多精彩内容