3/14day10_选择排序_二分查找_异常

复习

1.Map的通用方法【重点】
    put(键,值); 添加
    remove(键);
    get(键);
    put(键,值); 修改
    containsKey(键);
    containsValue(值);
2.Map的遍历方式【重点】
    a.以键找值
        Set<键> keys = map.keySet();//获取所有键的Set集合
        for(K 键 : keys){ //遍历所有的键
            V 值 = map.get(键); //以键找值
            打印
        }
    b.键值对方式
        Set<Map.Entry<键,值>> entries = map.entrySet();//获取所有键值对的Set集合
        for(Map.Entry<键,值> 键值对 : entries){ //遍历所有的键值对
            键值对.getKey(); //获取键
            键值对.getValue();//获取值
            打印
        }
3.集合的嵌套
    a.ArrayList<ArrayList<String>>
    b.ArrayList<HashMap<String,Integer>>
    c.HashMap<String,HashMap<String,Integer>>
4.斗地主【重点,3遍历】
5.冒泡排序【理解】
    核心: 依次比较相邻的两个元素,大的往后走,小的往前走
    代码:
        for(int i = 0;i < arr.length-1;i++){
            for(int j = 0;j < arr.length-1-i;j++){
                if(arr[j] > arr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                }
            }   
        }   

今日内容

  • 选择排序
  • 二分查找
  • 异常【异常的继承体系是重点】
  • 异常的处理【try...catch处理方式是重点】
  • 自定义异常

选择排序

介绍

  • 另外一种排序的方式,选中数组的某个元素,其后面的元素依次和选中的元素进行两两比较,将较大的数据放在后面,依次从前到后选中每个元素,直至所有数据按要求完成排序
  • 如果有n个数据进行排序,总共需要比较n-1次
  • 每一次比较完毕,下一次的比较就会少一个数据参与

图解选择排序

代码实现

/*
    选择排序:
        另外一种排序的方式,选中数组的某个元素,其后面的元素依次和选中的元素进行两两比较,将较大的数据放
在后面,依次从前到后选中每个元素,直至所有数据按要求完成排序
 */
public class ArrayDemo {
    public static void main(String[] args) {
        //定义一个数组
        int[] arr = {7, 6, 5, 4, 3};
        System.out.println("排序前:" + Arrays.toString(arr));
        // 这里减1,是控制比较的轮数
        for (int x = 0; x < arr.length - 1; x++) {
            // 从x+1开始,直到最后一个元素
            for (int i = x+1; i < arr.length; i++) {
                if (arr[x] > arr[i]) {
                    int temp = arr[x];
                    arr[x] = arr[i];
                    arr[i] = temp;
                }
            }
        }
        System.out.println("排序后:" + Arrays.toString(arr));
    }
}

二分查找

普通查找和二分查找

  • 普通查找: 给定数组,找到对应数组的索引. 只能从前往后依次遍历
  • 二分查找:给定数组, 必须是有自然顺序的(比如,从小到大), 从数组中找到某个元素的索引.
    原理:每一次都去获取数组的中间索引所对应的元素,然后和要查找的元素进行比对,如果相同就返回索引;如果不相同,就比较中间元素和要查找的元素的值;小的话,就去掉后一半.拿前半比较

二分查找图解

代码实现

    public static void main(String[] args) {
        int[] arr = {10, 14, 21, 38, 45, 47, 53, 81, 87, 99};
        int index = binarySerach(arr, 38);
        System.out.println(index);
    }
    /**
     * 二分查找方法
     * @param arr 查找的目标数组
     * @param number 查找的目标值
     * @return 找到的索引,如果没有找到返回-1
     */
    public static int binarySerach(int[] arr, int number) {
        int start = 0;
        int end = arr.length - 1;
 
        while (start <= end) {
            int mid = (start + end) / 2;
            if (number == arr[mid]) {
                return mid ;
            } else if (number < arr[mid]) {
                end = mid - 1;
            } else if (number > arr[mid]) {
                start = mid + 1;
            }
        }
        return -1;  //如果数组中有这个元素,则返回
    }

异常

介绍

异常:指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止.
在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.

异常的继承体系[重点]

Throwable 所有异常和错误的根类
|-- Error 错误类 硬件错误,或者说不可抗抗拒的意外.程序员无法处理
|-- Exception 异常类 写代码不当造成, 程序员必须处理好的

  • Throwable中的常用方法:
