【JavaSE学习笔记】集合应用_Collectons工具,模拟斗地主,异常

来源:互联网 发布:魔兽数据库2.43 编辑:程序博客网 时间:2024/05/23 20:51

集合应用

A.Collections工具

1)Collections和Collection的区别?

Collection:集合:顶层次的一个根接口,有两个子接口:List,Set

Collections:对集合操作的工具类,具体的类:它针对集合进行操作

2)功能

public static <T> void sort(List<T> list):默认的自然排序,将集合中的元素升序排序

import java.util.ArrayList;import java.util.Collections;public class Demo01 {public static void main(String[] args) {// 创建一个集合对象ArrayList<Integer> al = new ArrayList<Integer>();// 添加元素al.add(20);al.add(19);al.add(21);al.add(18);al.add(17);al.add(16);// 排序前System.out.println(al);// [20, 19, 21, 18, 17, 16]// 自然排序后Collections.sort(al);System.out.println(al);// [16, 17, 18, 19, 20, 21]}}

public static <T> int binarySearch(List> list,T key):二分查找搜索法:key:查找的元素

二分法必须是有序集合

import java.util.ArrayList;import java.util.Collections;public class Demo01 {public static void main(String[] args) {// 创建一个集合对象ArrayList<Integer> al = new ArrayList<Integer>();// 添加元素al.add(20);al.add(19);al.add(21);al.add(18);al.add(17);al.add(16);// 排序前System.out.println(al);// [20, 19, 21, 18, 17, 16]// 自然排序后Collections.sort(al);System.out.println(al);// [16, 17, 18, 19, 20, 21]int i = Collections.binarySearch(al, 18);System.out.println(i);// 2}}

public static void reverse(List list):反转功能

import java.util.ArrayList;import java.util.Collections;public class Demo01 {public static void main(String[] args) {// 创建一个集合对象ArrayList<Integer> al = new ArrayList<Integer>();// 添加元素al.add(20);al.add(19);al.add(21);al.add(18);al.add(17);al.add(16);// 排序前System.out.println(al);// [20, 19, 21, 18, 17, 16]// 自然排序后Collections.sort(al);System.out.println(al);// [16, 17, 18, 19, 20, 21]// 反转后Collections.reverse(al);System.out.println(al);// [21, 20, 19, 18, 17, 16]}}

public static void shuffle(List<?> list):随机置换,打乱顺序

import java.util.ArrayList;import java.util.Collections;public class Demo01 {public static void main(String[] args) {// 创建一个集合对象ArrayList<Integer> al = new ArrayList<Integer>();// 添加元素al.add(20);al.add(19);al.add(21);al.add(18);al.add(17);al.add(16);// 排序前System.out.println(al);// [20, 19, 21, 18, 17, 16]// 自然排序后Collections.sort(al);System.out.println(al);// [16, 17, 18, 19, 20, 21]// 置换后Collections.shuffle(al);System.out.println(al);// [20, 19, 18, 21, 17, 16]}}

3)问题:

如果用Collections集合工具类对自定义对象同时进行自然排序和比较器排序

哪个起作用?

答:比较器起排序主要作用

B.模拟斗地主(集合完成)

1)模拟斗地主洗牌、发牌、看牌、发牌是有序的

有序(3,4,5,6,7,8,9,10,J,Q,K,A,2,小王,大王)

2)思路:

1.创建HashMap集合,创建ArrayList集合,存储编号

2.装牌:给集合中添加编号,以及对应的牌(点色和花色数组遍历拼接)

将编号添加到ArrayList中

3.洗牌:洗的是编号(Collections.shuffle()只能对List集合进行置换,所以必须单独建一个ArrayList集合)

4.发牌:发的也是编号,为了保证牌是有序的,所有应该用TreeSet<Integer>集合

5.看牌:遍历TreeSet编号,在HashMap中遍历对应的值

3)代码

import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.TreeSet;public class PokerDemo {public static void main(String[] args) {// 1)创建HashMap集合:编号和牌HashMap<Integer, String> hm = new HashMap<Integer, String>();// 创建ArrayList集合:存储编号ArrayList<Integer> al = new ArrayList<Integer>();// 2)装牌// 创建花色数组(黑红梅方)String[] colors = { "♠", "♥", "♣", "♦" };// 创建点数数组(从小到大)String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2" };// 给牌进行编号,从0开始int index = 0;// 给牌拼接并编号// 先点数从小到大的顺序for (String number : numbers) {// 再花色按照黑红梅方的顺序for (String color : colors) {// 拼接扑克(花色+点数)String poker = color.concat(number);// 添加到集合中(编号, 扑克)hm.put(index, poker);// 将编号添加到ArrayListal.add(index);// 编号+1index++;}}// 不要忘了添加大王小王hm.put(index, "小王");al.add(index);index++;hm.put(index, "大王");al.add(index);// 3)洗牌:洗的是编号Collections.shuffle(al);// 4)发牌(发的也是编号,保证有序,用TreeSet接收)// 三个玩家,一个底牌TreeSet<Integer> player1 = new TreeSet<Integer>();TreeSet<Integer> player2 = new TreeSet<Integer>();TreeSet<Integer> player3 = new TreeSet<Integer>();TreeSet<Integer> diPai = new TreeSet<Integer>();for (int i = 0; i < al.size(); i++) {// 判断// 最后三张是底牌if (i >= al.size() - 3) {// 可以直接写diPai.add(i),最好写al.get(i)// i是角标,get(i)才是值diPai.add(al.get(i));} else if (i % 3 == 0) {// 被3整除的发给第1个人player1.add(al.get(i));} else if (i % 3 == 1) {// 被3整除余1的发给第2个人player2.add(al.get(i));} else if (i % 3 == 2) {// 被3整除余2的发给第3个人player3.add(al.get(i));}}// 5)看牌(遍历TreeSet集合获取到对应的编号,那对应的编号在HashMap中找牌)System.out.println("*********************************欢迎来到欢乐斗地主*********************************");lookPoker("玩家1", player1, hm);lookPoker("玩家2", player2, hm);lookPoker("玩家3", player3, hm);lookPoker("底牌", diPai, hm);}public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) {System.out.print(name + "的牌是:");// 遍历TreeSet集合的编号for (Integer key : ts) {// 获取到编号,通过get(key),获取hm中的牌String s = hm.get(key);System.out.print(s + "  ");}System.out.println();}}

4)结果展示


C.异常

1)程序出现问题

举例:

今天天天很好,班长骑车去旅游...

问题1:他在骑车的过程中,路塌陷了,不能骑行了;不可抗力的问题:严重问题!

问题2:他在骑行的过程中,自行车没气了;本来应该在骑行之前首先检查的问题!

问题3:山路两边是平坦的,中间是石子,班长非在中间骑,属于自身问题:no zuo no die

2)程序的异常:Throwable

error:这种问题是一个严重问题

一般出现这种问题,需要一起解决(程序员只能避免严重问题),比如:内存溢出(OutOfMemory);

Exception:异常:

编译时期异常:如果程序员不管这个,根本没办法运行,需要解决

运行时期异常:只要不是编译时期异常,都属于异常异常;一般情况,是因为们的代码不够严谨.

3)异常的描述:

哪一个包下的异常,并且将报错的信息打印控制台(出现错误的位置)

格式:(finally可省略)

try{

     可能出现问题的代码;
}catch(异常类名 变量名){

      输出语句;
}fianll{

      释放资源;
}

public class Demo01 {public static void main(String[] args) {int a = 10;int b = 0;// a / b,除数为0,抛出此类的一个实例。(运行时期异常!)System.out.println(a / b);// java.lang.ArithmeticException: / by zero}}

4)如果一个程序出现异常了,他会将异常的信息打印在控制台

运行时期异常如何解决:

try...catch一个异常

public class Demo01 {public static void main(String[] args) {int a = 10;int b = 0;try {System.out.println(a / b);} catch (ArithmeticException ae) {System.out.println("除数不能为0");}}}
两个异常

a.一个一个去try...catch

实际开发中:捕获异常时:给具体的异常类,不要随意使用Exception

public class Demo01 {public static void main(String[] args) {int a = 10;int b = 0;try {System.out.println(a / b);} catch (ArithmeticException ae) {System.out.println("除数不能为0");}int[] arr = new int[3];try {System.out.println(arr[3]);} catch (ArrayIndexOutOfBoundsException aie) {System.out.println("访问了不存在的索引");}}}

b.一个try,多个catch

捕获异常:catch中的歌异常类名是一种平级关系

                  如果出现父子关系,那么这种将最大的异常写在最后

public class Demo01 {public static void main(String[] args) {int a = 10;int b = 0;int[] arr = new int[3];try {System.out.println(a / b);System.out.println(arr[3]);} catch (ArithmeticException ae) {System.out.println("除数不能为0");} catch (ArrayIndexOutOfBoundsException aie) {System.out.println("访问了不存在的索引");} catch (Exception e){// 这个类就要放在最后面System.out.println("代码可能会有问题,但具体不知道");}}}
c.jdk7以后出现了一个新的捕获异常的方式

try{

       可能出现问题的代码

} catch (异常类名1 | 异常类名2 | 异常类名3  变量名){

}


注意:弊端:开发中,可能会出现同类型问题,需要捕获同一个异常信息

public class Demo01 {public static void main(String[] args) {int a = 10;int b = 0;int[] arr = new int[3];//try {//System.out.println(a / b);//System.out.println(arr[3]);//} catch (ArithmeticException | ArrayIndexOutOfBoundsException e){//System.out.println("捕获到了异常!");//}try {System.out.println(a/b);System.out.println(arr[3]);} catch (Exception e) {System.out.println("捕获到了异常!");}}}

5)java程序中编译时期异常和运行时期异常的区别

编译时期异常:需要我们去处理,否则编译不通过,显示处理

运行时期异常:无需显示处理,也可以像编译时期异常处理一样

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class Demo01 {public static void main(String[] args) {String s = "2017-10-1";SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM,dd");//开始解析try {Date d = sdf.parse(s);System.out.println(d);} catch (ParseException pe) {System.out.println("解析出问题了");}}}

使用捕获异常:try...catch这个格式时候

如果try里面的代码出现问题了,jvm会生成异常对象

然后抛出来和catch中描述的这个异常信息进行匹配,判断

如果一致,这里会输出处理语句(输出语句)

6)异常类的一些方法

public String getMessage():返回的是一个异常的消息字符串

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class Demo01 {public static void main(String[] args) {String s = "2017-10-1";SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM,dd");// 开始解析try {Date d = sdf.parse(s);// jvm产生一个对象 :ParseException} catch (ParseException pe) {// ParseException e = new ParseException ();String str = pe.getMessage();System.out.println(str);// Unparseable date: "2017-10-1"}}}

public String toString():返回的是一个简单的表述信息

当前类对象 name:全路径名 : 空格 + getMessage()

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class Demo01 {public static void main(String[] args) {String s = "2017-10-1";SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM,dd");// 开始解析try {Date d = sdf.parse(s);// jvm产生一个对象 :ParseException} catch (ParseException pe) {// ParseException e = new ParseException ();String str = pe.toString();System.out.println(str);// java.text.ParseException: Unparseable date: "2017-10-1"}}}

public void printStackTrace():捕获异常信息,以及出现的具体位置在哪里

返回的是void类型,直接在控制台的!

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class Demo01 {public static void main(String[] args) {String s = "2017-10-1";SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM,dd");// 开始解析try {Date d = sdf.parse(s);// jvm产生一个对象 :ParseException} catch (ParseException pe) {// ParseException e = new ParseException ();pe.printStackTrace();}}}

7)处理异常的第二种方式

throws:抛出异常

当我们处理异常,如果没有一些权限处理异常,那我们就不处理了

通过开发工具,提示抛出异常,这个时候就可以使用throws

推荐不建议在main方法抛出

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class Demo01 {public static void main(String[] args) {try {method();// 方法有异常,调用的时候也要处理异常} catch (ParseException e) {e.printStackTrace();}}// 该方法中的异常属于编译时期异常:告诉开发者,你注意了,我有问题!public static void method() throws ParseException {String s = "2017-8-8";// 创建对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");Date d = sdf.parse(s);// 编译时期异常System.out.println(d);}}

8)面试题:

throws和throw的区别?(100%会问到!)

throws:一般用在方法声明上

抛出的是一个异常类名,可以抛出多个异常,中间用逗号隔开

throws表示抛出异常,这段代码可能会抛出异常( 指的是抛出异常的可能性)

一般情况:throws用的比较多

throw:一般在方法中进行抛出

抛出的是一个异常对象(匿名对象的方式)

throw表示抛出异常:肯定的抛出异常(具体异常),走到这块代码,一定会执行throw中的异常

在语句中进行处理

public class Demo02 {public static void main(String[] args) {method();}public static void method(){int a = 10;int b = 0;if (b == 0) {throw new ArithmeticException();// 代码走到这块:表示一定会执行这个异常} else {System.out.println(a / b);}}}

9)执行代码的顺序

try{

可能出现错误的代码

}catch(异常类名 变量名){

处理异常;

}finally{

释放资源;

}

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class Demo03 {public static void main(String[] args) {String s = "2017-8-8";SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");Date d = null;try {d = sdf.parse(s);} catch (ParseException e) {e.printStackTrace();System.exit(0);// jvm退出} finally {System.out.println("必须执行!释放资源!除非前面有System.exit(0)");}}}
注意:

finally中的代码是一定会执行的,一般用在IO流中和数据库中;
如果在执行finally中的代码之前,JVMjava虚拟机退出了,那么finally中的释放资源是不会执行的

10)面试题

final,finalize,finally三者之间的区别?(100%问到)

final:最终的,终态的

final修饰类:该类不能被继承

final修饰成员变量:该变量是自定义常量

final修饰成员方法:该方法不能被重写

finalize:和垃圾回收期有关系:运行垃圾回收器的方法:gc().调用gc()

实质是调用了通过重写了Object中的finalize方法

finally:出现在IO流中或者数据库中,用来释放资源的!

11)面试题

如果catch有return语句,finally中的会执行吗?

如果会,是在return前执行还是在return后执行?

会执行finally中的代码,是在return前执行

确切的说是在代码中间执行!

public class Demo04 {public static void main(String[] args) {System.out.println(getInt());}public static int getInt() {int a = 10;try {a = 20;System.out.println(a / 0);} catch (Exception e) {a = 30;return a;/** * 当代码走到这一块,a = 30 ; return a ====>return 30 ,这里面形成了一回路径, * 但是,一看这里有finally,所以会执行finally中的代码,a =40 , * 最终返回return a====>return前面的语句:30 * */} finally {a = 40;}return a;}}

12)自定义异常类

有时候在实际开发中,可能会需要自己定义一个异常类;不是说起以类名就是可以当作异常类,

必须自定义的类继承Exception或者RuntimeException,那么这样的类,才是自己定义的异常类

// 自定义异常类public class MyException extends Exception {public MyException() {super();}public MyException(String message) {super(message);}}

// Teacherpublic class Teacher {public static void check(int score) throws MyException {// 录入学生成绩,0-100之间if (score > 100 && score < 0) {System.out.println("成绩必须在0~100之间!");} else {System.out.println("成绩符合我们的规则!");}}}

import java.util.Scanner;// 自定义异常的测试public class StudentDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入成绩:");int score = sc.nextInt();try {Teacher.check(score);} catch (MyException e) {e.printStackTrace();}}}

 异常类中的注意事项:

a.子类重写父类中的方法,如果父类中方法抛出一个异常

那么子类重写父类该方法时抛出异常,要么跟父类中异常保持一致,要么要是他的异常类的子类

b.如果被重写的方法,没有抛出异常,那么子类重写这个方法

也不能抛出异常,不能throws,只能try...catch(这种情况只能子类中进行捕获异常);


阅读全文
1 0
原创粉丝点击