Java入门第二阶段---容器+IO流

本文深入解析Java集合框架,包括Collection接口、List接口、Set接口、Map接口及其实现类的特性与区别,如ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等。探讨容器体系、泛型使用、迭代器接口、集合工具类Collections的功能与应用,以及数据结构如哈希表、红黑树的原理。

容器
collection接口     接口存储一组不唯一,无序的对象
List接口   存储不唯一,有序的对象 
Set接口   存储唯一,无序的对象
ArrayList(数组),LinkedList(链表)是List接口的实现类
Vector和ArrayList底层结构相同,都是Object类型的数组
Vector的add方法是同步方法,ArrayList的add不是
Vector在创建对象调用构造方法的时候就有10个容量,而ArrayList是第一次调用添加方法后容量是10
ArrayList扩容是0.5倍的扩容,而Vector扩容是1倍的扩容
Vector是1.0版本,ArrayList1.2版
Vector是线程同步的,安全性高,效率低,反之ArrayList的线程是非同步的,安全性低,效率高

Map接口
实现Map接口的类用来存储键值对
Map接口的实现类有HashMap和TreeMap
Map类中存储的键值对通过键来标识,所以键值不能重复
HashMap和Hashtable的区别
版本不同HashMap是1.2,Hashtable 1.0
HashMap继承了AbstractMap,实现了Map接口,Hashtable继承了Dictionary实现Map接口(父类不同)
HashMap允许null值和null键,但null作为key只允许一个,Hashtable非null的键和值
HashMap是线程不同步的,安全性低,效率高, Hashtable是线程同步的,安全性高,效率低

HashMap底层实现
hashtable也叫散列表    特点:快,很快,神奇的快      结构:结构有很多种
最流行、最容易理解:顺序表+链表                主结构:顺序表
哈希表是如何添加数据的
1.计算哈希码,调用hashCode(),结果是int值,整数的哈希码取本身即可
2.计算在哈希表中的存储位置  y=k(x)=x%11   x:哈希码   k(x)函数    y:在哈希表中的存储位置
3.如果该位置上有元素,需要调用equals()方法比较元素内容是否相等,不相等则使用链表链接,如果相同则不再添加
4.哈希函数的选择  直接定址法       平方取中法     折叠法     除留取余法(y=x&11)查询相关资料
JDK1.8开始,当链表的个数>=8时,就会将链表转为红黑树,目的是减少查询比较的次数

二叉树,结点只能为0,1,2的树
二叉搜索/查找树
空树或者是每一个结点,左孩子都比结点小,有孩子都比结点大,有几层最多就找几次
平衡二叉树   AVL树  
空树或者它的左右两个子树的高度差(平衡因子)的绝对值不超过1
每个结点的平衡因子0,-1,1的二叉排序树

红黑树RBT
每个节点是黑色或者红色,根节点是黑色,以及叶子节点是黑色
如果一个节点是红色,那么他的孩子都是黑色
从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点,确保没有一条路径会比其他路径长两倍
红黑树是相对接近平衡的二叉树

TreeMap的使用和底层实现
键key唯一且有序,升序
底层数据结构:红黑树
!!!如果使用TreeMap或者TreeSet存储自定义对象做为Key时,要求必须具备比较规则,否则运行报错
!!!如果使用HashMap或者HashSet存储自定义对象时,要求对象类重写hashCode()和equals()方法
TreeSet的底层使用的是TreeMap ,TreeMap底层是红黑树

Set接口:唯一,无序
HashSet底层数据结构是hash表,主结构是数组,+链表
创建HashSet的时候,无参构造,创建一个HashMap的对象 

泛型(增强程序的可读性以及安全性)
在创建集合对象时,明确集合中所存储的元素的数据类型加<>写入数据类型
1.泛型类,在类名后面加<T>T可以理解为形参,在类中创建集合对象的时候加入是什么数据类型就是什么数据类型
2.泛型接口,在接口后面加<T>,在接口的实现类的时候定下数据类型或者这个实现类也是泛型类,数据类型则参考上面一条
3.泛型方法,类泛型方法,调用方法时的泛型方法(解决了参数个数相同的方法重载),以及可变参数
的泛型方法(解决了参数个数不同的方法重载)

泛型的高级使用--在容器中使用泛型
泛型的上限,使用关键字extends,表示参数化的类型可能是所指定的类型或者是此类型的子类
泛型的下限,使用关键字super,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至
Object类
泛型只在编译期间起作用

