JAVA自学笔记19
JAVA自学笔记19
1、集合总结
Collection(单列集合)
List(有序可重复)
ArrayList:底层数据结构是数组 ,查询快,增删慢。线程不安全,效率高
Vector:底层数据结构是数组,查询快,增删慢。线程不安全,效率低
LinkedList:底层数据结构是链表,查询慢,增删快,线程不安全,效率高
Set(无序唯一)
HashSet:底层数据结构是哈希表,哈希表依赖两个方法:hashCode()和equals()
执行顺序:首先判断hashCode()值是否相同,是则继续执行equals(),为真说明元素重复,不添加,为假就直接添加到集合;否则直接添加到集合
注意:可直接生成以上两方法
LinkedHashSet:底层数据结构由链表和哈希表组成,由链表保证元素有序,由哈希表保证元素唯一
TreeSet:底层数据结构数红黑树(自平衡的二叉树)
如何保证元素唯一?根据比较的返回值是否是0决定
如何保证元素的顺序呢?①自然排序(元素具备比较性):让元素所属的类实现Comparable接口;②比较器排序(集合具备比较性)让集合接收一个Comparator的实现类对象
Map(双列集合):Map集合的数据结构仅仅针对键有效,与值无关;存储的是键值对形式的元素,键唯一,值可以重复
HashMap
底层数据结构是哈希表,哈希表依赖两个方法:hashCode()和equals().线程不安全,效率高
执行顺序:首先判断hashCode()值是否相同,是则继续执行equals(),为真说明元素重复,不添加,为假就直接添加到集合;否则直接添加到集合
注意:可直接生成以上两方法
LinkedHashMap
底层数据结构由链表和哈希表组成,由链表保证元素有序,由哈希表保证元素唯一
Hashtable
底层数据结构是哈希表,哈希表依赖两个方法:hashCode()和equals()。线程安全,效率低
执行顺序:首先判断hashCode()值是否相同,是则继续执行equals(),为真说明元素重复,不添加,为假就直接添加到集合;否则直接添加到集合
注意:可直接生成以上两方法
TreeMap
底层数据结构数红黑树(自平衡的二叉树)
如何保证元素唯一?根据比较的返回值是否是0决定
如何保证元素的顺序呢?①自然排序(元素具备比较性):让元素所属的类实现Comparable接口;②比较器排序(集合具备比较性)让集合接收一个Comparator的实现类对象
2、如何选择使用哪种集合?
1)根据需求:
是否是键值对形式:
是-Map
键要排序:TreeMap
键不用排序:HashMap
若不确定,使用HashMap
否-Collection
元素唯一:set
元素需要排序:TreeSet
元素不需要排序:HashSet
不确定就使用HashSet
元素不唯一:List
要求安全:Vector(一般不使用)
不要求安全:ArrayList或LinkedList
增删多:LinkedList
查询多:ArrayList
不确定则使用ArrayList
不确定则使用ArrayList
3、各种集合常见功能进而遍历方式总结
Collection:
add()
remove()
contains()
iterator()
size()
遍历方式:增强for,迭代器
–List
get()
遍历方式:普通for
–Set
Map:
put();
remove()
containsKey(),cintainsValue()
keySet()
get()
value()
entrySet()
size()
遍历方式:根据键寻值、根据键值对对象分别找键和值
3、异常
1)异常:
异常就是Java程序在运行过程中出现的错误,它是Java对不正常情况进行描述后的对象的体现。常见的异常有角标越界异常,空指针异常
2)Throwable
严重问题:Error:一般无法处理,是很严重的问题
一般问题:Exception
编译期问题:
不是RuntimeException的异常,必须处理
运行期问题:
RuntimeException的异常,难以处理
3)图解
4)JVM将对异常作出默认处理:把异常的名称,原因,及出现的问题等信息输出到控制台,并使程序强制结束
5)try…catch…finally方式处理异常
格式:try{
可能出现问题的代码
}catch(异常名变量){
针对问题的处理;
}finally{
释放资源
}
变形格式:
try{
可能出现问题的代码
}catch(异常名变量){
针对问题的处理;
}
注意:try内的代码越少越好,避免占用内存资源
catch内必须有内容,也可以给提示
//eg:一个异常
int a=2;
int b=0;
try{
System.out.println(a/b);
}catch(ArithmeticException ae){
System.out.println("除数不能为0");
}
//两个异常
int a=20;
int b=0;
try{
System.out.println(a/b);
}catch(ArithmeticException ae){
System.out.println("除数不能为0");
}
int[] arr={1,2,3};
try{
System.out.println(arr[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("索引越界");
}
对于多个异常:可以写多个try…catch。也可以写一个try,多个catch
try{
…
}catch(异常名 变量名){
}catch(异常名,变量名){
}…
注意:一旦try内出现问题,就会在这里把问题抛出去,然后和catch里面的问题进行匹配,一旦有匹配的,就继续执行catch后的语句。可以明确异常类型的尽量明确。平级关系的异常谁前谁后无所谓,如果出现父子关系的异常,父类异常必须在较后面.
在try里面发现问题后,jvm会帮我们生成一个异常对象,然后把这个异常对象抛出,和catch里面的内容匹配。如果该对象是某个类型的,就会执行该catch里面的处理信息
int a=20;
int b=0;
try{
System.out.println(a/b);
}catch(ArithmeticException ae){
System.out.println("除数不能为0");
}
int[] arr={1,2,3};
try{
System.out.println(arr[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("索引越界");
}
一个try复合多个catch
int a=20;
int b=0;
int[] arr={1,2,3};
try{
System.out.println(a/b);
System.out.println(arr[3]);
}catch(ArithmeticException ae){
System.out.println("除数不能为0");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("索引越界");}
}
}
对于不可知异常名的错误
try{
}catch(Exception e){
System.out.println(“发生未知错误”);
}//Exception e 一定要放在最后,否则前面已知类型的匹配将报错
附:各种try的格式
JDK7新特性:
try{
}catch(异常名1|异常名2|…变量){
}
多个异常之间必须是平级关系
6)编译期异常和运行期异常的区别
编译时异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
运行时异常:无需显式处理,也可以和编译时异常一样处理
7)Throwable
1)方法:
①getMessage()
获取异常信息,返回字符串
②toString()
获取异常类名和异常信息,返回字符串
③printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void
④printStackTrace(PrintStream s)
通常用该方法将异常内容保存在日志文件中,以便查阅
2)Throws的方式处理异常
定义:定义功能方法时,需要把出现的问题暴露出来让调用者去处理,那么就通过throws在方法上标识
有些时候,我们是可以对异常进行处理的;但又有些时候,我们根本就没有这个权限去处理某个异常;或者说,我处理不了,我就不处理了。为了解决出错问题Java提供了另一种处理方案:抛出
格式:throws 异常名
注意:throws必须跟在方法的括号后面。在方法声明上抛出,是为了告诉调用者,这里有问题。尽量不要在main方法上抛出异常,此时会把异常抛给虚拟机。编译时异常的抛出将来调用者必须处理,运行时异常的抛出可不处理。throws后可跟多个异常名,用逗号隔开
string s="2014-7-25";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd" HH-mm-ss);
Date d=sdf.parse(s);
System.out.println(d);
3)Throw
在功能方法内部出现的某种情况,程序不能继续运行,需要进行跳转时,就用Throw把异常对象抛出。此时的抛出应该是异常的对象。throws主要是在方法上声明异常,throw是在方法内部抛出异常对象
throw new ArithmeticException();
4)Throws与Throw的区别
①Throws:
用在方法声明后面,跟的是异常类名
可以跟多个异常名,用逗号隔开
表示抛出异常,由该方法的调用者处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
②throw
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则一定抛出了某种异常
5)如何处理异常?
原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这时用throw
区别:后续程序需要继续运行就用try,后续程序不需要继续运行就throws
6)finally
特点:被finally控制的语句体一定会执行。特殊情况,在执行到finally之前jvm退出了,就无法执行
作用:用于释放资源,在IO流操作和数据库操作中会见到
string s="2014-7-25";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd" HH-mm-ss);
Date d=null;
try{
d=sdf.parse(s);}catch(ParseException e){
e.printStackTrace();
}finally{
System.out.println("这里的代码一定会被执行");
}
System.out.println(d);
6)final,finally,finalize的区别
final:最终的意思,可以修饰类、成员变量,成员方法
修饰类:类不能被继承
修饰变量:变量是常量
修饰方法:方法不能被重写
finally:是异常处理的一部分,用于释放资源。一般来说,代码肯定会执行
finalize:是Object类的一个方法,用于垃圾回收
7)如果catch内有return语句,请问finally里面的代码还会执行吗?如果会,是在return前还是return后呢?
会,前。
问图中return a;//返回的是30但a=40
在程序运行到finally之上的return a时,以及形成了return 30的返回路径,不再受finally内的a=40的影响。return只有一条执行路径
4、自定义异常
1)java不可能对所有的情况都考虑到。所以在实际的开发中,我们需要自己定义异常。要想定义异常,就必须继承自Exception或RuntimeException
2)实现:
//以下是自定义的异常类
public class MyException extends Exception{
public Myexception(String message){
super(message);
}
}//不需要写内容,大多数异常没有成员方法
//以下是老师类,注意,运行时异常不用在方法名括号后throws相关异常名;而若是编译时异常就需要
public class Teacher{
public void check(int score){
if(score>100||score<0){
throws new MyException("成绩超过范围");
else{
System.out.println("成绩无误");
}
}
}
}
//以下是测试类
int score sc.nextInt();
Teacher t=new Teacher();
try{
t.check(score);
}catch(MyException e){
e.printStackTrace();
}
5、异常注意事项
1)子类覆盖父类方法时,子类的方法必须抛出相同的异常或父类异常的子类
2)如果父类抛出了多个异常,子类覆盖父类时,只能抛出相同的异常或是他的子集,子类不能抛出父类没有的异常
3)如果被覆盖的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws.
6、File类
1)文件和目录(文件夹)路径名的抽象表现形式。需导包java.io.File
2)构造方法:
public File(String pathname)
根据一个路径得到File对象
public File(String parent,String child)
根据一个目录和一个子文件得到一个File对象
public File(File parent,String child)
根据一个父File对象和一个子文件/目录得到File对象
//把d:\\demo\\a.txt封装成一个File对象
File file=new File("d:\\demo\\a.txt");
File file2=new File("d:\\demo","a.txt");
File file3=new File("d:\\demo");
File file4=new File(file3,"a.txt");
//以上三种方式效果一样
3)成员方法
①创建功能:
public boolean createNewFile()
创建文件,创建文件夹=,若相关文件存在,则创建失败
public boolean mkdir()
创建文件夹,若相关文件夹存在,则创建失败
public boolean mkdirs()
创建文件夹且只能创建文件夹,如果父文件夹不存在将自动创建
//创建文件夹
File file=new File("e:\\demo");
System.put.println("mkdir"+file.mkdir());
//创建文件,注意要想在某个目录下创建内容,该目录首先必须存在
File file2=new File("e:\\demo\\a.txt");
System.out.println("createNewFile:"+file2.createNewFile())
File file4 =new file("e:\\ddd\\fff\\ggg");
file4.mdirs();
②删除功能
public boolean delete()
File file2=new File("e:\\demo\\a.txt");//没有路径,默认为当前项目路径
System.out.println("createNewFile:"+file2.createNewFile());
file2.delete();//也可删文件夹,都是直接永久删除。某个目录下有其他文件夹,那么只有把内部的文件删除完毕后才能删改文件夹
③重命名功能
public boolean renameTo(File dest)
路径以盘符开始:绝对路径
路径不以盘符开始:相对路径
如果路径名相同,仅仅改名而已
如果路径名不同,将改名并剪切
File file =new File("cc.jpg");
File newFile=new File("dd.jpg");
file.renameTo(newFile));//File的名称将改为newFile的名称
④判断功能:
public boolean isDirectory()/isFile()/exists()/canRead()/canWrite()/isHidden
判断是否为目录、文件、存在、可读、可写、隐藏
⑤获取功能
public String getAbsolutePath();
获取绝对路径
public String getPath();
获取相对路径
public String getName()
获取名称
public long length()
获取长度,即字节数
public long lastModified()
获取最后一次的修改时间,返回毫秒值
⑥高级获取功能
public String[] list()
返回一个字符串数组,这些字符串数组指定此抽象路径名表示的目录中的文件和目录的名称
public File[] listFiles()
获取指定目录下的所有文件或者文件夹的File数组
File file=new File("e:\\");
String[] strArray=file.list();
for(String s:strArray){
System.out.println(s);
}
File[] fileArray=file.listFiles();
for(File f:fileArray){
System.out.println(f.getname());
}
例题1:判断e盘目录下是否有后缀名为.jpg的文件,如果有,输出该文件名称
-封装e判断目录
-获取该目录下所有文件或文件夹的File数组
-遍历该File数组,得到每一个File对象,然后判断。首先判断其是否是文件,是的话进行下一步。再判断其是否已.jpg结尾。是则输出该文件名称,否则不属输出
File file=new File("e:\\");
File[] fileArray=file.listFiles();
for(File f:fileArray){
if(f.isFile()){
if(f.getName().endWith(".jpg")){
System.out.println(f.getName());
}
}
}
用文件过滤器改进以上案例
文件名名称过滤器:
public String[] list(FilenameFilter filter)
public Filter[] listFiles(FilenameFilter filter)
File file=new File("e:\\");
String[] strArray=file.list(new FilenameFilter(){
public boolean accept(File dir,String name){
File file=new File(dir,name);
boolean falg=file.isFile();
boolean flag2=name.endsWith(".jpg");
return flag&&falg2;
//或return new File(dir,name).isFile()&&name.endsWith(".jpg");
}
})
for(String s:strArray){
System.out.println(s);
}
@例题2:批量修改文件名
-封装目录
-获取该目录下所有文件的File数组
-遍历该File数组,得到每一个File对象
拼接一个新的名称,然后重命名即可
File srcFolder=new File("E:\\english");
File[] fileArray=srcFolder.listFiles();
for(File file:fileArray){
String name=file.getame();
int endIndex=name.lastIndexOf("_");
String nameString=name.substring(endIndex);
String newName=numberString.concat(nameString);
File newFie=new File(srcFolder,newName);
file.renameTo(newFile);
}