一、数组
(一)数组查找
常用的两种查找方式
- 顺序查找
- 二分查找
1.顺序查找
概念:通过数组下标提取元素,与目标进行对比,如果找到匹配元素则返回下标;如果未找到则返回特定值(通常为-1)。
备注:通过循环实现。
public static int orderSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
2.二分查找(折半查找)
概念:通过赋予数组中间下标提取元素,与目标进行对比
- 如果匹配则返回下标
- 如果比当前元素大,则将查询区间重置为(当前下标+1)至最大下标,再取中间下标元素与目标进行对比
- 如果比当前元素小,则将查询区间重置为最小下标至(当前下标-1),再取中间下标元素与目标进行对比
只适用于有序数组!
备注:跳出判断:当查找到最大(小)下标时,lowPoint=highPoint,进入循环体,并执行最小下标+1或最大下标-1语句,实现lowPoint>highPoint情形,跳出while循环。
public static int binarySearch(int[] array, int target) {
int lowPoint = 0;
int highPoint = array.length - 1;
int midPoint = (lowPoint + highPoint) / 2;
while (lowPoint <= highPoint) {
midPoint = (lowPoint + highPoint) / 2;
if (target > array[midPoint]) {
lowPoint = midPoint + 1;
} else if (target < array[midPoint]) {
highPoint = midPoint - 1;
} else {
return midPoint;
}
}
return -1;
}
(二)数组内存
数组的存储由栈内存和堆内存实现
- 栈内存:存储对象的引用(句柄)
- 堆内存:存储对象主体(new表示建立内存空间)
- 方法区(常量池):存储运行时常量,如:字符串、static
String[] stringArray1 = {"Test"};
上方语句等价于下方语句
String[] stringArray1 = new String[1];//stringArray1在栈内存中
stringArray1[0] = "Test";//stringArray1[0]在堆内存中
//Test在方法区中
特别说明(String)
下面两种方法创建的string1存储内容不同!
- (上)方法存储的是方法区的引用;
- (下)方法存储的是堆内存的引用;
String string1 = "Test";
//栈内存<--(引用)--方法区
String string1 = new String("Test");
//栈内存<--(引用)--堆内存(String1的主体,含有Test引用)<--(引用)--方法区
(三)数组拷贝
数组拷贝有两种情形
- 浅拷贝:拷贝引用地址
- 深拷贝:拷贝值
public static void main(String[] args) {
//创建数组testArray
int[] testArray = new int[1];
testArray[0] = 007;
//testArray浅拷贝至array1
int[] array1 = testArray;
//testArray深拷贝至array2
int[] array2 = new int[1];
array2[0] = testArray[0];
}
(四)Arrays工具类
常用的Arrays工具类
- Arrays.binarySearch(数组名,元素)
说明:按二分查找方式匹配目标元素,(只适用于有序数组)返回一个下标值 - Arrays.copyOf(数组名,长度)
说明:深拷贝数组至新的数组,长度允许不一致,返回一个数组 - Arrays.equals(数组名1,数组名2)
说明:判断数组1和数组2是否相等,返回一个布尔值 - Arrays.fill(数组名,值)
说明:使用指定值填充数组,无返回值 - Arrays.sort(数组名)
说明:排列数组,无返回值 - Arrays.toString(数组名)
说明:将数组转换为字符串类型,返回一个字符串
二、二维数组
(一)二维数组内存
概念:二维数组是存储一维数组的容器,里面的元素为一维数组
- 二维数组位于栈内存,存储指向堆内存数组的引用
- 堆内存中的数组存储着同位于堆内存的一维数组
(二)创建二维数组
二维数组的创建方式有两种
- 静态初始化
- 动态初始化
public static void main(String[] args) {
//静态初始化矩形数组
int[][] arrar1 = new int[3][3];
//静态初始化锯齿数组
int[][] array2 = new int[3][];
array2[0] = new int[3];
array2[1] = new int[2];
array2[2] = new int[1];
//动态初始化矩形数组
int[][] array3 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
//动态初始化锯齿数组
int[][] array4 = {{1, 2, 3}, {4, 5}, {6}};
}
三、异常
(一)概念
Java的可抛出类(throwable)存在两个子类:错误类(Error)、异常类(Exception)
- 错误:通常为JVM错误,无法在程序中处理
- 异常:分为运行时异常(RuntimeException)和检查异常(其他),可以在程序中处理
- 运行时异常,编译器不检查的异常,通常为逻辑错误,不一定要处理
- NullPointerException - 空指针异常
- ArrayIndexOutOfBoundsException - 数组越界异常
- ArithemicException - 算术异常
- ClassCaseException - 类型转换异常
- NumberFormatException - 数字格式化异常
- InputMismatchException - 输入不匹配异常
- 检查异常,编译器检查的异常,通常为语法格式错误,必须要处理
- FileNotFoundExcetpion - 文件无法找到异常
- IOException - IO异常
- SQLException - SQL异常
- 运行时异常,编译器不检查的异常,通常为逻辑错误,不一定要处理
(二)处理异常
1.捕获异常
通常使用try-catch语句捕获异常,有以下几点需要留意
- 可使用多个catch语句
- 作用域小的(如:NullPointerException)异常写在前面,作用域大的(如:Exception)异常写在后面
- finally为可选内容
public static void main(String[] args) {
try {
int i = 0;//try作用域,存放需要检测的语句
} catch (NullPointerException e) {
e.printStackTrace();//显示异常信息
//此处的语句,不产生异常不被执行
} catch (Exception e) {
e.printStackTrace();
} finally {
//此处的语句,无论是否产生异常均被执行
}
//此处的语句,产生异常不被执行
}
生成try-catch语句的快捷键:Ctrl+alt+T
注意快捷键要在方法中使用,在类中无效!
2.抛出异常
通常在方法上增加throws关键字,实现方法内异常的抛出,含throws关键字方法的调用者,需要对其进行处理,可选择以下两种方式
- 继续增加throws关键字向上抛出
- 使用try-catch语句进行处理
异常–>方法2–>方法1–>main–>JVM
2.1抛出异常的特点
- 异常尽量在main或之前进行处理,切勿抛给JVM
- 下游方法抛出的异常(NullPointerException)要小于上游方法(Exception)抛出的异常
- 子类不能抛出比父类更大的异常
public static void testThrows1() throws NullPointerException {
//内置产生异常的代码块
}
public static void testThrows2() throws Exception {
testThrows1();
}
2.2主动抛出异常
使用throw+异常实例的语句,可以主动向外抛出一个异常,通常警示方法的调用者勿使用错误实参。
Exception exception1 = new Exception("主动异常");//自定义异常
try {
throw exception1;//抛出主动异常
} catch (Exception e) {
e.printStackTrace();
}
2.3自定义异常
通过继承Exception类,实现自定义异常
class customizeException extends Exception {
public customizeException(String message) {
super(message);//将子类构造方法中的message参数传递给父类
}
}