public void printStackTrace() :打印异常的详细信息。
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace
public String getMessage() :获取发生异常的原因。
提示给用户的时候,就提示错误原因。
public String toString() :获取异常的类型和异常描述信息(不用)。

异常的分类

我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。

  • 编译时异常(必须在类名中声明抛出异常)
    checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败
    编译时异常是Exception 以及Exception的子类(RuntimeException除外)

  • 运行时异常(不用在类名中声明异常)
    runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)

  • 图解分类


  • 图解异常产生过程

异常处理

java 中异常相关的五个关键字
throw, throws, try...catch finally

throw抛出异常(写在方法内)

  • throw是一个关键字

  • 想要先上抛出异常时, 使用throw关键字

  • 格式
    throw 异常对象
    throw new 异常类();

  • 代码演示

 public class TestException02 {
        public static void main(String[] args) {
            int[] arr = {1,2,3};
            //调用方法
            int element = getElement(arr);
            System.out.println(element);
        }

        public static int getElement(int[] arr){
            //自己判断,数组是否有3索引
            if (arr.length < 4) {
               //抛出异常
                throw new ArrayIndexOutOfBoundsException("哥们越界了!!!");
            }
            //获取数组中索引为3的元素
            int num = arr[3];
            //返回num
            return num;
        }
    }

Objects非空判断

Objects 是个工具类
其中有个静态方法 叫做空指针容忍方法

public static <T> T requireNonNull(T obj) :查看指定引用对象不是null。
public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

遇到异常的两种处理方式[重点]

编译时遇到异常,必须处理, 采用以下两种方式
运行时异常, 编译时期不需要处理,不需要在类名上进行声明异常, 运行后根据异常信息修改即可

throws 声明异常(写在方法定义上)

  • 声明异常格式
    throws关键字是给方法使用的, 为该方法做出声明,将问题标识出来,报告给调用者。
    如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。
    格式:
    修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
    代码演示
public class ThrowsDemo {
    public static void main(String[] args) throws FileNotFoundException {
        read("a.txt");
    }
 
    // 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
    }

try...catch捕获异常

自己写的抓住异常的话, 虚拟机就不会拿到异常,不会立刻终止程序,还是会继续运行
如果异常出现的话,会立刻终止程序,所以我们得处理异常:

  1. 该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
  2. 在方法中使用try-catch的语句块来处理异常。
    try-catch的方式就是捕获异常。
    捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。
    捕获异常语法如下:

try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
注意:try和catch都不能单独使用,必须连用。

  • 捕获异常的格式
    try{
    可能出现异常的代码
    } catch(XxxExcption e){
    //处理异常
    e.printStackTrace();//直接打印
    save(e);//将异常保存到异常日志(或者数据库)
    }

  • 代码演示

public class TryCatchDemo {
    public static void main(String[] args) {
        try {// 当产生异常时,必须有处理方式。要么捕获,要么声明。
            read("b.txt");
        } catch (FileNotFoundException e) {// 括号中需要定义什么呢?
            //try中抛出的是什么异常,在括号中就定义什么异常类型
            System.out.println(e);
        }
        System.out.println("over");//抓住异常之后的代码还是会继续运行
    }
    /*
     *
     * 我们 当前的这个方法中 有异常  有编译期异常
     */
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
    }
}
  • 捕获到异常之后, 查看异常信息
    1.直接打印出来,调用e.printStachTrace(); 开发阶段
    2.可以先保存出来,比如保存到异常日志,异常系统之类

finally代码块[IO流时使用]

  • finally代码块格式
    finally一般不单独使用, 配合try...catch使用
    try...catch....finally...:自身需要处理异常,最终还得关闭资源。
    写在finally中的代码,无论是否有异常, 都会执行

  • finally代码块的作用
    一般用于写释放资源,关闭连接等代码
    当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。

  • 伪代码演示

public class TryCatchDemo4 {
    public static void main(String[] args) {
        try {
            read("a.txt");
        } catch (FileNotFoundException e) {
            //抓取到的是编译期异常  抛出去的是运行期 
            throw new RuntimeException(e);
        } finally {
            System.out.println("不管程序怎样,这里都将会被执行。");
            xxx.close();
        }
        System.out.println("over");
    }
    /*
     *
     * 我们 当前的这个方法中 有异常  有编译期异常
     */
    public static void read(String path) throws FileNotFoundException {
        if (!path.equals("a.txt")) {//如果不是 a.txt这个文件 
            // 我假设  如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常  throw
            throw new FileNotFoundException("文件不存在");
        }
    }
}

