一、数组概要
1. 数组是一组数据的集合
2. 数组作为一种引用类型
3. 数组元素的类型可以是基本类型,也可以是引用类型,但同一个数组只能是同一种类型
4. 数组作为对象,数组中的元素作为对象的属性,除此之外数组还包括一个成员属性length,length表示数组的长度
5. 数组的长度在数组对象创建后就确定了,就无法再修改了
6. 数组元素是有下标的,下标从0开始,也就是第一个元素的下标为0,依次类推最后一个元素的下标为n-1,我们可以通过数组的下标来访问数组的元素
二、一维数组的声明和使用
1、数组的声明
一维数组的声明格式有以下两种:
1. 数组元素的类型[] 变量名称 = new 数组元素的类型[5];
2. 数组元素的类型[]变量名称 = new 数组元素的类型[]{a,b,c};
3. 数组元素的类型[] 变量名称 = {a,b,c};
数组元素的类型,可以是java中的任意类型,变量名称可以是任意合法的标识符。
在一行中也可以声明多个数组,例如:int[] a, b, c
2、数组的创建
数组有两种创建方式有三种
l 第一种,使用new操作符来创建数组,格式为:new 数组元素的数据类型[数组元素的个数]
1. 基本类型的数组
public class ArrayTest01 {
public static void main(String[] args) {
//声明int类型的数组,长度为5 //数组中的元素必须为int类型 int[] data = new int[5];
//对数组中的元素进行赋值,如果不赋值默认为该类型的默认值,以上数组默认为0 //如何赋值?变量名[下标],下标从0开始 data[0] = 1; data[1] = 2; data[2] = 3; data[3] = 4; data[4] = 5;
//输出数组中的元素,变量名[下标] System.out.println(data[0]); System.out.println(data[1]); System.out.println(data[2]); System.out.println(data[3]); System.out.println(data[4]);
System.out.println("-----------------------"); //采用length属性可以取得数组的长度 for (int i=0; i<data.length; i++) { System.out.println(data[i]); }
//输出指定的数组元素 System.out.println("data[3]=" + data[3]);
//会抛出ArrayIndexOutOfBoundsException异常 //数组下标越界 System.out.println("data[10]=" + data[10]);
//不能成功赋值,数组中的类型必须是一种类型 //data[0] = "iiii"; } } |
三、二维数组的声明和使用
1 | 2 | 3 |
4 | 5 | 6 |
二维数组属于多维数组,那么什么是多维数组呢,当数组元素的类型是数组时就成了多维数组,二维数组的声明格式如下:
1. 数组元素的数据类型[][] 变量名;
2. 数组元素的数据类型变量名[][];
其中方括号的个数就是数组的维数,声明二维数组如下:
int [][] data;
public class ArrayTest05 {
public static void main(String[] args) {
//声明二维数组 int[][] data = new int[2][3];
//对二维数组赋值 data[0][0] = 1; data[0][1] = 2; data[0][2] = 3;
data[1][0] = 4; data[1][1] = 5; data[1][2] = 6;
//输出二维数组 for (int i=0; i<data.length; i++) { for (int j=0; j<data[i].length; j++) { System.out.println(data[i][j]); } }
} } |
四、数组的排序
1、冒泡排序
假设有5个数字3,1,6,2,5在一个int数组中,要求按从小到大排序输出
如何采用冒泡排序算法呢?
冒泡排序的算法是这样的,首先从数组的最左边开始,取出第0号位置(左边)的数据和第1号位置(右边)的数据,如果左边的数据大于右边的数据,则进行交换,否而不进行交换。接下来右移一个位置,取出第1个位置的数据和第2个位置的数据,进行比较,如果左边的数据大于右边的数据,则进行交换,否而不进行交换。沿着这个算法一直排序下去,最大的数就会冒出水面,这就是冒泡排序。
以上示例排序过程如下:
第一遍排序
3 | 1 | 6 | 2 | 5 |
3>1,需要交换 |
1 | 3 | 6 | 2 | 5 |
3<6,无需交换 |
1 | 3 | 6 | 2 | 5 |
6>2,需要交换 |
1 | 3 | 2 | 6 | 5 |
6>5,需要交换 |
1 | 3 | 2 | 5 | 6 |
public class Sort {
public static void sort() {
Scanner input = new Scanner(System.in);
int sort[] = new int[10];
int temp;
System.out.println("请输入10个排序的数据:");
for (int i = 0; i < sort.length; i++) {
sort[i] = input.nextInt();
}
for (int i = 0; i < sort.length - 1; i++) {
for (int j = 0; j < sort.length - i - 1; j++) {
if (sort[j] < sort[j + 1]) {
temp = sort[j];
sort[j] = sort[j + 1];
sort[j + 1] = temp;
}
}
}
System.out.println("排列后的顺序为:");
for(int i=0;i<sort.length;i++){
System.out.print(sort[i]+" ");
}
}
public static void main(String[] args) {
sort();
}
}
|
2、选择排序
选择排序对冒泡排序进行了改进,使交换次数减少,但比较次数仍然没有减少。
假设有5个数字3,1,6,2,5在一个int数组中,要求按从小到大排序输出
采用选择排序,选择排序是这样的,先从左端开始,找到下标为0的元素,然后和后面的元素依次比较,如果找到了比下标0小的元素,那么再使用此元素,再接着依次比较,直到比较完成所有的元素,最后把最小的和第0个位置交换。
以上示例排序过程如下:
第一遍排序
3 | 1 | 6 | 2 | 5 |
3>1,那么使用1和后面的元素比较 |
3 | 1 | 6 | 2 | 5 |
1<6,继续使用1和后面的元素比较 |
3 | 1 | 6 | 2 | 5 |
1<2,继续使用1和后面的元素比较
|
3 | 1 | 6 | 2 | 5 |
1<5,此时已经到达末尾,不再比较了,将1值和最左边的3值,进行交换
|
1 | 3 | 6 | 2 | 5 |
扫描了所有数据,最后选择出了,最小的数据,这也是为什么叫选择排序的原因 |
第二遍排序将从下标为1的元素开始,以此类推,经过N(N-1)/2次比较,经过N次数据交互就完成了所有元素的排序。
【示例代码】
public class ArraySortTest02 {
public static void main(String[] args) {
int[] data = {3,1,6,2,5}; for (int i=0; i<data.length; i++) { int min = i; for (int j=i+1; j<data.length; j++) { if (data[j] < data[min]) { min = j; } } //进行位置的交换 if (min != i) { int temp = data[i]; data[i] = data[min]; data[min] = temp; }
} for (int i=0; i<data.length; i++) { System.out.println(data[i]); } } } |
五、数组的搜索
1、二分法(折半法)查找
查找数组中的元素我们可以遍历数组中的所有元素,这种方式称为线性查找。线性查找适合与小型数组,大型数组效率太低。如果一个数组已经排好序,那么我们可以采用效率比较高的二分查找或叫折半查找算法。
见示例
数值 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
假设,我们准备采用二分法取得18在数组中的位置
l 第一步,首先取得数组0~9的中间元素
中间元素的位置为:(开始下标0 + 结束下标9)/2=下标4
通过下标4取得对应的值15
18大于15,那么我们在后半部分查找
l 第二步,取数组4~9的中间元素
4~9的中间元素=(下标4 + 1 +下标9)/2=下标7
下标7的值为18,查找完毕,将下标7返回即可
以上就是二分或折半查找法,此种方法必须保证数组事先是排好序的,这一点一定要注意
【示例代码】
public class BinarySearchTest01 {
public static void main(String[] args) { int[] data = {11,12,13,14,15,16,17,18,19,20}; int index = binarySearch(data, 18); System.out.println(index); }
//采用折半法查询,必须建立在排序的基础上 private static int binarySearch(int[] data, int value) { //开始下标 int beginPos = 0; //结束下标 int endPos = data.length - 1;
while (beginPos <=endPos) { int midPos = (beginPos + endPos)/2; if (value == data[midPos]) { return midPos; }else if (value > data[midPos]) { beginPos = midPos + 1; }else if (value < data[midPos]) { endPos = midPos - 1; } } return -1; } } |
六、Arrays工具类
了解sort、fill和binarySearch
1、Arrays.sort的使用
import java.util.Arrays;
public class ArraysUtilTest01 {
public static void main(String[] args) { int[] data = {3,1,6,2,5}; Arrays.sort(data); for (int i=0; i<data.length; i++) { System.out.println(data[i]); } System.out.println("----------------"); for (int i=data.length-1; i>=0; i--) { System.out.println(data[i]); } } } |
2、Arrays.binarySearch的使用
import java.util.Arrays;
public class ArraysUtilTest02 {
public static void main(String[] args) { int[] data = {3,1,6,2,5}; Arrays.sort(data); for (int i=0; i<data.length; i++) { System.out.println(data[i]); } System.out.println("");
int index = Arrays.binarySearch(data, 3); System.out.println("index=" + index);
} } |
七、数组索引越界
ArrayIndexOutOfBoundsException:访问到了数组中的不存在的索引时发生。
NullPointerException:空指针异常。
数组引用没有指向实体,却在操作实体中的元素时。
动态初始化数组必须给出长度,否则将报“缺少数组维数”的错误
动态初始化二维数组时,可以只指定第一维的长度而不指定第二维的长度
当数组包含的元素是引用数据类型时,必须为每位元素实例化,否则会出现空指针异常