数组
编程语言中国常见的一种数据结构,可用于存储多个数据。
数组的定义
- 方式1(推荐,更能表明数组类型)
type[] 变量名 = new type[数组中元素的个数];
比如:
int[] a = new int[10];
数组名,也即引用a,指向数组元素的首地址。值得注意的是a不是整型,而是数组类型。
- 方式2(同C语言)
type变量名[] = new type[数组中元素的个数];
如:
int a[] = new int[10];
数组没有存到a中去,a保存的仅仅是数组数据在内存中的地址。
堆和栈的相关知识
数组的一个小题目
/**
* 内存中是否有垃圾?没有,因为虽然x不再引用栈内存中的数据,但是依旧在引用。只要栈内存的数据有被引用,其就不是内存垃圾
*/
@Test
public void TestArrayMemorry()
{
int[] x=new int[3];
int[] y=x;
y[0]=11;
x[0]=12;
x=null;
}
数组的初始化
Java 中数组必须先初始化才能使用。所谓初始化就是为数组的数组元素分配内存空间并为每个数组元素赋值。
Java 数组的初始化有两种方式:
- 静态初始化:初始化时由程序显式指定每个数组元素的初始值,由系统决定数组长度。
- 动态初始化: 初始化时程序员只指定数组长度,由系统为数组分配初始值。
基本类型数组的初始化
基本类型的数组因为数组元素的值是直接存放在对应的数组元素中的,因此初始话数组时先为该数组分配内存空间,然后直接将数组元素的值存入对应对应的数组元素中就OK了。没什么可说的。
引用类型的数组的初始化
一个代码说明一切:
public void arrayInit() {
People[] peoples=new People[2];
//执行People[] peoples时,计算机仅仅在内存中定义了一个引用变量,此时这个变量并没有指向内存中任何有效的地区。当执行了new People[2]时,peoples数组的两个元素依然为空。
//栈中定义了一个变量,他仅仅是一个引用,并没有指向任何有效内存。知道执行初始化,这里执行的时动态初始化,动态初始化由系统为数组元素分配默认值:null.也就是每个数组元素的默认值都是null。
//此处输出为空
System.out.println(peoples[1]);
People people=new People();
people.setAge(22);
people.setName("路飞");
People people1=new People();
people1.setName("卡普");
people1.setAge(80);
peoples[0]=people1;
peoples[1]=people;
//执行了这两句之后peoples才有值。这时people1和peoples[1]指向的时同一个内存区域。
for (int i = 0; i < peoples.length; i++) {
System.out.println(peoples[i].getName() + ":" + peoples[i].getAge() + "岁");
}
}
使用数组
Java数组索引时从0开始的。下面代码就是标准的输出数组元素的值以及为指定数组元素赋值。
数组提供了一个length属性用来获取可以访问到的数组的长度。
获取数组当中的元素通常会需要用到遍历。
Array[0]="testData";
System.out.println(Array[0]);
如果使用如下的方式打印一个数组会出现什么情况呢?
public void printArr()
{
int array[] ={1,2,3,4,5,6,7,8,9};
System.out.println(array);
}
输出结果:
[I@2f7a2457
注意这不完全是乱码,这一串字符是有特殊含义的。第一个中括号标示打印的是一个数组;第二个I表示的是这是一个整型数组;@后面的字符串是该变量引用的数组存放的地址。
数组使用过程中常见的异常:
- ArrayIndexOutOfBoundsException:操作数组是访问到了数组不存在的角标。
- NullPointerException:空指针异常,变量不在指向任何数组实体。
数组的排序
选择排序
将最值逐渐
示例代码
/***
* 选择排序:内循环结束一次,最值的会出现在头角标位置
* @param array
*/
public void orderArray(int[] array)
{
int temp;
for (int i = 0; i < array.length-1; i++) {
for (int j=i+1;j<array.length;j++)
{
if(array[j]<array[i])
{
temp=array[j];
array[j]=array[i];
array[i]=temp;
}
}
}
}
冒泡排序
相邻的两个元素进行比价,如果符合条件就交换位置。
示例代码
/***
* 冒泡排序
*/
public static void bobbleOrder(int[] array)
{
int temp;
for (int i = 0; i < array.length-1; i++) {
for (int i1 = 0; i1 < array.length-i-1; i1++) {
if(array[i1]>array[i1+1])
{
temp=array[i1+1];
array[i1+1]=array[i1];
array[i1]=temp;
}
}
}
}
问题:使用这个函数对一个数组进行排序为什么不需要返回值呢?
因为数组是引用变量,该函数所操作的数组实质上就是原数组。
二维数组
二维数组的定义:
int[][] arr=new int[2][2];
以上表示名称为arr的数组中有两个以为数组,每一个一维数组数组中有两个元素。
二维数组中需要注意的:
public void erWeiShuZu()
{
int[][] arr=new int[2][2];
System.out.println(arr);
//[[I@2f7a2457
System.out.println(arr[0]);
//[I@566776ad
System.out.println(arr[0][0]);
//0
int[][] arr2=new int[2][];
System.out.println(arr2);
//[[I@6108b2d7
System.out.println(arr2[0]);
//null
System.out.println(arr2[0][0]);
//不能输出
}
为什么会有null输出呢?因为数组是引用类型,虽然最外层的数组初始化了,但是内层的数组并没有。因为外层的数组并没有指向内存中的任何地方。
数组的查找
折半查找
使用折半查找可以提高程序运行效率,但是前提是数组必须是有顺序的
示例代码:
public int findInArray()
{
int[] array={0,1,2,3,4,5,6,7,8,9,212,323,4432,243334};
int min=0;
int max=array.length-1;
int mid=(min+max)/2;
int key=323;
while (array[mid]!=key)
{
if(array[mid]>key)
{
max=mid-1;
}
if(array[mid]<key)
{
min=mid+1;
}
if(min>max) {
return -1;
}
mid=(max+min)/2;
}
System.out.println(mid);
return mid;
}
深入数组
数组是一种引用数据类型,数组引用变量只是一个引用,数组元素和数组变量在内存里时分开存放的。
内存中的数组
数组引用变量只是一个引用,引用变量是访问真实对象的根本方式。实际的数字对象被存放在堆内存中,如果引用该数组对象的数组引用变量是一个局部变量,那么他被存储在栈内存中。
如果堆内存中数组不再有任何引用引用变量指向自己,则这个数组将成为垃圾,该数组所占用的内存将会被系统的垃圾回收机制回收。因此为了垃圾回收机制回收一个数组所占用的内存空间,可以将该数组变量赋值为null。
实际的数组对象存放在对内存中,如果引用该数组的数组引用变量是一个局部变量,那么这个局部变量放在栈内存中。
只要类型相互兼容,就可以让一个数组变量指向另一个实际的数组,这种操作会让人产生数组长度可变的错觉。如下代码所示:
public void arrayTest()
{
int[] array1={1,2,3};
int[] array2={1,2,3,4,5,6};
System.out.println(array2.length);
array2=array1;
System.out.println(array2.length);
}
执行结果为6 3。当执行了arrray2=array1后,堆内存中原本array1指向的数组就有了两个引用,array1和啊rray都指向了最开始时array1所指向的数组。而最开始array2所指向的数组失去了引用,但是他的长度依然不会改变。这是他变成了内存垃圾,等待垃圾回收机制的回收。
Java8的增强工具类:Arrays
Java提供了一系列static修饰的方法可以直接操作数组。
- binarySearch(type[] a,type key):使用二分法查询某一元素在数组中出现的索引,如果不包含这个元素则返回负数。调用该方法时要求数组已经生序排列,否则可能不会得到正确结果。
- binarySearch(type[] a,int fromindex,int toindex,type key):同上,不过这个方法只搜索索引从fromindex到toindex的元素。