/**
/*
* StringBuilder提供了对字符串编辑的
* 相关方法:
* 增:append
* 删:delete
* 改:replace
* 插:insert
*/
集合 collection 是集合的接口
Iterator 迭代器
Iterator iterList= list.iterator();//List接口实现了Iterable接口
while(iterList.hasNext()){
String strList=(String)iterList.next();
System.out.println(strList.toString());
* List 可重复且有序
* 特点:可以根据下标操作元素,这一点和数组很像
* ArratList:使用数组实现,查询更快
LinkedList: 使用链表实现,增删更快(收尾增删效果明显)
*
*/E set(int index,E e)
将给定的元素设置到指定位置上,返回值为
原位置的元素。所以是替换元素操作
集合提供了一个方法转换为数组 toArray (new String[c.size()])
Array.asList 数组转集合 //修改集合就是修改数组 不能添加删除元素会异常
排序集合元素
排序集合使用的是集合的工具类Collections(集合的工具类)的静态方法sort
排序仅能对List集合进行 因为Set部分实现类是无须的
sort 方法要求集合元素必须实现Comparable<>接口,
该接口用于规定实现类是可以比较的。 //需要重写下面的方法
其有一个抽象方法是用来定义比较大小的规则。
(左边 点到原点的距离长的大)
Queue 队列 首尾增删快 指向对象链表LinkedList
queue.offer 向对位追加一个新元素
queue.poll取出一个元素
queue.peek 引用一个元素
栈 Deque 存储一组元素,但是存取元素必须遵循先进后出原则
通常为了实现后退这类功能时会使用栈
双端对垒,两端都可以进出对
当只调用冲一端进出队操作时,就形成了栈结构
因此,双端队里为栈提供了两个方法:
push ,pop
Map看起来像是一个多行多列的表格
是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
以Key-value对的形式存放元素。
在Map中Key不允许重复(重复是依靠key的equals判断)
常用的实现类为:HashMap
HashMap 性能
当一个类(自己写的类的时候)的实例作为HashMap的key时,它的equals方法与hashcode方法
的重写直接影响这散列表(HashMAP)的查询性能
在API文档中Object对这两个方法的重写做了说明:
当我们重写一个类的equals方法时,就应当连同重写hashcode方法
方法应当遵循:
1.一致性,当两个对象euqals比较给true时,hashcode方法返回的数字
必须相等。反过来虽然不是必须的,但也应当遵循,否则在HashMap中会形成
链表影响查询性能。所以两个对象hashcode值相同,equals比较也应当为true;
2:稳定性:hashcode方法多次调用后返回的数字应当相同,
是一个变化的值,除非参与equals比较的属性值发生了改变。
创建一个数组只占4分之3
由于Map要求key不予许重复,所以使用Map已有的key存入一个新的value
时的操作是替换value,那么返回值为该key原来对应的value
若是一个新的key,则返回值为null。
Map<String,Integer> map=new HashMap<String,Integer>();
Integer value=map.put("生物", 100);
System.out.println("old:"+value);
map.put("语文", 99);
map.put("数学", 55);
map.put("化学", 22);
map.put("物理", 33);
map.put("英语",31);
value=map.put("生物", 97);
System.out.println(map);
System.out.println("old:"+value);
get(K k) 根据给点的key获取对应value,
若当前Map中没有给定的key,则返回给null
//取元素
value=map.get("数学");
System.out.println("数学:"+value);
value=map.get("地理");
System.out.println("地理:"+value);
remove删除
遍历Map 有三种方式:1;所有的key 2;所有的key-value 3;所有的value
keySet()(返回collection集合) 遍历方法
java.util.Map.Entry Set<String> keySet=map.keySet();
for(String key:keySet){
System.out.println(key);//遍历键值
}
Set<Entry<String,Integer>> entrySet=map.entrySet();
for(Entry<String,Integer> e:entrySet){
String key=e.getKey();
Integer value1=e.getValue();
System.out.println(key+":"+value1);
} //获取键值和value 返回Set集合
Collection<Integer> value2=map.values();
for(Integer a:value2){
System.out.println(a);
创建文件 在当前目录 delete删除目录只能删除空目录
File file=new File("test.txt");
if(!file.exists()){
file.createNewFile();
System.out.println("已执行");
}else{
System.out.println("已存在");
}
if(file.exists()){
file.delete();
System.out.println("删除完毕");
}else{
System.out.println("不存在");
}
File die=new File("demo");
if(!die.exists()){
die.mkdirs();
System.out.println("已创建");
}else{
System.out.println("已存在");
}
//创建多级目录
File dir=new File("a"+File.separator+
"b"+File.separator+
"c"+File.separator+
"d"+File.separator
);
if(!dir.exists()){
dir.mkdirs();
System.out.println("创建完毕");
}else{
System.out.println("已存在");
}
//遍历当前目录
File dir1=new File(".");
if(dir1.isDirectory()){//判断是否为目录
File[] sub=dir1.listFiles();//获取子目录
for(File subs:sub){
if(subs.isFile()){
System.out.println("是文件:"+subs);
}else{
System.out.println("是目录:"+subs);
}
System.out.println(subs.getName());
}
}
public static void delete(File file){//删除目录方法
if(file.isDirectory()){//删除所有子项
//File[] sub=file.listFiles();
for(File subs:file.listFiles()){
delete(subs);
}
}
file.delete();
}
java.io.RandomAccessFile
用来读写文件数据
RAF是给予指针进行读写的,既,RAF总是在指针指向的位置读写字节,
并且读写后指针会自动向后移动。
RAF既可以读取文件数据也可以向文件中写入数据
RandomAccessFile raf=new RandomAccessFile("raf.txt","r");
第二个参数 r 只读 rw 读写
若想提高读写效率,可以通过提高每次读写数据量来减少读写次数达到
read(byte[] data) 一次性尝试读取给定的字节数组总长度的字节量
并存入到该数组中,返回值为实际读取到的字节量,若返回值为-1,
则表示本次没有读取到任何数据。
void write(byte[] d,int start,int len)从开始到指定的字节
1 流
根据方向不同分为输入流与输出流,参照点为当前程序
输入流用来读取数据,输出流用来写出数据
java.io.InputStream
抽象类,定义了输入流的读取字节方法,所有的字节输入流都继承他
java.io.OutputStream则是所有字节输出流的父类
流分类节点流与处理流
节点流,也叫低级流,是真实负责读写数据的流
读写操作中必须要有低级流。数据源明确
处理流,也叫高级流。读写可以没有高级刘,高级流也不能独立存在,必须
用于处理其他流,处理其他流的目的是简化读写数据中的操作。
java.io.FileOutputStream
文件输出流,是一个低级流,作用是向文件中写出字节
默认创建的FOS是覆盖写操作
FOS会先将文件数据(若哟数据)全部删除,然后再开始写
再创建FOS时,若指定第二个参数,并且改制给ture时,则是追加写操作
,那么本次通过FOS写出的内容会被追加到该文件末尾。
使用文件流复制文件
使用文件输入流读取原文件,再使用文件输出流向目标文件中写。
顺序从源文件中读取每个字节并写入到目标文件即可完成复制
缓冲流 java.io.BufferedInputStream
java.io.BufferedOutputStream
缓冲字节输入输出流是一对高级流,使用它们可以加快读写效率
高级流可以处理其他流,但是无论添加了多少高级流,最低下都要有低级流,
因为低级流是真实读写数据的流,高级流都是处理数据的;
高级流处理其他流就形成了流的连接,并且有效的组合不同的高级流可以得到叠加效果。
关闭流时,只关闭最外层的高级流即可
缓冲流内部有一个缓冲区
当bis.read方法读取第一个字节时,实际上BIS会一次性读取一组字节并
存入内部的字节数组中,然后将第一个字节返回,当再次调用read方法是,
BIS直接冲字节数组中所有字节全部返回后,才会再次读取一组字节,
所以缓冲流也是依靠提高一次读写的数据量减少读写次数来达到提高读写效率的
对象流 是一对高级流,作用是方便读写java中的对象
java.io.ObjectOutputStream
对象输出流,可以将给定的对象转为一组字节后写出
当一个类需要被对象流读写,这个类必须实现Serializable 接口;
实现接口后应添加一个常量:SerialVersionUID
该常量会为当前类的序列化版本号,若不定义系统会跟根据当前类的
结构生成,但是只要类的结构发生改变,版本号也会改变。
反序列化会发生异常.
将一个对象转换一组字节的过程称为:对象序列化
做长久保存的过程称为:对象持久化
java.io.ObjectInputStream
对象输入流,作用是可以进行对象反序列化,读取一组字节并还原为对象.
OSI读取的字节必须有OOS将对象序列化得到的字节,否则会抛出异常
transient关键字用来修饰属性
当被修饰后,该类实例在使用oos进行对象序列化时,该属性值被忽略,达到瘦身目的
字符流的读写单位为字符
字符流都是高级流,虽然以字符为单位读写数据
但是实际底层还是读写字节,只是从字节与字符的转换工作交给字符流来完成
java.io.Reader:祖父输入流的顶级父类
java.io.Writer:祖父输出流的顶级父类
转换流
java.io.OutputStreamWriter
特点是可以按照指定字符集写出字符
java.io.InputStreamReader;
之所以称OutputStreamWriter与InputStreamReader为转换流,是因为大多数的字符流都只处理其他字符流,而低级流又是字节流,这就导致字符流不能处理字节流的问题,
转换流相当于是一个转换器的作用,他们可以将字节流先转变为字符流,这样其他
的字符流就可以处理了。
'
缓冲字符流
BufferedWriter ,
特点是可以按行读写字符串
java.io.PrintWriter
具有自动行刷新的缓冲字符输出流
创建PW时,它一定会在内部创建BufferedWriter作为缓冲功能的叠加
PrintWriter(File file)
PrintWriter(String path)构造方法可以直接对文件进行写出
提供的方法可以传入字节流,也可以处理字符流
并且,当使用这类构造方法时,可以再传入第二个参数,该参数
为Boolean值,该值为true时,则具有了自动刷新功能
若PrintWriter具有自动刷新功能,那么每当调用println方法就
会自动 flush(实时写入)
BufferedReade缓冲字符输入流 特点是按行读取字符串
* String readLine()
* 一次读取一行字符串,该方法会判断
* 读取到换行符为止,将之前的一行
* 字符串返回
* 若该方法返回的字符串为null,说明
* 没有数据可读了。
异常
这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。-
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
当内存不够,文件为null,小标越界的时候程序报错
java 异常捕获机制中的try-catch
try块是用类扩上可能出错代码片段
catch是用来处理try块中捕获的异常
应当养成一个好习惯,在最后一个catch中捕获Exception。避免因
未捕获异常导致程序中断。
异常子类在上父类在下 Exception是父类
走完catch 走finally 必须走的
throw 抛异常
当一个方法中使用throw抛出一个异常时,就要在方法上使用throws声明
该类异常的抛出以通知调用者解决。
只有RuntimeException 及其子类异常使用throw抛出时不强制要求必须使用throws声明,其他异常都是强制要求的,否则编译不通过
当调用一个含有throws声明异常抛出的方法时,编译器要求必须处理该异常。
1.使用tey--catch捕获并处理
2.在当前方法上继续使用throws声明该异常的抛出。
第一种创建线程的方式
继承Thread并重写run方法来定义线程要执行的任务。
有两个不足:
1.由于java是单继承,那么当继承了Thread后就无法再继承其他类
2.由于继承Thread后重写run方法规定了线程执行的任务,这导致
线程与任务有一个必然的耦合关系,不利于线程的重用;
启动线程要指定start方法,而不是直接调用run方法
run方法是线程要执行的任务,当线程的strat方法被调用后,
线程进入runnable状态,一旦获取cpu时间,run方法会自动调用
第二种创建线程的方式
实现Runnable接口并重写run方法
static Thread .currentThread()
获取运行当前方法线程
线程优先级
线程的时间片分配完全听线程调度的,线程只能被动的被分配时间,对于
线程调度的工作不能干预。
但是可以通过提高线程的优先级来达到尽可能干预的目的;
理论上,优先级越高的线程,获取CPU时间片的次数就越多
static void sleep(long ms)
线程提供的静态方法sleep可以使运行该方法的线程进入阻塞状态指定毫秒,
超时后线程会自动回到RUNNABLE状态
Thread.sleep()
守护线程,又称为后台线程
当一个进程中所有的前台线程都结束时,进程就要结束,若患有后台线程运行,
那么后台线程会被强制结束
jeck.setDaemon(true); 设置为后台线程 并且要在start前调用
void join()
join 方法可以使调用该方法的线程进入阻塞状态,直到该方法所属线程完成
工作才会解除调用该方法线程的阻塞状态
join方法一般用来完成多个线程之间的同步工作问题
局部匿名内部类 调用变量,变量要放在main方法外部
多线程并发访问同一资源时,就会形成“抢”的现象,由于线程切换时间不确定
,可能导致执行代码顺序的混乱,严重时会导致系统崩溃。
当一个方法被synchronized修饰后,该方法为同步方法,即:多个线程不能同时进入方法内部执行。
解决多线程并发执行安全问题的办法就是将“抢”变为“排队”
同步锁 synchronized修饰的同一段代码
同步块,有效的缩小同步范围可以保证并发安全的同时,尽可能提高并发效率;
同步块可以要求多个线程对该快内的代码排队执行,但是前提条件是同步监视器对象即(上锁的对象)要求多个线程看到的必须是同一个
synchronized(同步监视对象){需要同步的代码}
同步执行即:多个线程必须排队执行
异步执行即:多个线程可以同时执行
静态方法的同步
当一个静态方法被synchronized修饰后,那么该方法即为同步方法,
由于静态方法从属类,全局就一份,所以同步的静态方法一定具有同步效果。
与对象无关
互斥锁
synchronized也叫互斥锁,即:使用synchronized修饰多段代码,只要他们的同步
监视器对象相同,那么这几段代码间就是互斥关系,即:多个线程不能同时执行这些代码
线程池的作用:
控制线程数量
重用线程
当我们的应用需要创建大量线程或者发现线程会频繁的创建和销毁的时,就应当考虑使用线程池来维护线程