HashMap和File与IO
1、Collection
(1)体系结构Iterator Collection 子接口 List 实现类ArrayList、Vector、LinkedList Set HashSet…
Map 实现类 HashMap
(2)常用方法
(3)迭代器
- 使用增强for,底层就是迭代器 for(类型 变量:要遍历集合或者数组) { }
- 迭代器原理
- 首先创建迭代器对象,判断是否有下一个元素,指向下一个元素,获取出来
2、List集合
(1)List特点:有序的,可以重复元素,底层结构数组、链表…
(2)List常用方法:add get size…
(3)List遍历四种方式:普通for、增强for、迭代器、List迭代器
(4)实现类存储结构和扩容机制:ArrayList、Vector、LinkedList
3、Set集合
(1)set特点:没有重复,无序
(2)实现类和方法
(3)Set集合遍历:增强for、迭代器
4、Map集合
(1)Map特点:键值对 key-value
(2)Map集合方法和遍历
- 添加 put
- 删除(取出) remove
- 清空 clear
- 所有key ketSet
- 所有value values
一、HashMap底层结构和原理
(1)创建HashMap对象时候,初始化几个值,
- 主要:table代表数组默认null,负载因子默认0.75,边界值0
(2)第一次向HashMap添加元素 - 根据添加数据key计算hash值
- 判断当前table数组是否为空,第一次肯定是空,数组进行初始化
– 数组容量 16 ,临界值 12 - 根据数组初始长度和hash值得到数组某个位置,在位置添加元素(第一次加不存在重复问题)
(3)容量不超过临界值12时候,再次添加数据
- 根据添加数据key计算hash值
- 根据数组长度和hash值得到数组某个位置,在位置添加元素
– 判断数组这个位置上面是否存在元素,如果不存在,添加
– 如果位置存在元素,
— 判断位置元素key是否一样,如果key相同,替换,如果key不一样,链表存储
(4)容量超过临界值12,添加数据
- 根据添加数据key计算hash值
- 根据数组长度和hash值得到数组某个位置,在位置添加元素
– 判断数组这个位置上面是否存在元素,如果不存在,添加
– 如果位置存在元素,
— 判断位置元素key是否一样,如果key相同,替换,如果key不一样,链表存储
– 判断数组容量是否超过临界值,如果超过进行扩容
— 把数组大小2倍,临界值2倍
— 把数组元素重新编排
(5)在jdk1.8优化
- 如果数组容量64,链表节点8,把链表转换树形结构
二、Map集合补充
1、Hashtable解决线程安全问题,任何非 null 对象都可以用作键或值。
HashMap是线程不安全的,并允许使用 null 值和 null 键。
2、LinkedHashMap是HashMap子类
3、TreeMap
三、File文件操作
1、什么是File
File类是java.io包下代表与平台无关的文件和目录,也就是说如果希望在程序中操作文件和目录都可以通过File类来完成,
File类能新建、删除、重命名文件和目录。
2、常用方法
public class FileDemo1 {
public static void main(String[] args) throws IOException {
// 文件路径名
// String pathname = "D:\\aaa.txt";
// File file1 = new File(pathname);
// 文件路径名
String pathname2 = "E:\\0224\\bbb.txt";
File file = new File(pathname2);
//1 查看是否存在文件
boolean exists = file.exists();
//System.out.println(exists);
//2 获取文件路径和文件名称
// System.out.println("文件构造路径:"+file.getPath());
// System.out.println("文件名称:"+file.getName());
//3 public boolean isDirectory()` :此File表示的是否为目录。
//- `public boolean isFile()` :此File表示的是否为文件。
// System.out.println(file.isDirectory());
// System.out.println(file.isFile());
//相对路径
// ./ 当前目录下
// ../ 上层目录 ../../
//- public boolean createNewFile()` :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
//- `public boolean delete()` :删除由此File表示的文件或目录。 只能删除空目录。
//- `public boolean mkdir()` :创建由此File表示的目录。单层目录
//- `public boolean mkdirs()` :创建由此File表示的目录,包括任何必需但不存在的父目录。 多层目录
File f = new File("E:\\aaa.txt");
// System.out.println(f.exists());
boolean newFile = f.createNewFile();
// System.out.println(newFile);
// System.out.println(f.exists());
File f1 = new File("E:\\atguigu0224");
// System.out.println(f1.exists());
boolean mkdir = f1.mkdir();
// System.out.println(mkdir);
// System.out.println(f1.exists());
File f2 = new File("E:\\wwww\\abcd");
boolean mkdir1 = f2.mkdir();
// System.out.println(mkdir1);
boolean mkdirs = f2.mkdirs();
// System.out.println(mkdirs);
boolean f1delete = f1.delete();
// System.out.println(f1delete);
boolean f2delete = f2.delete();
// System.out.println(f2delete);
File dir = new File("E:\\wwww");
//获取当前目录下的文件以及文件夹的名称。
String[] names = dir.list();
for(String name : names){
System.out.println(name);
}
//获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息
File[] files = dir.listFiles();
for (File file1 : files) {
System.out.println(file1);
}
}
}
3、递归操作
package com.atguigu.io;
import java.io.File;
import java.io.IOException;
public class FileDemo2 {
public static void main(String[] args) throws IOException {
File file = new File("E:\\wwww");
listSubFiles(file);
}
//递归遍历所有目录
public static void listSubFiles(File dir) {
//判断
if(dir !=null && dir.isDirectory()) {
//获取dir里面内容
File[] files = dir.listFiles();
//files是否为空
if(files != null) {
//遍历
for(File file:files) {
//递归调研
listSubFiles(file);
}
}
}
System.out.println(dir);
}
}
四、IO
1、什么是io
(1)针对文件内容操作,Java中I/O操作主要是指使用java.io
包下的内容,进行输入、输出操作。
输入也叫做读取数据,输出也叫做作写出数据。
2、IO流分类
根据数据的流向分为:输入流和输出流**。
- 输入流 :把数据从其他设备
上读取到内存
中的流。
- 以InputStream,Reader结尾
- 输出流:把数据从内存
中写出到其他设备
上的流。
- 以OutputStream、Writer结尾
根据数据的类型分为:字节流和字符流。
- 字节流 :以字节为单位,读写数据的流。比如读取图片
- 以InputStream和OutputStream结尾
- 字符流 :以字符为单位,读写数据的流。比如读取文本
- 以Reader和Writer结尾
3、字节流-输出流(重点)
(1)字节输出流 OutputStream 向文件写入内容
(2)OutputStream有很多方法:write close
OutputStream子类 FileOutputStream,专门针对文件操作
(3)演示使用输出流写文件简单操作 asc码
public static void main(String[] args) throws Exception {
//创建操作文件输出流对象
OutputStream outputStream = new FileOutputStream("E:\\0224\\atguigu.txt");
//OutputStream outputStream = new FileOutputStream(new File("E:\\0224\\atguigu.txt"));
//向文件写入内容
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
//关闭输出流
outputStream.close();
}
(4)字节数组写内容
@Test
public void outFile01() throws Exception {
//创建操作文件输出流对象
OutputStream out = new FileOutputStream("E:\\0224\\a.txt");
//写内容
byte[] b = "尚硅谷".getBytes();
out.write(b);
//关闭
out.close();
}
(5)指定位置字符写到文件
@Test
public void outFile02() throws Exception {
//创建操作文件输出流对象
OutputStream out = new FileOutputStream("E:\\0224\\b.txt");
//写内容
byte[] b = "abcde".getBytes();
//write 第一个参数开始位置 索引
// 第二个参数 从开始位置取几个字符
out.write(b,2,2);
//关闭
out.close();
}
4、字节流-输入流(重点)
(1)字节输入流 InputStream,读文件,常用方法:close read
(2)InputStream子类 FileInputStream,专门进行文件读取操作
(3)调用read方法读取文件内容
public static void main(String[] args) throws Exception {
//创建操作文件输入流对象
InputStream inputStream = new FileInputStream("E:\\0224\\b.txt");
//读取文件内容
int read = inputStream.read();
System.out.println((char) read);
//关闭
inputStream.close();
}
(4)循环读取文件内容
@Test
public void readFile01() throws Exception {
//创建操作文件输入流对象
InputStream inputStream = new FileInputStream("E:\\0224\\b.txt");
//定义变量
int b;
//循环判断读取
while((b = inputStream.read())!=-1) {
System.out.println((char)b);
}
//关闭
inputStream.close();
}
(5)字节数组读取文件内容
@Test
public void readFile02() throws Exception {
//创建操作文件输入流对象
InputStream inputStream = new FileInputStream("E:\\0224\\b.txt");
//定义变量
int len;
//字节数组
byte[] b = new byte[1024];
//循环读取
while((len = inputStream.read(b))!=-1) {
System.out.println(new String(b));
}
//关闭
inputStream.close();
}
5、字节输入流和输出综合例子
public static void main(String[] args) throws Exception {
//E:\01.jpg
//1 创建输入流读取文件
InputStream in = new FileInputStream("E:\\01.jpg");
//2 创建输出流
OutputStream out = new FileOutputStream("E:\\0224\\001.jpg");
//3 流对接:把输入流内容放到输出流里面
int len;
byte[] b = new byte[1024];
while((len=in.read(b))!=-1) {
//把读到内容直接写到文件
out.write(b,0,len);
}
//4 关闭
out.close();
in.close();
}
6、字符流
(1)概述
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,
可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。
所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
(2)字符输入流 Reader,子类 FileReader
public class ReaderDemo {
public static void main(String[] args) throws Exception {
Reader reader = new FileReader("E:\\0224\\b.txt");
//字符数组读取
char[] cbuf = new char[1024];
int len;
while((len=reader.read(cbuf))!=-1) {
System.out.println(new String(cbuf,0,len));
}
reader.close();
}
}
(3)字符输出流 Writer,子类 FileWriter
7、其他流
(1)缓冲流
缓存:提高读速度
缓冲:提高写速度
-
字节输入流 InputStream – BufferedInputStream
-
字节输出流 OutputStream – BufferedOutputStream
-
字符输入流 Reader – BufferedReader
-
字符输出流 Writer – BufferedWriter
//缓冲流实现
@Test
public void test02() throws Exception {
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
BufferedInputStream fis = new BufferedInputStream(new FileInputStream("E:\\01.mp4"));
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream("F:\\01.mp4"));
// 读写数据
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
fos.close();
fis.close();
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("普通流复制时间:"+(end - start)+" 毫秒");
}
(2)转换流
public static void main(String[] args) throws Exception {
// 定义文件路径,文件为gbk编码
String FileName = "E:\\aaa.txt";
// 创建流对象,默认UTF8编码
InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));
// 创建流对象,指定GBK编码
InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK");
// 定义变量,保存字符
int read;
// 使用默认编码字符流读取,乱码
while ((read = isr.read()) != -1) {
System.out.print((char)read);
}
isr.close();
// 使用指定编码字符流读取,正常解析
while ((read = isr2.read()) != -1) {
System.out.print((char)read);// 大家好
}
isr2.close();
}