迭代器Iterator
ArrayList,LinkedList,HashSet,TreeSet,找一个数据都会有判断和取出的过程,但是由于底层结构不一样,
这种功能一样,实现不一样的放在一起也就是Iterator接口,Iterator接口实现是由内部类实现的

ListIterator接口是Iterator的扩展,方法比Iterator多,有add()方法,可以解决并发修改异常,因为由
ListIterator创建的对象可以调用add()方法,不需要用对象去调用add()方法,而Iterator没有此方法,
可以正向遍历也可以逆向遍历

Iterator遍历Map集合两种遍历方式
1.先取键的集合,然后加强For循环,遍历
2.取键值关系的集合,然后加强For循环,遍历

Collections工具类的使用
专门用来操作集合的工具类     构造方法私有,禁止创建对象    提供一系列静态方法实现对各种集合的操作
具体操作:搜索、复制、排序、线程安全化等
常用方法
Collection.addAll()       
Collections.binarySearch()      先排序,再搜索
Collections.copy()                     拷贝要注意源集合和目标集合的大小
Collections.fill()       Collections.max()       Collections.min()        Collections.reverse()反向,逆向
Collections.synchronizedList() 线程不同步的转成线程同步的

容器体系框架总结


IO流 Input  Output
1)在Java程序中,对于数据的输入输出操作以“流”方式进行
2)J2SDK提供了各种各样的“流”类,用以获取不同种类的数据:程序通过标准的方法输入输出
3)Java的流类型一般位于java.io包中
数据源 data source,提供原始数据的原始媒介,常见的:数据库、文件、其他程序、内存、网络连接、IO设备
流是一个抽象、动态的概念,是一连串连续动态的数据集合
流的方向分类:
输入流:数据源到程序 InputStream Reader 读进来
输出流:程序到目的地OutPutStream Writer写出去
处理数据单元分类:
字节流:按照字节读取数据(InputStream OutPutStream)
字符流:按照字符读取数据(Reader  Writer )
功能不同分类:
节点流:可以直接从数据源或目的地读写数据
处理流(包装流):不直接连接到数据源或目的地,是其他流进行封装,目的主要简化操作和提高性能
节点流和处理流的关系:
1)节点流处于io操作的第一线,所有操作必须通过他们进行
2)处理流可以对其他流进行处理(提高效率或操作灵活性)
InputStream 和OutPutStream是字节流,都是抽象类,不能创建实例,所以用其子类
Reader和Writer 是字符流,都是抽象类,不能创建实例,所以用其子类
FileInputStream  available   read   close 方法 read() 一个字节,0-255,-1  read(byte[] buf)字节的个数 -1
FileOutPutStream  write  flush  close 方法 write(int b)  write(byte[] buf)
使用字节流实现文件复制
源文件-->输入流-->中转站-->输出流-->目标

文件字符流
Reader 读取文件内容
read()一个字符,read(char [] cbuf) read(char[] cbuf,int off, int len)  available()  close()
Writer 写内容到文件
write(int c) write(char[] cbuf) write(char[] cbuf,int off,int len) write(String s )  flush();

缓冲字节流
BufferedInputStream和BufferedOutputStream是处理流
1)读文件和写文件都使用了缓冲区,减少了读写次数,从而提高了效率
2)当创建这两个缓冲流的对象时,会创建了内部缓冲数组,缺省使用32字节大小的缓冲区
3)当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
4)当写入数据时,首先写入缓冲区,当缓冲区满时,其中的数据写入所连接的输出流。使用方法flush()
可以强制将缓冲区的内容全部写入输出流
5)关闭流的顺序和打开流的顺序相反,只要关闭高层流即可,关闭高层流其实关闭的底层节点流
6)Flush的使用:手动将buffer中内容写入文件

缓冲字符流
BufferedReader
readLine()读取一个文本行的数据
BufferedWriter
newLine() 写入一个行分隔符
使用缓冲字符流是复制文本常用的方式

转换流
用于将字节流转化成字符流,字符流与字节流之间的桥梁
InputStreamReader处理流
把InputStream转换还成Reader
OutputStreamWriter处理流
把OutputStream转换成Writer
存在将字节流转换成字符流的转换流,因为字符流操作文本更简单,反之不存在

打印流(数据都成为了String类型)
PrintStream(字节流)
1)提供了一系列的print()和println(),可以实现将基本数据类型格式化成字符串输出,对象类型将先调用
toString(),然后输出该方法返回的字符串
2)System.out就是PrintStream的一个实例,代表显示器  输出流
3)System.err 也是PrintStream的一个实例,代表显示器  错误输出流
4)PrintStream的输出功能非常强大,通常需要输出文本内容,都可以将输出流包装成PrintStream后输出
5)PrintStream的方法都不抛出IOException

