1. 数组的定义
定义:同一种类型数据的集合。其实数组就是一个容器。
2. 好处
可以自动给数组中的元素从0开始编号,方便操作这些元素。
3. 格式
元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
int [] arr= new int[5];
或者 int [] arr=new int[5]{1,4,5,6,7};
int [] arr={1,4,5,6,7};
4. 数组的内存分配及特点
例如 int[] arr = new int[4];
5. 内存结构
5.1 Java程序在运行时,需要在内存中分配空间。为了提高运算效率,又对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
5.2 内存的划分:
1、寄存器。
2、本地方法区。
3、方法区。
4、栈内存。
5、堆内存。
5.3 栈内存
用于存储局部变量,当变量所属的作用域一旦结束,所占空间会自动释放。
5.4 堆内存
数组和对象,通过new建立的实例都存放在堆内存中。
每一个实体都有内存地址值。
实体中的变量都有默认初始化值,根据类型的不同而不同。整数类型是0,小数类型是0.0或0.0f,boolean类型是false,char类型是'\u0000'。
如果将数组的引用实体设置为null,也就是实体不再被使用,那么会在不确定的时间内被垃圾回收器(GC)回收。
6. 数组操作常见问题(涉及异常)
6.1 脚标越界异常(ArrayIndexOutOfBoundsException)
int[]arr = new int[2];
System.out.println(arr[3]);//访问了不存在的脚标
6.2 空指针异常(NullPointerException)
int[]arr = null;
System.out.println(arr[0]);
arr引用没有指向实体,却在操作实体中的元素时。
7. 数组常见操作
7.1 遍历打印数组
使用for循环
class ArrayDemo{
public static void main(String[] args) {
int[] arr = {1,3,2, 7};
for(int x = 0; x < arr.length; x += 1){
System.out.println("arr[" + x + "] = " + arr[x] + ";");
}
}
}
数组中有一个属性可以直接获取到数组元素个数:length.
使用方式:数组名称.length
7.2 获取最大值最小值
以最大值为例
思路:将第一设为最大值,遍历数组,每次比较数据,如大于最大值,则交换,否则不交换。
public static int getMax(int[] arr){
int max = arr[0];
for(int x = 1; x < arr.length; x++){
if(arr[x] > max)
max = arr[x];
}
return max;
}
最小值原理相同。
7.3 排序
7.3.1 冒泡排序
分析
1、首先在第一轮排序中,数组从第一个元素到倒数第二个元素依次与其右边的元素进行比较,如果左边的元素大于右边的元素,那么两个元素就互换。
即01比、12比、23比…按需求交换。
2、经过第一轮比较,最大的元素就已经存储到数组最右边的结点中了。
3、第二轮排序则是从第一个元素到倒数第三个元素依次与其右边的元素进行比较,如果左边的元素大于右边的元素,那么两个元素就互换。
4、依照此方式,一直到只有第一和第二个元素互相比较而结束。
流程
代码
public static void bubbleSort(int[] arr){
for(int x = 0; x < arr.length - 1; x++){
for(int y = 0; y < arr.length - 1 -x; y++){
//每次比完,最大值在最高位,下一次不用比较,故减x
if(arr[y] > arr[y+1]){
int temp = arr[y];
arr[y] = arr[y+1];
arr[y+1] = temp;
}
}
}
}
7.3.2 选择排序
分析
1、首先拿数组第一个元素依次与除其自身外的其他每个元素顺序比较,如果第一个元素大于剩下的某个元素,就互换内容。
2、经过第一轮比较之后,此时第一个元素就是数组中最小的元素。然后再拿第二个元素与除第一个元素和其自身的元素进行比较,如果第二个元素大于剩下的某个元素,就互换内容。
3、依次类推,直到最后一个元素。
流程
代码
public static void selectSort(int[] arr)
{
for(int i=0;i<arr.length-1;i++)
{
for(int j=i+1;j<arr.length;j++)
{
//每次比较都交换会比较耗内存,也可以定义一个角标来实现,获取最小值的角标,和第一位交换。
if(arr[i]>arr[j])
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
需要注意的是, 返回值类型可以是void,因为传入一个arr数组,排序后仍然可以通过arr操作这个排序后的数组,而不用另外接收。
7.3.3 简单查找
遍历寻找符合条件的元素。
代码
public static int getIndex(int[] arr, int key){
for(int x = 0; x < arr.length; x++){
if(arr[x] == key)
return x;
}
return -1;//-1表示未找到
}
}
7.3.4 折半查找
前提:数组是有序的!
思路:
1、设置三个变量记录角标:min、max、mid。min初始值为0,max为数组最大角标,mid为(max+min)/2。
2、查看mid角标的元素是否与待查找的值相等,如果相等,则直接返回角标值,程序终止执行。
3、如果待查找的值小于角标为mid的元素值,那么说明待查找的元素的位置可能在min与mid角标之间。设置max =mid - 1,mid = (max + min)/2,重复第1、2步的操作。
4、如果待查找的值大于角标为mid的元素值,那么说明待查找的元素的位置可能在mid与max角标之间。设置min =mid + 1,mid = (max + min)/2,重复第1、2步的操作。
5、如果数组中不存在待查找的元素,那么按照如上流程,最终min角标值会大于max角标值,此时返回-1。
代码
public static int binarySearch(int[] arr, int key){
int max,min,mid;
min = 0;
max = arr. length - 1;
while(min <= max){
mid = (max + min) >> 1;
if(key > arr[mid])
min = mid + 1;
else if (key < arr[mid])
max = mid - 1;
else
return mid;
}
return -1;
}
}
8. 练习 进制转换
//进制转换的通用方法
public static void trans(int num, int base,int offset){
//要转换的数字、转换的进制、对应的位移数
if(num == 0){
System.out.println("0" );
return;
}
char[] chs = {'0','1' ,'2' ,'3' ,
'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' };
//查表法,将对应的元素做成一个数组存放
char[] arr = new char[32];//最多32位
int pos = arr.length ;
while(num != 0){
int temp = num & base;
//十六进制&上15,八进制&7,二进制&1
arr[--pos] = chs[temp];
num = num >>> offset;
//十六进制右移4位,八进制右移3位,二进制右移1位。
//可以计算负数
}
//System. out.println("pos = " + pos);
for(int x = pos; x < arr.length; x++){
//从pos打印到arr.length-1.
System.out.print(arr[x]);
}
System.out.println();
}
}
9. 二维数组
int [][] arr=new int[3][4];
意思是arr中有3个一维数组,每个数组有4个元素。
打印一维数组结果:[I@哈希码
打印二维数组结果:[[I@哈希码
练习: int [] x,y[];
声明了一个一维数组 x
同时声明了一个二维数组 y
求二维数组的左右元素的和
class Array2Demo
{
public static void main(String[] args){
int sum = 0;
int[][] arr = {{3,1,7},{5,8,2,9},{4,1}};
for(int x = 0; x < arr.length; x++){
for(int y = 0; y < arr[x].length; y++){
sum += arr[x][y];
}
}
System. out.println("sum = " + sum);
}
}
结果:sum=40