笔记-迎难而上之Java基础进阶3
统计字符串中每一个不同的字符
import java.util.*; //统计字符串每一个字符出现的字数 public class stringdemo{ public static void main(string[] args){ scanner ascanner = new scanner(system.in); //让用户输入字符串 system.out.println("请输入你要统计的语句"); string astring = ascanner.next(); //要统计每一个字符,就要把字符串转换为字符,可以调用字符串的方法tochararray char[] achararray = astring.tochararray(); //创建hashmap集合,让其存储键与值 hashmap<character,integer> ahashmap = new hashmap<>(); //遍历字符数组 for(character key:achararray){ //把achar作为键,先判断集合中有没有该键,若有则value加一,没有的话添加键进去 if(ahashmap.containskey(key)){ integer value =ahashmap.get(key); value++; //后来的值会取代前面的值,put方法把值添加进去, ahashmap.put(key,value); }else{ //不存在添加进去 ahashmap.put(key,1); } } //把key存储都set集合中,遍历集合 set<character> aset = ahashmap.keyset(); //遍历ahashmap for(character key : aset){ integer value = ahashmap.get(key); system.out.println(key+"="+value); } } }
jdk9的新特性:
list接口,set接口,map接口里边增加了一个静态方法of,可以给集合一次性添加多个元素
使用前提:当集合中存储的元素的个数已经确定了,不再改变使用,也就是说,添加完元素之后,就不能再使用put方法来添加元素了
注意事项:
of方法只适用于list接口,set接口,map接口,不适用于接口的实现类
of方法的返回值是一个不能够改变的集合
set接口和map接口在调用of方法适合,不能存放重复元素,否则会抛出异常
import java.util.*; public class jdk9demo{ public static void main(string[] args){ list<string> list = list.of("a","b","c","d","a");//可以重复元素 system.out.println(list); set<string> set = set.of("a","b","c");//不允许重复元素 system.out.println(set); map<string,integer> map = map.of("张三",18,"李四",17,"王五",16,"赵三",18);//不允许重复元素,键不允许重复,值可以 system.out.println(map); } }
debug追踪
debug调试程序
可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
f8:逐行执行程序 f7:进入到方法中 shift+f8跳出方法
f9:跳到下一个断点 ctrl +f2 退出debug模式,停止程序
console:切换到控制台
斗地主案列
import java.lang.reflect.array; import java.util.arraylist; import java.util.collections; import java.util.hashmap; import java.util.list; public class doudizhu { public static void main(string[] args){ //integer表示的索引,string表示牌的大小 hashmap<integer,string> poker = new hashmap<>(); //创建一个list集合,存储牌的索引,sort方法可以对索引进行排序 arraylist<integer> pokerindex = new arraylist<>(); //定义两个集合,存储花色和牌的序号 list<string> colors = list.of("♠","♥","♣","♦"); list<string> numbers = list.of("2","a","k","q","j","10","9","8","7","6","5","4","3"); //把大小王存储到集合中 int index = 0; poker.put(index,"大王"); pokerindex.add(0); index++; poker.put(index,"小王"); pokerindex.add(index); index++; //0索引代表着大王,1索引代表着小王,以此类推,到后面就可以对索引排序,也就是对牌排序 for(string number : numbers){ for(string color :colors){ string str = color+number; poker.put(index,str); //牌的索引也要添加,因为他代表着牌的大小, pokerindex.add(index); index++; } } //使用collections中的方法shuffle(); collections.shuffle(pokerindex); arraylist<integer> p1 = new arraylist<>(); arraylist<integer> p2 = new arraylist<>(); arraylist<integer> p3 = new arraylist<>(); arraylist<integer> p4 = new arraylist<>(); for(int i=0;i <pokerindex.size();i++){ //先转为integer类型,不然会添加失败 integer in = pokerindex.get(i); if(i>=51){ p4.add(in); }else if(i%3==0){ p1.add(in); }else if(i%3==1){ p2.add(in); }else if(i%3==2){ p3.add(in); } } //把分完的牌进行排序 collections.sort(p1); collections.sort(p2); collections.sort(p3); collections.sort(p4); lookpoker("刘德华",poker,p1); lookpoker("周润发",poker,p2); lookpoker("周星驰",poker,p3); lookpoker("底牌",poker,p4); } public static void lookpoker(string name,hashmap<integer,string> poker,arraylist<integer> list){ system.out.print(name+": "); for(integer key : list){ //通过索引获取值 string value = poker.get(key); system.out.print(value+" "); } system.out.println(); } }
异常
throwable有两个子类exception和error
error:严重错误error,无法通过处理的错误,只能实现避免,好比绝症
exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的
throw关键字可以在指定的方法里面抛出指定的异常对象
/* throw关键字 作用: 可以使用throw关键字在指定的方法中抛出指定的异常 使用格式: throw new xxxexception("异常产生的原因"); 注意: 1.throw关键字必须写在方法的内部 2.throw关键字后边new的对象必须是exception或者exception的子类对象 3.throw关键字抛出指定的异常对象,我们必须处理这个异常对象 throw关键字后边创建的是runtimeexception或者是runtimeexception的子类对象,我们可以不处理,默认交给jvm处理 throw关键字后边创建的是编译器异常,我们必须处理这个异常, */ public class throwdemo{ public static void main(string[] args){ int[] arr= new int[3]; int e = getelement(arr,-2); system.out.println(e); //抛出指定了异常 //exception in thread "main" java.lang.nullpointerexception: 传递的数组是空 //at throwdemo.getelement(throwdemo.java:24) //at throwdemo.main(throwdemo.java:18) } //如果传递的参数不合法,那么我们就必须使用抛出异常的方式,告知方法的调用者,传递参数有问题 public static int getelement(int[] arr,int index){ if(index<0 || index>arr.length-1){ throw new arrayindexoutofboundsexception("传递的索引不能超过范围或者低于范围"); } if(arr == null){ //如果是空,就指定他为空指针异常 throw new nullpointerexception("传递的数组是空"); } int i = arr[index]; return i; } }
objects的非空判断
objects.requirenonnull();可以判断一个对象是否为null
import java.util.objects; public class throwdemo{ public static void main(string[] args){ method("云想衣裳花想容");//传递null将会返回nullpointerexception异常 } public static void method(object obj){ object objects=objects.requirenonnull(obj); system.out.println(objects); } }
throws关键字_异常处理的第一种方式
/* throws关键字:当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象,可以使用thorws关键字来处理异常对象,会把异常对象声明抛出给方法的调用者处理 */ import java.io.filenotfoundexception; public class throwsdemo{ public static void main(string[] args)throws filenotfoundexception{ readfile("d:\\a.txt"); } public static void readfile(string filename)throws filenotfoundexception{ //传递进来的文件不对就抛出异常 if(!filename.equals("c:\\a.txt")){ throw new filenotfoundexception("传递的文件路径不对,请重新传递"); } system.out.println("传递路径成功"); } }
try_catch异常处理的第二种方式
捕获异常语法格式 try{ 编写可能会出现异常的代码 }catch(用来接收try中抛出的异常信息 异常类型 e){ 处理异常代码 } .... catch(){} 注意: try中可能会抛出多个异常对象,那么久可以使用多个catch来处理这些异常对象 如果try中产生了异常,那么就会执行catch中的异常处理逻辑
import java.io.filenotfoundexception; public class throwsdemo1{ public static void main(string[] args){ try{ readfile("d:\\a.txt"); }catch(filenotfoundexception e){ system.out.println("传递的文件不对"); } system.out.println("后续代码"); } public static void readfile(string filename)throws filenotfoundexception{ //传递进来的文件不对就抛出异常 if(!filename.equals("c:\\a.txt")){ throw new filenotfoundexception("传递的文件路径不对,请重新传递"); } system.out.println("路径没有问题"); } }
throwable类中3个异常处理的方法
getmessage() :简短的描述
tostring() :详细的消息字符串
printstacktrace():打印的异常信息最全面
字异常符类 public class fu{ public void show1()throws nullpointerexception,classcastexception{} public void show2()throws indexoutofboundsexception{} public void show3()throws indexoutofboundsexception{} class zi extens fu{ //子类重写父类方法是,抛出和父类相同异常 public void show1()throws nullpointerexception,classcastexception{} //子类重写父类方法时,抛出父类异常的子类 public void show2()throws arrayindexindexoutofboundsexception{} //子类重写父类方法时,不抛出异常 public void show3(){} //父类没有抛出异常,子类也不可以抛出异常,如若有异常,需要try catch处理异常
自定义异常
//自定义一个注册异常 //需要一个空参数的构造方法,一个带异常信息的构造方法 //继承exception //那么自定义的异常类就是一个编译器异常,那就需要throws或者try...catch处理 //继承的是runtimeexception,那么异常无序处理,交给虚拟机 public class registerexception extends exception{ public registerexception(){} public registerexception(string message){ super(message); } }
import java.util.*; //使用自定义异常类 public class exceptiondemo{ //定义一个集合,存储姓名 public static void main(string[] args){ arraylist<string> list = new arraylist<>(); list.add("詹姆斯"); list.add("科比"); list.add("乔丹"); list.add("诺维斯基"); list.add("邓肯"); system.out.println(list); //让用户输入昵称 scanner sc = new scanner(system.in); system.out.println("请输入你的昵称"); string nicheng = sc.next(); //向里面添加姓名,如果不存在则添加成功,如果存在则返回注册异常 for(string name : list){ //使用字符串的方法equals判断集合是否存在元素,将会返回一个boolean //为真,就表示昵称已经存在,需要返回一个注册异常 if(name.equals(nicheng)){ try{ throw new registerexception("亲,该昵称已经被注册过了"); }catch(registerexception e){ e.printstacktrace(); return;//一旦放生异常,立马结束方法 } } //遍历完了,如果没有发生异常,就表示昵称可以创建 } list.add(nicheng); system.out.println("恭喜您,注册成功"); } }
多线程
public class threaddemo{ public static void main(string[] args){ mythread mt = new mythread(); //执行start方法,开启线程,执行run方法 //如果使用mt.run();的话程序会在堆内存中执行,那就不是多行程了,而是单线程 //每一次使用start();都会开辟一条新的线程,在栈空间里面执行run方法,多行程的好处就是线程之间互相不影响,cup喜欢哪一个线程就执行哪一个线程 mt.start(); for(int i= 0;i<10;i++){ system.out.println("main线程"+i); } } }
public class mythread extends thread{ //重写run方法 public void run(){ for(int i=0;i<10;i++){ system.out.println("run线程"+i); } } }
thread类的常用方法
获取线程名称的方法
1.使用thread类中的方法getname string getname() 返回该线程的名称,那条线程调用我,我就返其的名称 2.可以先获取到当前正在执行的线程,然后使用线程中的方法getname()获取线程的名称
public class mythread1 extends thread{ public void run(){ /*第一种获取名字的方式 string name=getname(); system.out.println(name);*/ // 第二种获取名字的方式 //先获取当前线程(currentthread是一个静态方法,可以通过类名直接获取线程) thread t = thread.currentthread();//这个方法将会返回当前的线程 //通过线程获取名字 string naem =t.getname(); system.out.println(name); } }
public class threadname{ public static void main(string[] args){ mythread1 mt = new mythread1(); mt.start(); } }
设置线程名称
一种通过setname方法,一种通过构造方法来设置
public class threadname{ public static void main(string[] args){ mythread1 mt = new mythread1(); mt.setname("小强"); mt.start(); new mythread1("旺财").start(); } }
public class mythread1 extends thread{ public mythread1(){} public mythread1(string name){ super(name); } public void run(){ /*第一种获取名字的方式 string name=getname(); system.out.println(name);*/ // 第二种获取名字的方式 //先获取当前线程 thread t = thread.currentthread(); //通过线程获取名字 string name =t.getname(); system.out.println(name); } }
sleep方法
是一个静态方法,使用类名就可以直接调用,让当前线程睡眠指定时间
创建多线程程序的第二种方式_实现runnable接口
实现步骤:
1.创建一个runnable接口的实现类
在实现类中重写runnable接口的run方法,设置线程任务
创建一个runnable接口的实现类对象
创建thread类对象,构造方法中传递runnable接口的实现类对象
-
调用thread类的start方法,开启线程
public class runnableimp implements runnable{ public void run(){ for(int i=0;i<10;i++){ //获取当前的线程,然后获取线程名字 system.out.println(thread.currentthread().getname()+"--"+i); } } }
public class runnabledemo { public static void main(string[] args){ //创建runnable接口实现类对象 runnableimp run = new runnableimp(); //thread中有个构造方法可以接runnable接口作为参数传递 new thread(run).start(); for(int i=0;i<10;i++){ //想要获取main方法的线程,只能够用下面的方式获取,然后获取线程名字 system.out.println(thread.currentthread().getname()+"--"+i); } } }