一、数组——静态初始化——常见问题
1、书写格式1: int[] arr = new int[3];//常用格式 int arr[] = new int[3]; 以上两种书写格式都OK。 格式2(静态初始化方式): 元素类型[] 数组名 = new 元素类型[]{元素,元素……}; 示例: int[] arr = new int[]{3,5,1,7}; int[] arr = {3,5,1,7};//数据明确时常用格式 注意: 不可以将数组定义成如下格式: int[] arr = new int[3]{1,2,3}; 2、数组在操作时常见问题: 示例一: int[] arr = new int[3]; System.out.println(arr[3]);//数组角标越界;编译OK,运行时出错。原因是编译时检查语法OK,运行时才通过new建立数组,分配空间,而打印时找不到3角标的元素,报错。 //ArrayIndexOutOfBoundsException:3 示例二: int[] arr = new int[3]; arr = null ; System.out.println(arr[1]); //运行时出现:NullPointerException//空指针异常:当引用没有任何指向值为null时,该引用还在用于操作实体。二、数组——常见操作——遍历
遍历:获取数组中的元素class ArrayDemo1 { public static void main(String[] args) { int[] arr = {2,4,7,8,12,73}; printArray(arr); } //定义一个遍历并打印数组的功能 public static void printArray(int[] arr) { //打印数组长度 System.out.println("length: "+arr.length); //遍历数组 System.out.println("["); for (int x=0; x<arr.length ;x++ ) { if(x!=arr.length-1) System.out.print(arr[x]+", "); else System.out.println(arr[x]+"]"); } } }
注意一:
数组中有一个属性可以直接获取数组长度。.length-->使用方式:数组名称.length
注意二:
数组不可以直接打印。直接打印,其结果是一个地址值。
例如:
System.out.println(arr);//[I@15db9742
//[ 代表数组; I 代表数组中的元素类型是int类型; @后面部分代表内存地址值。三、数组——常见操作——获取最值
获取最大值:class ArrayDemo2 { public static void main(String[] args) { int[] arr = {3,4,7,8,1,12,9}; int max = getMax(arr); } //方法一:记住最大元素 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; } //方法二:记住最大元素的角标 public static int getMax_2(int[] arr) { int max = 0; for (int x=1 ;x<arr.length ;x++ ) { if(arr[x]>arr[max] max = x; } return arr[max]; } }//获取最小值则更改if条件即可。
四、数组——排序——选择排序
选择排序:头角标和其他角标比较,如果符合条件就换位。
class ArrayDemo3 { public static void main(String[] args) { int[] arr = {5,4,7,8,1,12,9}; selectSort(arr); } public static void selectSort(int[] arr) { for (int x=0; x<arr.length-1 ;x++ )//x<arr.length-1 是因为到最后一个角标时不需要参与比较。 { for (int y=x+1; y<arr.length ;y++ ) { if(arr[y]<arr[x]) { int temp = arr[y]; arr[y] = arr[x]; arr[x] = temp; } } } } }//选择排序特点:内循环结束一次,最值出现在头角标位置上。
五、数组——排序——冒泡排序
冒泡排序:相邻两个元素进行比较,如果符合条件就换位。class ArrayDemo4 { public static void main(String[] args) { int[] arr = {5,4,7,8,1,12,9}; bubbleSort(arr); } public static void bubbleSort(int[] arr) { for (int x=0; x<arr.length-1 ;x++ ) {//外循环控制循环次数 for (int y=0; y<arr.length-x-1 ;y++ ) { if (arr[y]>arr[y+1]) { int temp = arr[y]; arr[y] = arr[y+1]; arr[y+1] = temp; } } } } }//冒泡排序特点:最值往后跑;内循环结束一次,最值出现在末位。
注意:
java已经定义好的一种排序方式,供开发中使用:
import java.util.*;
Arrays.sort(arr);
六、数组——排序——位置置换功能抽取
在数组排序时,都需要进行位置置换;位置置换功能出现了重复,可以定义一个功能。
public static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
完整代码:class Demo { public static void main(String[] args) { int[] arr = {32,55,6,91,8,7,11,24}; printArray(arr); bubbleSort(arr); printArray(arr); } //冒泡排序 public static void bubbleSort(int[] arr) { for (int x=1 ; x<arr.length ; x++ ) { for (int y=0 ; y<arr.length-x ; y++ ) { if (arr[y]>arr[y+1]) { swap(arr ,y ,y+1); } } } } //选择排序 public static void selectSort(int[] arr) { for (int x=0 ; x<arr.length-1 ; x++ ) { for ( int y=x+1 ; y<arr.length ; y++ ) { if (arr[y]<arr[x]) { swap(arr, x, y); } } } } //位置置换功能抽取 public static void swap(int[] arr,int a ,int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } //遍历数组并打印 public static void printArray(int[] arr) { System.out.print("["); for (int x=0; x<arr.length ; x++ ) { if(x!=arr.length-1) System.out.print(arr[x]+","); else System.out.println(arr[x]+"]"); } } }
七、数组——折半查找
简单方法:class ArrayTest1 { public static void main(String[] args) { int[] arr = {5,4,7,8,1,12,9}; int index = getIndex(arr,7); } public static int getIndex(int[] arr, int num); { for (int x=0 ;x<arr.length ;x++ ) { if (arr[x]==num) return x; } return -1; } }
折半查找:可以提到效率,但必须保证数组是有序的。class ArrayTest2 { public static void main(String[] args) { int[] arr = {2,5,7,9,12,45,77,87,123,453}; int index = halfSearch(arr,45); System.out.println("index="+index); } public static int halfSearch(int[] arr,int key) { int min = 0 ; int max = arr.length-1 ; int mid = (min+max)/2 ; while(arr[mid]!=key) { if(key>arr[mid]) min = mid + 1 ; else //key<arr[mid] max = mid - 1 ; if(min>max) return -1 ; mid = (max+min)/2 ; } return mid ; } }
插入一个元素,保证原数组仍然有序:
将ArrayTest2中的代码 return -1; 改为 return min; 即可。八、数组——进制转换——十进制转二进制
思路:对于正数的十进制转换为二进制,其实就是一个模2和除2的过程。
因为这个过程需要重复去做,所以是一个循环;循环条件:只要大于0就循环。
代码:
class ArrayTest3 { public static void main(String[] args) { toBin_2(6); } //初期代码,打印结果为反向,为011 public static void toBin_1(int num) { while (num>0) { System.out.print(num%2); num = num>>1; } } //优化代码(但使用到了StringBuffer),打印结果正常,为110 public static void toBin_2(int num) { StringBuffer sb = new StringBuffer(); while (num>0) { sb.append(num%2); num = num / 2 ; } System.out.println(sb.reverse()); } }
九、数组——十进制转十六进制
十进制转十六进制,其实也是一个模16和除16的过程,但是这样比较麻烦。
所以可以使用一个简便方法:
1、将该数mun和15进行 & 运算,得到其最低四位的值temp,并将temp转为16进制符号;
2、再将mun右移4位得到一个新的值重复第1步;
3、循环1和2,并控制循环次数:因为mun为int类型,占32个二进制位,循环一个右移4位,所以需循环8次。
代码:
class ArrayTest4 { public static void main(String[] args) { toHex(60); } public static void toHex(int num) { StringBuffer sb = new StringBuffer(); for (int x=0; x<8 ;x++ ) { int temp = num & 15; if(temp>9) //System.out.println((char)(temp-10+'a')); sb.append((char)(temp-10+'a')); else //System.out.println(temp); sb.append(temp); num = num >>> 4; } System.out.println(sb.reverse()); } }
十、数组——十进制转十六进制(查表法)
查表法: 将所有十六进制的元素当中数组的元素存储起来,建立对应关系;每一次用num&15后的值作为元素的索引去查建立好的表,就可以找到对应的元素,也就是十六进制符号。
char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} 代码:class ArrayTest5 { public static void main(String[] args) { toHex(60); } public static void toHex(int num) { char[] arr = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; StringBuffer sb = new StringBuffer(); for (int x=0; x<8 ;x++ ) { int n = num & 15; //System.out.println(arr[n]); sb.append(arr[n]); num = num >>> 4; } System.out.println(sb.reverse()); } }
不使用 StringBuffer 时,代码如下:
class ArrayTest6 { public static void main(String[] args) { toHex(60); } public static void toHex(int num) { char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char[] arr = new char[8];//定义一个数组,用于存储运算后的数据 int pos = arr.length;//定义一个指针,用于操作角标 while (num!=0) { //将数据存储到数组的前一个角标中 int n = num & 15; arr[--pos]=chs[n];//将运算后的结果存储到给数组中 num = num >>> 4; } for (int x=pos; x<arr.length ;x++ )//从有效位开始循环输出。 { System.out.print(arr[x]); } } }
十一、数组——查表法——十进制转二进制
思路同上一题:class ArrayTest7 { public static void main(String[] args) { toBin(6); } public static void toBin(int num) { char[] chs = {'0','1'}; char[] arr = new char[32]; int pos = arr.length; while(num!=0) { int n = num & 1; arr[--pos] = chs[n]; num = num >>> 1; } for (int x=pos; x<arr.length ;x++ ) { System.out.print(arr[x]); } } }
十二、数组——进制转换优化
如果在一个类中同时定义十进制转换成二进制、八进制、十六进制,代码会出现重复。
优化代码如下:class ArrayTest8 { public static void main(String[] args) { toBin(6); toHex(60); toOctal(0); } //十进制 --> 二进制 public static void toBin(int num) { trans(num,1,1); } //十进制 --> 十六进制 public static void toHex(int num) { trans(num,15,4); } //十进制 --> 八进制 public static void toOctal(int num) { trans(num,7,3); } //其中num是需要转换的数,base是参与 & 运算的数,offset是右移的位数 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]; int pos = arr.length; while (num!=0) { int n = num & base; arr[--pos]=chs[n]; num = num >>> offset; } for (int x=pos; x<arr.length ;x++ ) { System.out.print(arr[x]); } System.out.println(); } }
十三、二维数组
概念:数组中的数组
格式一:
int[][] arr = new int[3][2];
含义:
定义了名称为arr的二维数组;
二维数组中有3个一维数组;
每一个一维数组中有2个元素;
一维数组的名称分别为arr[0],arr[1],arr[2];
给第一个一维数组1角标位赋值为12的写法是:arr[0][1] = 12;
格式二:
int[][] arr = new int[3][];
含义:
二维数组中有3个一维数组;
每一个一维数组都是默认初始化值null;
//引用数据类型默认初始化值都是null;
可以对这三个一维数组分别进行初始化:
arr[0] = new int[3];//新开辟空间,并将空间的地址值赋给arr[0],并覆盖null;
arr[1] = new int[2];
arr[2] = new int[4];
注意:
直接打印二维数组,结果是二维数组地址值。
例如:
int[][] arr = new int[3][2];
System.out.println(arr);
//[[I@15db9742 //[[ 表示二维数组
System.out.println(arr[1]);//[I@15db9742
System.out.println(arr[1][1]);//结果是0
System.out.println(arr.length);//打印的是二维数组的长度,结果是3;
System.out.println(arr[0].length);//打印的是二维数组中第一个小数组的长度,结果是2;
格式三:
int[][] arr = {{2,4,5},{1,7},{3,6,9,0}};
需求:对二维数组arr所有元素求和。class Array2Demo { public static void main(String[] args) { int[][] arr = {{2,4,5},{1,7},{3,6,9,0}}; int sum = 0; for (int x=0 ;x<arr.length ;x++ ) { for (int y=0; y<arr[x].length ;y++ ) { sum = sum + arr[x][y]; } } System.out.println(sum); } }
十四、二维数组练习
前提:
一维数组的不同写法: int[] x; int x[];
二维数组的不同写法: int[][] y; int y[][]; int[] y[];
需求:根据第一行代码,判断a~f书写是否正确。(//后面是答案)
int[] x,y[];//x一维,y二维。//int[] x;//int[] y[];
//第一个中括号跟着类型int走,对后面的变量都有效;第二个中括号跟着变量y走,值对变量y有效。
a.
x[0] = y;//error
b.
y[0] = x;//yes
c.
y[0][0] = x;//error
d.
x[0][0] = y;//error
e.
y[0][0] = x[0];//yes
f.
x=y;//error