异常的注意事项

  • 运行时异常被抛出可以不处理。即不捕获也不声明抛出。
  • 如果父类的方法抛出了多个异常,子类覆盖(重写)父类方法时,只能抛出相同的异常或者是他的子集。
    比如父类抛出100个异常,子类重写该方法时,只能抛出这100个或者这100个中的需要的几个。
  • 父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
  • 当多异常分别处理时,捕获处理,前边的类不能是后边类的父类
  • 在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收。
  • 多个异常使用捕获又该如何处理呢?
    1.多个异常分别处理。
    2.多个异常一次捕获,多次处理。所有异常一起try,分开catch
    3.多个异常一次捕获一次处理。所有异常一起try,一个catch

使用一次捕获多次处理方式,格式如下:
注意事项: 多个catch捕获异常必须是 前面先是捕获子类异常,后面才能是捕获父类异常

try{
     编写可能会出现异常的代码
}catch(异常类型A  e){  当try中出现A类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}catch(异常类型B  e){  当try中出现B类型异常,就用该catch来捕获.
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

多个异常一次捕获一次处理。所有异常一起try,一个catch

try{
     编写可能会出现异常的代码
}catch(Exception  e){  用异常的父类来捕获
     处理异常的代码
     //记录日志/打印异常信息/继续抛出异常
}

自定义异常

自定义异常概念

  • 概念:自定义一个异常类.(每一个异常类就是一种异常情况)
    因为JDK不可能定义所有的异常情况.

自定义异常步骤

1.创建一个类, 类名必须叫做XxxException
2.继承Exception或者RuntimeException
3.提供两个构造,无参构造+带有String参数的构造

代码演示

需求:我们模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。
首先定义一个注册异常类RegisterException:

// 业务逻辑异常
public class RegisterException extends Exception {
    /**
     * 空参构造
     */
    public RegisterException() {
    }
 
    /**
     *
     * @param message 表示异常提示
     */
    public RegisterException(String message) {
        super(message);//表示调用父类的构造
    }
}

模拟登陆操作,使用数组模拟数据库中存储的数据,并提供当前注册账号是否存在方法用于判断。

public class Demo {
    // 模拟数据库中已存在账号
    private static String[] names = {"bill","hill","jill"};
   
    public static void main(String[] args) {     
        //调用方法
        try{
              // 可能出现异常的代码
            checkUsername("nill");
            System.out.println("注册成功");//如果没有异常就是注册成功
        }catch(LoginException e){
            //处理异常
            e.printStackTrace();
        }
    }
 
    //判断当前注册账号是否存在
    //因为是编译期异常,又想调用者去处理 所以声明该异常
    public static boolean checkUsername(String uname) throws LoginException{
        for (String name : names) {
            if(name.equals(uname)){//如果名字在这里面 就抛出登陆异常
                throw new LoginException("亲"+name+"已经被注册了!");
            }
        }
        return true;
    }
}

今日小结

能够理解选择排序的执行原理
    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;
            }
        }
    }
能够理解二分查找的执行原理
    public static int binarySearch(int[] arr,int key){
        int left = 0;
        int right = arr.length - 1;

        while(left <= right){
            int middle = (left+right)/2;
            if(arr[middle] > key){
                right = middle - 1;
            }else if(arr[middle] < key){
                left = middle + 1;
            }else{
                retrun middle;
            }
        }
        return -1;
    }
    
能够辨别程序中异常和错误的区别
    Throwable
        Exception 异常一般是程序编写不当造成的,程序有能力处理
        Error 错误一般硬件引起的(系统崩溃,内存溢出),程序员一般无法处理
说出异常的分类
    Throwable 
        |- Error
        |- Exception
            |- 编译时异常 Exception以及其子类(RuntimeException除外) 需要强制进行 throw try...catch
            |- 运行时异常 RuntimeException以及其子类
列举出常见的三个运行期异常
    ArrayIndexOutOfBoundsException
    NullPointerException
    ClassCastException 向下转型时出现的类型转换异常
    ConcurrentModificationException 并发修改异常,迭代器使用过程中直接向集合添加/删除元素
能够使用try...catch关键字处理异常【重点】
    try{
        方法名(实际参数);   
    }catch(XxxException e){
        e.printStackTrace();   
    }
能够使用throws关键字处理异常【重点】
    throws 给方法使用的,表示声明抛出异常,该调用的调用者要处理异常
    public void 方法名(参数列表) throws Exception{
        %^&*()%^&(
    }
能够自定义并使用异常类
    完成自定义异常的练习案例(3遍历)    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容