这辈子没办法作太多事情,因此每一件都要作到精彩绝伦!java
People can't do too many things in my life,so everything will be wonderful 面试
本资料只进行简单介绍说明以及相关重要问题的解答;关于类的详细说明及使用请参考java API文档算法
本文参考的依据是:JDK API 1.6.0 中文版,下载地址:http://down.51cto.com/data/2300228数据库
面向对象语言对事物的体现都是以对象的形式,因此,为了方便对多个对象的操做,java就提供了集合类。编程
数组和集合同是容器,有何不一样?windows
数组能够存储基本类型和引用类型(对象)数据,长度固定;设计模式
集合只能存储对象,长度可变。数组
集合特色:安全
集合只用于存储对象,长度可变,能够存储不一样类型的对象。网络
Collection层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 容许有重复的元素,而另外一些则不容许。一些 collection 是有序的,而另外一些则是无序的。
成员方法:
boolean add(E e)
boolean remove(Object o)
void clear()
boolean contains(Object o)
boolean isEmpty()
int size()
boolean addAll(Collection c)
boolean removeAll(Collection c)
boolean containsAll(Collection c)
boolean retainAll(Collection c)
Object[] toArray()
把集合转成数组,能够实现集合的遍历
Iterator iterator()
迭代器,集合的专用遍历方式
boolean hasNext()
E next()
是一个接口,还不是具体类?
注意:不要屡次使用hasNext()方法,由于每次都是访问的同一个对象。
特色:有序(存储顺序和取出顺序一致),可重复。
A:栈 先进后出
B:队列 先进先出
C:数组 查询快,增删慢
D:链表 查询慢,增删快
E:树:
F:哈希表:
l ArrayList类概述
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
l Vector类概述
底层数据结构是数组,查询快,增删慢
线程安全,效率低
l LinkedList类概述
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
使用场景:要安全吗?
要:Vector(即便要,也不使用这个,后面再说)
不要:ArrayList或者LinkedList
查询多;ArrayList
增删多:LinkedList
什么都不知道,就用ArrayList
泛型:是一种特殊的类型,是一种把明确类型的工做推迟到建立对象或调用方法的时候才去明确的特殊的类型。
格式:<泛型类型>
注意:该类型只能是引用类型。
好处:
1, 把运行时期的问题提早到了编译期间;
2, 避免了强制类型转换;
3, 优化了程序设计,解决了×××警告线问题,让程序更安全。
泛型的由来:
Object类型做为任意类型的时候,在向下转型的时候,会隐含一个转型问题。泛型就是为了解决这个问题
泛型类
把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
泛型之通配符
l 泛型通配符<?>
任意类型,若是没有明确,那么就是Object以及任意的Java类了
l ? extends E
向下限定,E及其子类
l ? super E
向上限定,E及其父类
一个不包含重复元素的collection
l HashSet类概述
不保证 set 的迭代顺序
特别是它不保证该顺序恒久不变。
l HashSet如何保证元素惟一性
底层数据结构是哈希表(元素是链表的数组)
哈希表依赖于哈希值存储
添加功能底层依赖两个方法:
l int hashCode()
l boolean equals(Object obj)
执行顺序:
首先比较哈希值是否相同:
相同:继续执行equals()方法
返回true:元素重复了,不添加
返回false:直接把元素添加到集合
不一样:就直接把元素添加到集合
l LinkedHashSet类概述
元素有序惟一
由链表保证元素有序
由哈希表保证元素惟一
l TreeSet类概述
使用元素的天然顺序对元素进行排序
或者根据建立 set 时提供的 Comparator进行排序
a:天然排序(元素具有比较性)
让元素所属的类实现Comparable接口
b:比较器排序(集合具有比较性)
让集合构造方法接收Comparator的实现类对象
具体取决于使用的构造方法。
l TreeSet是如何保证元素的排序和惟一性的
底层数据结构是红黑树(红黑树是一种自平衡的二叉树)
Collection:
|--List有序,可重复
|--ArrayList:底层是数组,查询快,增删慢;线程不安全;
|--Vector:底层是数组,查询快,增删慢;线程安全;
|--LinkedList:底层是链表,查询慢,增删快;线程不安全;
|--Set无序或有序,惟一
|--HashSet:底层是哈希表;依赖hashCode和equals方法保证元素惟一(开发中自动生成这两个方法便可)
|--LinkedHashSet:底层是链表和哈希表,由链表保证元素有序,由哈希表保证惟一
|--TreeSet:底层是红黑树(一种自平衡的二叉树),由天然排序和比较器排序保证元素有序;根据比较的返回值是不是0决定惟一。
到底使用谁?
惟一吗?
是:Set
排序吗?
是:TreeSet
否:HashSet
若是你知道是Set,可是不知道是哪一个Set,就用HashSet。
否:List
要安全吗?
是:Vector
否:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
若是你知道是List,可是不知道是哪一个List,就用ArrayList。
若是你知道是Collection集合,可是不知道使用谁,就用ArrayList。
若是你知道用集合,就用ArrayList
将键映射到值的对象;一个映射不能包含重复的键;每一个键最多只能映射到一个值。
Map和Collection的区别:
1,Map是双列的,Collection是单列的
2,Map的键惟一,Collection的子体系Set是惟一的
3,Map集合的数据结构值针对键有效,跟值无关
4,Collection集合的数据结构是针对元素有效
Map接口成员方法
V put(K key,V value)
V remove(Object key)
void clear()
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
int size()
V get(Object key)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()
l HashMap类概述
键是哈希表结构,能够保证键的惟一性
LinkedHashMap :Map 接口的哈希表和连接列表实现,具备可预知的迭代顺序
l TreeMap类概述
键是红黑树结构,能够保证键的排序和惟一性
遍历MAP以及效率比对
咱们都知道遍历Map通常有3种方法,values(),keySet()和entrySet(),常见的是keySet用的多,简单容易理解,entrySet()是返回Map中的静态内部类Entry类类型的Set实例,固然了你别说forEach,forEach只是一种代替for(int i=0;;)和while()遍历的一种方式,底层也是用迭代器实现的,只不过把部分东西隐藏了,建议你们日常开发中能用forEach遍历,尽量的用这个,《Effective java》中也明确表示了,简单而不容易出错。
若是Map中有大量的元素,并且并发量又很高,这就涉及到采用哪一种遍历方法的问题,下面就来测试一下:
[java] view plain copy
Map<String,String>mapTest=new HashMap<String,String>();
for(int i=0;i<10000;i++){
mapTest.put(String.valueOf(i),String.valueOf(i) );
}
//一种遍历,keySet()方法
longstart=System.nanoTime();
Set<String>setEach=mapTest.keySet();
for(String key:setEach){
String value=mapTest.get(key);
}
long end=System.nanoTime();
System.out.println("keySet遍历map耗时"+(end-start)/1000+"微秒");
[java] view plain copy
//二种遍历,可用values()返回Collection<T>,不容易获得对应的key
start=System.nanoTime();
Collection<String>co=mapTest.values();
for(String value:co){
//遍历中也在建立value
}
end=System.nanoTime();
System.out.println("values遍历map(只获得值)耗时"+(end-start)/1000+"微秒");
[java] view plain copy
//三种遍历,用entrySet()方法返回Set<Map.Entry<T,T>>类型,再获取里边的Map.Entry
start=System.nanoTime();
Set<Map.Entry<String,String>>entrySet=mapTest.entrySet();
for(Map.Entry<String,String> entry:entrySet){
String key=entry.getKey();
String value=entry.getValue();
}
end=System.nanoTime();
System.out.println("entrySet遍历map耗时"+(end-start)/1000+"微秒");
通过屡次运行,结果大概都是这样的:
[java] view plain copy
keySet遍历map耗时9867微秒
values遍历map(只获得值)耗时2539微秒
entrySet遍历map耗时2783微秒
values()是返回Map的全部value的集合collection,只能遍历到值,很难遍历到key因此通常不用,除非在某种特殊场合,因此通常采用的第一种和第三种方式。而测试代表entrySet()方式遍历效率更高。
entrySet()方式遍历之因此快与keySet(),一个缘由是keySet至关与遍历了2次,一次是对key的Set集合的遍历,二次是每次遍历过程都要经过key和map.get(key)来获取value值。第二个缘由是map.get(key)获取的时候,底层其实根据key的hashcode值通过哈希算法获得一个hash值而后做为索引映射到对应table数组的索引位置,这是一次密集型计算,很耗费CPU,若是有大量的元素,则会使CPU使用率飙升,影响响应速度,而entrySet()返回的set里边元素都是Map.Entry类型,key和value就是这个类的一个属性,entry.getKey()和entry.getValue()效率确定很高。
因此日常开发过程当中,若是对Map讲究效率的遍历的话,仍是采用entrySet()方法。
Collections类概述
针对集合操做 的工具类
Collections成员方法
public static<T> void sort(List<T> list)
public static<T> int binarySearch(List<?> list,T key)
public static<T> T max(Collection<?> coll)
public staticvoid reverse(List<?> list)
public staticvoid shuffle(List<?> list)
IO流用来处理设备之间的数据传输
上传文件和下载文件
Java对数据的操做是经过流的方式
Java用于操做流的对象都在IO包中
File类的概述
文件和目录路径名的抽象表示形式
构造方法
public File(String pathname)
public File(String parent,String child)
public File(File parent,String child)
递归
方法定义中调用方法自己的现象
递归注意实现
要有出口,不然就是死递归
次数不能太多,不然就内存溢出
构造方法不能递归使用
递归解决问题的思想
找到出口
找到规律
按照数据流向
输入流 读入数据
输出流 写出数据
按照数据类型
字节流
字符流
什么状况下使用哪一种流呢?
若是数据所在的文件经过windows自带的记事本打开并能读懂里面的内容,就用字符流。其余用字节流。
若是你什么都不知道,就用字节流
IO流经常使用基类
l 字节流的抽象基类:
InputStream ,OutputStream。
l 字符流的抽象基类:
Reader , Writer。
l 注:由这四个类派生出来的子类名称都是以其父类名做为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
FileOutputStream写出数据
A:操做步骤
a:建立字节输出流对象
b:调用write()方法
c:释放资源
B:代码体现:
FileOutputStreamfos = new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();
C:要注意的问题?
a:建立字节输出流对象作了几件事情?
b:为何要close()?
c:如何实现数据的换行?
d:如何实现数据的追加写入?
FileInputStream读取数据
A:操做步骤
a:建立字节输入流对象
b:调用read()方法
c:释放资源
B:代码体现:
FileInputStreamfis = new FileInputStream("fos.txt");
//方式1
intby = 0;
while((by=fis.read())!=-1){
System.out.print((char)by);
}
//方式2
byte[]bys = new byte[1024];
intlen = 0;
while((len=fis.read(bys))!=-1){
System.out.print(newString(bys,0,len));
}
fis.close();
字节缓冲区流
A:BufferedOutputStream
B:BufferedInputStream
因为字节流操做中文不是特别方便,因此,java就提供了转换流。
字符流=字节流+编码表。
编码表
由字符及其对应的数值组成的一张表
常见编码表
ASCII: 字符集 美国标准信息交换码。用一个字节的7位能够表示。
ISO-8859-1: 拉丁码表。欧洲码表;用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
GB18030:GBK的取代版本
BIG5:通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”
Unicode:国际标准码,融合了多种文字。全部文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符
UTF-8不一样,它定义了一种“区间规则”,这种规则能够和ASCII编码保持最大程度的兼容:
它将Unicode编码为00000000-0000007F的字符,用单个字节来表示
它将Unicode编码为00000080-000007FF的字符用两个字节表示
它将Unicode编码为00000800-0000FFFF的字符用3字节表示
字符串中的编码问题
编码
String-- byte[]
解码
byte[]-- String
A:OutputStreamWriter
OutputStreamWriter(OutputStreamos):默认编码,GBK
OutputStreamWriter(OutputStreamos,String charsetName):指定编码。
B:InputStreamReader
InputStreamReader(InputStreamis):默认编码,GBK
InputStreamReader(InputStreamis,String charsetName):指定编码默认编码
字符流
Reader
|--InputStreamReader
|--FileReader
|--BufferedReader
Writer
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
IO流
|--字节流
|--字节输入流
InputStream
intread():一次读取一个字节
intread(byte[] bys):一次读取一个字节数组
|--FileInputStream
|--BufferedInputStream
|--字节输出流
OutputStream
voidwrite(int by):一次写一个字节
voidwrite(byte[] bys,int index,int len):一次写一个字节数组的一部分
|--FileOutputStream
|--BufferedOutputStream
|--字符流
|--字符输入流
Reader
intread():一次读取一个字符
intread(char[] chs):一次读取一个字符数组
|--InputStreamReader
|--FileReader
|--BufferedReader
StringreadLine():一次读取一个字符串
|--字符输出流
Writer
voidwrite(int ch):一次写一个字符
voidwrite(char[] chs,int index,int len):一次写一个字符数组的一部分
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
voidnewLine():写一个换行符
voidwrite(String line):一次写一个字符串
1:数据操做流(操做基本类型数据的流)(理解)
(1)能够操做基本类型的数据
(2)流对象名称
DataInputStream
DataOutputStream
2:内存操做流(理解)
(1)有些时候咱们操做完毕后,未必须要产生一个文件,就可使用内存操做流。
(2)三种
A:ByteArrayInputStream,ByteArrayOutputStream
B:CharArrayReader,CharArrayWriter
C:StringReader,StringWriter
3:打印流(掌握)
(1)字节打印流,字符打印流
(2)特色:
A:只操做目的地,不操做数据源
B:能够操做任意类型的数据
C:若是启用了自动刷新,在调用println()方法的时候,可以换行并刷新
D:能够直接操做文件
问题:哪些流能够直接操做文件呢?
看API,若是其构造方法可以同时接收File和String类型的参数,通常都是能够直接操做文件的
(3)复制文本文件
BufferedReaderbr = new BufferedReader(new FileReader("a.txt"));
PrintWriterpw = new PrintWriter(new FileWriter("b.txt"),true);
Stringline = null;
while((line=br.readLine())!=null){
pw.println(line);
}
pw.close();
br.close();
4:标准输入输出流(理解)
(1)System类下面有这样的两个字段
in标准输入流
out标准输出流
(2)三种键盘录入方式
A:main方法的args接收参数
B:System.in经过BufferedReader进行包装
BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));
C:Scanner
Scannersc = new Scanner(System.in);
(3)输出语句的原理和如何使用字符流输出数据
A:原理
System.out.println("helloworld");
PrintStreamps = System.out;
ps.println("helloworld");
B:把System.out用字符缓冲流包装一下使用
BufferedWriterbw = new BufferedWriter(new OutputStreamWriter(System.out));
5:随机访问流(理解)
(1)能够按照文件指针的位置写数据和读数据。
(2)案例:
A:写数据
B:读数据
C:获取和改变文件指针的位置
6:合并流(理解)
(1)把多个输入流的数据写到一个输出流中。
(2)构造方法:
A:SequenceInputStream(InputStreams1, InputStream s2)
B:SequenceInputStream(Enumeration<?extends InputStream> e)
7:序列化流(理解)
(1)能够把对象写入文本文件或者在网络中传输
(2)如何实现序列化呢?
让被序列化的对象所属类实现序列化接口。
该接口是一个标记接口。没有功能须要实现。
(3)注意问题:
把数据写到文件后,在去修改类会产生一个问题。
如何解决该问题呢?
在类文件中,给出一个固定的序列化id值。
并且,这样也能够解决×××警告线问题
8:Properties(理解)
(1)是一个集合类,Hashtable的子类
(2)特有功能
A:publicObject setProperty(String key,String value)
B:publicString getProperty(String key)
C:publicSet<String> stringPropertyNames()
(3)和IO流结合的方法
把键值对形式的文本文件内容加载到集合中
publicvoid load(Reader reader)
publicvoid load(InputStream inStream)
把集合中的数据存储到文本文件中
publicvoid store(Writer writer,String comments)
publicvoid store(OutputStream out,String comments)
10:NIO(了解)
(1)JDK4出现的NIO,对之前的IO操做进行了优化,提供了效率。可是大部分咱们看到的仍是之前的IO
(2)JDK7的NIO的使用
Path:与平台无关的路径。
Paths:包含了返回Path的静态方法。
publicstatic Path get(URI uri):根据给定的URI来肯定文件路径。
Files:操做文件的工具类。提供了大量的方法,简单了解以下方法
publicstatic long copy(Path source,OutputStream out):复制文件
publicstatic Path write(Path path,Iterable<?extends CharSequence> lines,Charset cs,OpenOption... options):
把集合的数据写到文件。
//复制文件
Files.copy(Paths.get("Demo.java"),newFileOutputStream("Copy.Java"));
//把集合中的数据写到文件
List<String> list = newArrayList<String>();
list.add("hello");
list.add("world");
list.add("java");
Files.write(Paths.get("list.txt"),list, Charset.forName("gbk"));
异常就是Java程序在运行过程当中出现的错误。
异常由来:问题也是现实生活中一个具体事务,也能够经过java 的类的形式进行描述,并封装成对象。其实就是Java对不正常状况进行描述后的对象体现。
Throwable
|--Error 严重问题,咱们不处理。
|--Exception
|--RuntimeException 运行期异常,咱们须要修正代码
|--非RuntimeException编译期异常,必须处理的,不然程序编译不经过
异常分三类:
骑车去旅行:
Error:走到半路上,发生山路塌陷,或者出现了泥石流,这个问题很严重,不是班长可以立马解决的。
Exception:出门前,班长要看看车轮子以及车链子等是否还在
RuntimeException:在骑车的过程当中,有好路不走,恰恰要走石子路
1,编译时异常
除了RuntimeException及其子类,Exception中全部的子类都是,这种异常必需要处理,要不编译通不过
2,运行时异常
RuntimeException及其子类都是,这种异常不用处理,编译会经过,不过这样的程序会有安全隐患,遇到这种异常是须要改代码的
3,严重错误问题
用Error进行描述,这个问题发生后,通常不编写针对代码进行处理,而是要对程序进行修正.一般都是由虚拟机抛出的问题
A:JVM的默认处理
把异常的名称,缘由,位置等信息输出在控制台,可是呢程序不能继续执行了。
B:本身处理
a:try...catch...finally
本身编写处理代码,后面的程序能够继续执行
b:throws
把本身处理不了的,在方法上声明,告诉调用者,这里有问题
finally的特色
被finally控制的语句体必定会执行
特殊状况:在执行到finally以前jvm退出了(好比System.exit(0))
finally的做用
用于释放资源,在IO流操做和数据库操做中会见到
继承自Exception或者RuntimeException,只须要提供无参构造和一个带参构造便可
异常的注意实现
A:父的方法有异常抛出,子的重写方法在抛出异常的时候必需要小于等于父的异常
B:父的方法没有异常抛出,子的重写方法不能有异常抛出
C:父的方法抛出多个异常,子的重写方法必须比父少或者小
ConcurrentModificationException异常
并发修改异常
A:出现的现象
迭代器遍历集合,集合修改集合元素
B:缘由
迭代器是依赖于集合的,而集合的改变迭代器并不知道。
C:解决方案
a:迭代器遍历,迭代器修改(ListIterator)
元素添加在刚才迭代的位置
b:集合遍历,集合修改(size()和get())
元素添加在集合的末尾
ArithmeticException数学运算异常
1、HashMap是非线程安全的,HashTable是线程安全的。
2、HashMap的键和值都容许有null值存在,而HashTable则不行。
3、由于线程安全的问题,HashMap效率比HashTable的要高。
A:Collection是单列集合的顶层接口,有两个子接口List和Set
B:Collections是针对集合进行操做的工具类,能够对集合进行排序和查找等
编译期异常 必需要处理的,不然编译不经过
运行期异常 能够不处理,也能够处理
throws
用在方法声明后面,跟的是异常类名
能够跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不必定会发生这些异常
throw
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则必定抛出了某种异常
百度
会,前。
何时序列化?
如何实现序列化?
什么是反序列化?
对象序列化是将对象状态转换为可保持或传输的过程。通常的格式是与平台无关的二进制流,能够将这种二进制流持久保存在磁盘上,也能够经过网络将这种二进制流传输到另外一个网络结点。
对象反序列化,是指把这种二进制流数据还原成对象。