PrintWriter
1)PrintStream的对应字符流,功能相同,方法对应
2)PrintWriter的方法也不抛出IOException
3)复制文件时,可以使用PrintWriter代替BufferedWriter完成,更简单

数据流
DateInputStream和DateOutputStream
1)提供了可以存取所有Java基础类型数据(如:int,double等)和String的方法
2)处理流,只针对字节流,二进制文件
3)输入流链和输出流链
4)注意:只要关闭上层流即可
File-->Buffered-->Data  

对象流
对象序列化(Serialization)
ObjectOutputStream  写对象----序列化(对象的内存状态以字节的形式存储到磁盘的文件上)
ObjectInputStream 读对象----反序列化(磁盘上的字节形式的数据还原成对象的内存状态)

将Java对象转换成字节序列(IO字节流)
对象反序列化(DeSerialization)
从字节序列化中恢复Java对象

序列化以后的对象可以保存在磁盘上,也可以在网络上传输,使得不同的计算机考研共享对象(序列化
的字节序列是平台无关的)

只有实现了Serializable接口的类的对象才可以被序列化。Serializable接口中没有任何的方法,实现该
接口的类不需要实现额外的方法。
如果对象的属性也是对象,属性对应类也必须实现Serializable接口

序列化步骤
1)创建ObjectOutputStream对象
2)调用WriteObject()输出对象
3)关闭流

1)序列化能保存的元素
a)只能保存对象的非静态成员变量
b)不能保存任何成员方法和静态变量
c)不保存transient成员变量
d)如果一个对象的成员变量是一个对象,这个对象的成员变量也会保存
e)串行化(序列化)保存的只是变量的值,对于变量的任何修饰符都不能保存
2)使用对象流把一个对象写到文件时不仅保证该对象是序列化的,
而且该对象的成员对象也必须是可序列化的
3)如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且
会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化

对象序列化注意事项
1)同一个对象多次序列化的处理
a)所有保存到磁盘中的对象都有一个序列化编号
b)序列化一个对象中,首先检查该对象是否已经序列化过
c)如果没有,进行序列化
d)如果已经序列化,将不在重新序列化,而是输出编号
2)如果不希望某些属性(敏感)序列化,或不希望出现递归序列
a)为属性添加transient关键字
b)自定义序列化(不仅可以决定哪些属性不参与序列化,还可以定义属性具体如何序列化)
3)序列化版本不兼容
a)修改了实例属性后,会影响版本号,从而导致反序列化不成功
b)解决方法,为Java对象指定序列化版本号serialVersionUID

文件夹的复制
如果文件中有很多不同格式的文件选择用字节流
BufferedInputStream,BufferedOutputStream
FileInputStream,FileOutputStream
问题分析
(1)先复制一个文件
(2)指定目录下的所有文件
(3)指定目录下的所有文件以及子目录的文件

字节数组流
ByteArrayInputStream和ByteArrayOutputStream
1)数据源或目的地为:字节数组
2)只有字节流,没有字符流
3)节点流

设计模式--装饰器模式Decorator
职责:动态的为一个对象增加新的功能
装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系
代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
实现细节:
1)抽象构件角色ICar
2)具体的构件角色Car
3)装饰器角色 SuperCar
4)具体的装饰器角色 FlyCar、WaterCar、AICar
优点:
1)扩展对象功能,比继承灵活,不会导致类个数急剧增加
2)可以对一个对象进行多次装饰,创建出不同行为的组合,得到功能更大的对象
3)具体构建类和具体装饰类可以独立变化,用户可以根据需要,自己增加新的具体构件子类和具体装饰子类
缺点:
1)产生很多小对象。大量小对象占据内存,一定程度上影响性能
2)装饰模式易于出错,调试排查比较麻烦

IO流实现细节
1)抽象构件角色  InputStream OutputStream Writer Reader
2)具体构件角色  FileInputStream FileOutputStream
3)装饰器角色 FilerInputStrem FilerOutputStream
4)BufferedInputStream,BufferedOutputStream等

Apache IOUtils使用和Apache FileUtils的使用
Commons IO 是apache的一个开源的工具包,封装了IO 操作的相关类,使用 Commons IO 可以很方便的读写文件
1)FileUtils 中提供了许多设计文件操作的已封装好的方法
2)IOUtils 则是提供了读写文件的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值