Stream
作用:操作数组、集合、主要减少遍历
中间方法:
过滤:-->filter(s -> {return 条件)
排序:--> sorted()
排序,指定规则:-->sorted( (o1,o2)-->{ return 比较规则;})
去重 :-->distinc()
获取前n个:-->limit(long n)
跳过前n个:-->skip(long n)
数据进一步加工,做映射:-->map(s-> return 加工后的值)
合并流 :-->conca(流1,流2)
最终方法:
遍历:forEach(suutc)
统计个数:count()
最大值:max(o1,o2)->{排序规则,只能是升序})
最小值:min(o1,o2)->{排序规则,只能是升序})
收集流的方法:
目的:转化为数组、集合,因为实际开发中,拥挤和、数组更多
collect:
收集为List--- Collector.toList()
收集为set ----Collector.toSet()
收集为Map ---Collector.toMap(k->返回键的映射,v->返回值得映射)
收集为数组:---toArray()
Exception
分类:
编译时异常:属于Exception,编写代码会出现异常报错
运行时异常:属于RuntimeException,程序运行过程中报错
处理异常方式:
使用try..catch
格式:try{ 异常代码 }catch(Exception e){ 处理方案}
throws:直接抛出异常,让调用他的人处理,代码可以继续运行
try..catch..finally:在finally里面的代码一定会执行,他会在返回前执行
自定义异常:
创建一个类继承Exception/RuntimeException
写上两个构造器,一个无参,一个满参
在方法中先通过throw抛出异常对象。再在方法上throws异常类名【运行时异常,可以不用】
File
概念:代表文件、文件夹
创建对象:
构造器:File(String path)、File(String parent,String child)、File(File parent,String child)
路径:相对路径,当前所在项目的路径。绝对路径:带盘符路径
创建文件、删除文件的方法:
创建文件:creatrNewFile()
创建文件夹:mkdir()
创建多级文件夹:mkdirs()
删除文件、文件夹:delete(),文件夹需为空
判断文件类型、获取信息的方法
判断是否存在:exists()
判断是否为文件:isFille()
判断是否为文件夹:isDirectory()
获取文件大小:length()
获取文件名字:getName()
获取文件路径:getPath()
获取文件的绝对路径:getAbsolutePath()
获取最后修改时间:lastModified()
获取目录下所有文件:String[] list()、File[] listFiles()
递归
概念:方法自己调用自己
格式:直接递归:方法调用子。间接递归:方法互相调用
流程:层层递进,不断回归
使用场景:
多层遍历的时候:文件夹遍历、类目的创建
算法:二分查找、斐波那契数列、汉诺塔
IO流(后面以IO框架为主)
概念:输入(input)输出(Out)流
分类:
(1)字节输入流:InputStream
分类:
原始的字节输入流:把文件中的数据读取到程序中
字节缓冲输入流:把文件的数据读取到程序中。多了缓冲区,提高读的效率
数据流:把数据按照指定的类型读入。特有方法:readXxx类
型
反序列化流:可以读入到对象的程序中。
特有方法:readXxx类型,readObject()
方法:
读取一个字节:int read()
读取一个字节数组,返回长度:int read(byte[] bytes)
读取所有的字节:byte[] readAllBytes()
(2)字节输出流(OuputStream)
分类:
原始的字节输出流:把数据输出到文件中
字节缓冲输出流:把数据输出到文件中,多了一个缓冲区
打印流:把数据的原型保存到文件中,写的时候没类型,println。
数据流:把数据按照指定类型保存到文件中,写的时候有类型,write数据类型
序列化流:把对象保存到文件中,要实现序列化接口
特有方法:write数据类型,writeObject
方法:
写出一个字节:write(int n)
写出一个字节数组:write(byte[] bytes)
写出字节数组的一部分内容:write(byte[] bytes,int index,int length
(3)字符输入流:Reader
分类:
原始字符输入流:把文本的数据按照字符的方式读取到程序中
字符输出缓冲流:把文本的数据按照字符的方式读取到程序中。readLine()
转换流:可以读取不同编码的文件 , 把字节流转换为字符流
方法:
读取一个字符:read()
读取一个字符数组:int read(char[] chs)
读取数组的一部分数据:read(char[] chas,int index,int length)
(4)字符输出流:Writer
分类:
原始字符输出流:把程序中的内容按照字符的方式输出到文本中
字符输出缓冲流:把程序中的内容按照字符的方式输出到文本中,多一个缓冲区。newLine() 换行
转换流:实现把文本按照不同的编码写入到文件中
打印流:可以实现把内容按照不同类型直接写到文本中。println()
方法:
输出一个字符:write(int n)
输出一个字符数组:wirte(char[] chs)
输出数组的中某一部分数据:write(char[] chs , int index, int length)
输出一个字符串:write(String str)
输出字符串中某一部分的内容:wirte(String str, int index, int length)
Properties
作用:用于记录一些键值对的信息,而且这些信息相互之间没有太大的关联
常用方法:
加载Properties文件:load(输入流->j建议使用字符流)
添加数据到Properties对象中:setProperties(String key,String value)
把Properties文件写出:store(输出流->使用字符流,说明)
XML
作用:用于记录一些系统的配置信息:框架配置信息,Mybatis,Spring
解析:通过Dom4j
常用方法:
创建SAXReader的对象
读取xml文件的方法:read()->得到一个Document对象
获取跟标签:getRootElement()->Element
获取子标签的方法:
elements() 获取当前标签下所有的子标签
elements(String name) 获取指定名字的所有子标签
element(String name) 获取单个指定名字的子标签
获取标签中文本的方法:elementText(String name),getText()
获取属性值的方法:attributeValue(String name)
把程序的内容写出到xml文件中:
(1)手动拼接数据到StringBuilder中,然后再通过输出流输出
(2)使用Dom4j提供的技术:
先要创建以恶搞Document对象:DocumentHelper
再创建根标签
再给根标签创建属性/子标签
在使用一个输出流输出内容:XMLWriter
约束:
作用:约束xml文件写的内容
分类:
dtd:只约束内容,不约束类型
xsd schema:约束内容,也约束类型
Log
作用:记录系统的操作、异常
使用步骤:
(1)导3个jar包,接口的jar,核心jar,chassic的jar
(2)在src下引用logback.xml文件
(3)创建对象:Logger log = LoggerFactory.getLogger(xxx.class);
级别:
ALL:全开启
OFF:关闭
trace
debug
info
warn
error
多线程
概念:
作用:用来执行程序
并行:同一个时刻,同时执行多件事情
并发:某一个时间段,交替执行多件的事情
多线程执行的效果:因为cpu快速切换,所以看起来像是同时在运行
创建线程的方式:
(1)继承Thread类,重写run方法
好处:简单。缺点:扩展性差,没有返回值
(2)实现Runable接口,重写run方法
好处:扩展性强。缺点:没有返回值
(3)实现Callable接口:
步骤:
1、先用子类实现Callable接口要指定返回值的泛型,重写call方法
2、创建一个FutureTask的任务对象,封装Callable对象
3、创建Thread对象,把FutureTask封装进去
4、启动线程
5、通过FutureTask的get()方法,获取执行结果
好处:可以得到线程执行的结果。缺点:太复杂
线程API
构造器:Thread(String name)、Thread(Runnable r)、Thread(Runnable r , String name)
成员方法:
启动线程:start()
获取线程名字:getName()
设置线程名字:setName(String name)
获取当前线程:static Thread currentThread()
线程休眠:static void sleep(long time)
线程安全问题
造成线程安全问题的原因:多线程、共享资源、同时操作
处理的方案:
(1)同步代码块
格式:synchronized(锁){ }
锁的要求:实例方法:this。静态方法:类名.class
(2)同步方法
格式:public synchronized 返回值 方法名(){ }
(3)Lock锁
创建对象的方式:ReentrantLock r = new ReentrantLock()
加锁:lock。解锁:unlock (需搭配try..catch..finally)
线程通信:生产消费者模型
线程生命周期:(6个状态)
(1)new :创建线程对象的时候
(2)runnable:调用了start()方法
(3)blocked:没有锁对象
(4)wait:等待、调用了wait()方法
(5)time-waiting:计时等待,sleep(时间)、wait(时间)
(6)terminated:线程结束
线程池
作用:创建一个容器,存放线程。可以复用
提供的线程池:
Executors.newFixedThreadPool(个数);
创建任务对象 【Runnable / Callable】
提交任务
关闭线程池
自定义线程池
new ThreadPoolExecutor(
int 数量 , 核心线程数
int 数量, 总的线程数
int 时间 ,指定临时线程的存活时间
TimeUnit t , 时间单位
WorkingQueue, 指定等候区
工厂 , 用于生产线程,
拒绝策略 );
网络编程
网络三要素:
ip:网路设备的唯一标识
端口:程序的唯一标识
协议:数据传输的规则
udp通信
特点:无连接,不可靠通信
接收端:
流程:先创建一个接收端(指定端口)、准备数据包、接收数据
方法:
1. DatagramSocket socket = new DatagramSocket(端口);
2. DatagramPacket(字节数组, 数组长度 )
3. 调用 DatagramSocket的receive(数据包)
4. 调用DatagramPacket的getLength()获取接收到的数据的长度
发送端:
流程:先创建一个发送端 【端口可指定,可不指定】、准备数据包、发送数据
方法:
1. DatagramSocket socket = new DatagramSocket(端口);
2. DatagramPacket(内容字节数组, 数组长度 ,接收端的ip, 接收端的端口 )
3. 调用 DatagramSocket的send(数据包)
tcp通信
特点:面向连接、可靠通信
客户端:
Socket s = new Socket(对方ip, 端口)
获取输入流:getInputStream()
获取输出流:getoutputStream()
服务端:
ServerSocket server = new ServerSocket(端口)
接收连接方法:Socket accept()
Junit
作用:用于测试代码,以方法作为单元的方式测试
好处:可以实现自动化测试、可以生成测试报告、断言
常用注解:
@Test:用于测试方法
@Before(@BeforeEach):在每个方法执行前执行
@After(@AfterEach):在每个方法执行完执行
@BeforeClass(@BeforeAll):在所有方法执行前执行一次
@AfterClass(@AfterAll):在所有的方法执行完执行一次
Assertions:断言的类(5.x版本)
反射
作用:获取类的所有的成员,再去使用
好处:可以无视修饰符
使用场景:idea、框架
使用步骤:
(1)先获取这个类的class对象
类名.class、对象名.getClass、Class.forName(类全名)
(2)获取对应的成员:class对象.getDeclaredXxx(xxx)
构造器:constructor。属性字段:filed
方法:Method。注解:Annotation
(3)全部设置暴力反射(设置访问权):成员.setAccessible(true)
(4)使用成员:
构造器:构造器成员.newInstance(xxx , xx)
字段:字段成员.set(对象,值)。返回值 字段成员.get(对象)
方法:invoke(对象 ,参数...)
注解
作用:做标记(@Test 、@Override)
参数传递:@Book(name = "xxx" , price = 100)
定义:
public @interface 注解名{
8种基本数据类型
String
枚举
注解
Class
上面所有的类型的一维数组 }
元注解
作用:用来约束注解的注解
分类:
@Target:用来限定注解的使用范围
@Retention:用来限定注解的生命周期
source:在java文件中有
class:java文件有,class文件中也有
runtime:java文件有,class文件中也有 , 运行时也有
注解解析的步骤:
1. 先获取class对象
2. 获取注解所在的成分【方法、字段 、 类..】
3.判断当前成分上是否有指定注解:isAnnotationPresent(注解类型)
4. 获取这个注解:getDeclaredAnnotation(注解类型)
动态代理
作用:在不改变类的前提下,增强这个类的功能
使用步骤:
1. 先创建一个接口,让代理对象和 被代理对象 都有同样的方法
2. 创建被代理对象,创建一个子类,实现接口
3. 创建一个代理对象
Proxy.newProxyInstance( 当前类.class.getClassLoader(),
被代理对象.getClass().getIntefaces(),
new 匿名内部类 );
4. 在代理对象中,实现功能增强:在匿名内部类的invoke方法中写就OK
Proxy:实际上就是代理对象
method:代理对象执行的方法
args:代理对象执行方法时的参数