作业解析
- 描述HashMap内部实现原理
HashMap是一种存储机制,存储的是key-value对,key用来保证元素的唯一性。通过hash算法将要存储的对象打散,分布在不同的区间中。- 当添加对象时,先得到该对象的hashcode,通过hashcode定位到将要存储的区间上,然后将区间中原有的元素依次与该对象进行比对,比对原则有三个:hashcode是否相同、是否是同一对象、equals方法是否返回true。如果没有元素与之相同,则添加到该区间元素的末尾
- 通过key查询时,先得到key对应的hashcode, 然后定位到所在区间,简化了查询,最后按照上述的三个原则进行比对
- List Set Map区别
List
ArrayList: 有序,可重复,线程不安全
LinkedList: 手拉手,线程不安全
Vector: 线程安全- Set
HashSet: 不可重复,无序,使用键值对存储机制
TreeSet: 通过实现Comparable接口实现排序,或者包装一个对比器Comparator Map
HashMap: 键值对,不可重复
HashTable: 线程安全
描述HashSet和HashMap的区别
HashSet集合内部是通过HashMap进行实现的。使用的是HashMap中key部分。对象在添加进集合中时,首选会对hashcode进行处理(hashcode右移16位和自身做异或运算)得到一个经过处理的hash值,然后该值和集合的容量进行&运算,得到介于0和集合容量值之间一个数字。该数字表示着数组的下标。也就是该元素应该存放在哪个集合中。然后按照hashcode1()==hashcode2() && (是否同一对象 || equals() )与集合中已有元素进行对比,如果没有相同的元素,则添加该元素。-
编程实现文本文件的复制。合理设计程序,得到缓冲区的大小的高效区间。
提示缓冲区设置1k开始,不超过10M。public static void main(String[] args) throws Exception { FileWriter fw = new FileWriter("Test.txt"); int count=0; for(int i=0;i<=10000000;i++) { if(count<=1000) { count++; fw.write(i+","); } else { fw.write("\r\n"); count=0; } } fw.close(); System.out.println("over"); /* * 编程实现文本文件的复制。合理设计程序,得到缓冲区的大小的高效区间。 * 提示:缓冲区设置1k开始,不超过10M。 * */ int bufSize=1024;//缓冲区1k开始 long spendTime = 0;//耗费的时间 long minTime = Long.MAX_VALUE;//记录最少耗时 for(int i=1;i<=10*1024;i++) { long beginTime = System.currentTimeMillis(); copyFile("Test.txt","Test2.txt",i*bufSize); spendTime = System.currentTimeMillis()-beginTime; if(spendTime<minTime) { minTime = spendTime; System.out.println(i); } } System.out.println(minTime); System.out.println("over"); } /* * 按给定的缓冲区大小,复制文件src到des */ public static void copyFile(String src,String des,int bufSize) throws Exception { FileReader fr = new FileReader(src); FileWriter fw = new FileWriter(des); char[] buf = new char[bufSize]; int len = -1; while((len=fr.read(buf))!=-1) { fw.write(new String(buf,0,len)); } fw.close(); fr.close(); }
-
使用FileWriter,将1-1000000写入到文本中
package com.kokojia.io; import java.io.FileWriter; import java.io.IOException; public class FileWriterDemo { public static void main(String[] args) { /** * 使用FileWriter,将1-1000000写入到文本中 */ FileWriter fw = null; try { fw = new FileWriter("h1.txt"); for(int i=1;i<=1000000;i++) { fw.write(i+","); } } catch (IOException e) { e.printStackTrace(); } finally { if(fw!=null) { try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("over!"); } }
-
变长参数 + 增强for循环
package com.kokojia.io; public class AvgParAndForDemo { public static void main(String[] args) { /** * 变长参数 + 增强for循环练习 */ OutString("a","b","123","中国"); } //变长参数只能有一个,且必须是最后一位形参 private static void OutString(String...str) { for(String s: str) { System.out.println(s); } } }
行分隔符在java中可以通过方法得到
System.getProperty("line.separator"); //执行 系统属性名
系统属性名是line.separator
windows: \r\n
macOS: \n
字符缓冲区
- FileWriter没有缓冲区功能,本身没有新增任何功能,继承的OutputStreamWriter
-
等级树结构:Object ---> Writer ---> OutputStreamWriter ---> FileWriter
writer(){ //直接写入数据到文件中 sun.nio.cs.StreamEncoder.write(); }
-
- FileReader
- 继承关系树:Object ---> Reader ---> InputStreamReader ---> FileReader
- read()
读取一个字符 -
read(char[])
读取多个字符read(){ InputStreamReader.read(){ sun.nio.StreamDecoder.read(); } }
- BufferedReader
-
等级树结构:Object ---> Reader ---> BufferedReader ---> LineNumberReader
read(){ char[] cbuf = ... ; cbuf[xxx] = c; return c; }
-
避免对物理文件的频繁访问
public static void main(String[] args) throws Exception { BufferedReader bufReader = new BufferedReader(new FileReader("d:/foo.txt")); String line = null; while((line = bufReader.readLine())!=null) { System.out.println(line); } System.out.println("over"); bufReader.close(); /* * 使用LineNumberReader读取文件的行号 * 打印输出行号+"."+行内容 */ LineNumberReader lineNumReader = new LineNumberReader(new FileReader("d:/foo.txt")); while((line=lineNumReader.readLine())!=null) { int lineNo = lineNumReader.getLineNumber(); System.out.println(lineNo+"."+line); } lineNumReader.close(); System.out.println("------------"); /** * 使用FileReader和BufferedReader读取文本文件,观察消耗时间 */ //非缓冲reader FileReader fr = new FileReader("d:\\1.txt"); //缓冲reader BufferedReader br = new BufferedReader(new FileReader("d:\\1.txt")); //非缓冲循环读取 int len = -1; //开始时间 long beginTime = System.currentTimeMillis(); while((len=fr.read())!=-1) { } //结束时间 long endTime = System.currentTimeMillis(); fr.close(); System.out.println("reader over!花费了时间"+(endTime-beginTime));//42443 //缓冲循环读取 beginTime = System.currentTimeMillis(); while((len=br.read())!=-1) { } //结束时间 endTime = System.currentTimeMillis(); br.close(); System.out.println("bufreader over!花费了时间"+(endTime-beginTime));//18654 }
-
- BufferedWriter
- 对Writer进行包装,里面定义缓冲区,提供写入单个字符、char[]、String方法,提高写入效率
- 等级树结构:Object ---> Writer ---> BufferedWriter
- flushBuffer(): 清理缓冲区,将缓冲区数据写入目的地
-
close()方法: 包含flushBuffer()动作
static char[] buf = null; static { buf = new char[8192]; for(int i=0;i<8192;i++) { buf[i]='a'; } } public static void main(String[] args) throws Exception { PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("d:/foo.txt"))); out.println("hello word"); out.close(); System.out.println("over"); //非缓冲 FileWriter fw = new FileWriter("d:/1.txt"); //缓冲区 BufferedWriter bw = new BufferedWriter(new FileWriter("d:/2.txt"),1024*1024); /**************非缓冲区writer操作*******/ //最大次数 int max = 100000; //开始时间 long startTime = System.currentTimeMillis(); for(int i=0;i<max;i++) { fw.write(buf); } fw.close(); long endTime = System.currentTimeMillis(); System.out.println("wrtier over! 花费了时间:"+(endTime-startTime)); /**************缓冲区writer操作*******/ //开始时间 startTime = System.currentTimeMillis(); for(int i=0;i<max;i++) { bw.write(buf); } bw.close(); endTime = System.currentTimeMillis(); System.out.println("bufwrtier over! 花费了时间:"+(endTime-startTime)); }
内存回收机制
堆中的对象只有在没有引用时才会释放
byte[] bytes = new byte[1023][1024][1024];
byte[] b2 = bytes ;
.
.
.
.
bytes = null ;
几个重要的函数
flush() //清理
refresh() //刷新
clear() //清空
字节流
- OutputStream
- 输出流
- FileOutputStream
- 等级树: Object ---> OutputStream --->FileOutputStream
- InputStream
- 输入流
- FileInputStream
- 等级树:Object ---> InputStream --->FileInputStream
装饰模式:decorator
实现方式: Buffered 类继承Writer类,在类中添加Writer类型的成员变量,对象应方法进行重写时,调用成员变量的方法进行完成。
class BufferedWriter extends Writer{
Writer out;
char[] cb = new char[8192];
public void writer(String str){
//1.先将数据写入缓冲区
cb.xxx
//2.如果cb已满,再写入到out中
}
public void close(){
//1.清理cb
//2.关闭out
}
}
时间单位换算:
1s=1000ms
1ms=1000us
1us=1000ns
juint
- 单元测试框架
- 方便进行测试时使用
- 方法签名
import org.juint.Text
@Test
public void xxx(){
}
作业
- 阐述BufferedReader和BufferedWriter的工作原理,
是否缓冲区读写器的性能恒大于非缓冲区读写器的性能,为什么,请举例说明? 写入数据1~1000000数字到文件中,分别使用FileWriter和BufferedWriter实现,考察其效率的不同
- 文件切割:
把较大的文件切割成20k一个的小文件 文件合成:
把小文件合并成大文件文件归档解档:
0=txt,1=jpg,2=avi,3=gif- Charset类操作: isSupport()
通过该类验证平台是否支持一下字符集:
gb2312
GB2312
gbk
GBK
utf-8
utf8
iso8859-1
iso-8859-1取出平台默认的字符集
FileReader.getEncoding();
new String(,,,,,charset);使用FileInputStream + FileOutputStream / BufferedInputStream + BufferedOuputStream
实现大文件复制,比较复制效率。阐述对象回收的前提条件。