class="p0">集合(面向接口编程)
?
装载单个对象的集合:
Java.util.Collection[I]
|--java.util.Set[I]:无序,且不能重复
|--java.util.HashSet[C]
|--java.util.TreeSet[C]
|--java.util.List[I]:有序,且可以重复
????|--java.util.ArrayList[C]
????|--java.util.LinkedList[C]
?
装载键值对的集合
java.util.Map<K,V>[I]
|--java.util.HashTable[C]
|--java.util.HashMap[C]
|--java.util.TreeMap[C]
?
对象比较时,需要重写?equals()?和?hashCode()?方法以实现自定义对象的相等规则。
相等的对象具有相同的hashcode?值。
?
java.util.Iterator[I]
所有实现了?java.util.Collection?接口的容器类都有一个?iterator()?方法,返回一个实现了?java.util.Iterator?接口的对象。Iterator对象称作“迭代器”,用以对容器内的对象进行遍历操作。
java.util.Iterator?接口定义的方法如下:
boolean?hasNext();
Object?next();
void?remove();
Iterator对象的?remove?方法是在迭代过程中删除对象唯一安全的方法!不能使用容器自身的?remove方法,会抛出异常!!!
?
?
增强的?for?循环
JDK1.5之后,新增一个for循环结构,对于遍历数组或者集合的时候比较方便。
?
java.util.Collections[C]:该类提供了一些静态方法?实现了基于List容器的常用算法。
?
?
java.lang.Comparable[I]:对象比较大小接口
该接口中仅含有一个方法:public?int?compareTo(Object?obj);
返回?0?表示?this?==?obj;
返回?正数?表示?this?>?obj;
返回?负数?表示?this?<?obj;
?
?
集合类中的数据结构及其速度
Array*?读快改慢;
Linked*?改快读慢;
Hash*?介于两者之间;
?
?
?
?
IO流(InputStream/OutputStream)
java.io.File类代表系统文件名(不代表文件本身!)
常见构造方法:
public?File(String?pathName);
public?File(String?parentPathName,?String?childPathName);
常见方法:
<参见API>
File类的静态属性?String?separator?存储了当前系统的路径分隔符;
?
java.io包定义了多个流模型。
根据流的方向不同分为:输入流、输出流;
根据处理数据单位的不同分为:字节流、字符流;
根据功能的不同分为:节点流(连接在数据上的流)、处理流(连接在流上的流);
?字节流
字符流
输入流
InputStream
Reader
输出流
OutputStream
Writer
?
?
查看API对应的方法。
打开流之后,一定要关闭!!!
?
?
InputStream类的基本方法:
//读取一个字节,并以整数的形式返回(0~255),如果读到结尾则返回-1;
int?read()?throws?IOException;
//读取一系列的字节,保存到数组buffer中,并返回实际读取的字节数,如果读到结尾则返回-1;
int?read(byte?[]?buffer)?throws?IOException;
//关闭流,释放内存
void?close()?throws?IOException;
?
?
OutputStream类的基本方法:
//向输出流中写入一个字节数据
void?write(int?b)?throws?IOException;
//将一个字节数组写入输出流
void?write(byte?[]?b)?throws?IOException;
//关闭流,释放内存
void?close()?throws?IOException;
//将输出流中的数据全部写出到目的地
void?flush()?throws?IOException;
?
?
Reader类的基本方法:
//读取一个字符,并以整数的形式返回(0~255),如果读到结尾则返回-1;
int?read()?throws?IOException;
//读取一系列的字符,保存到数组buffer中,并返回实际读取的字符数,如果读到结尾则返回-1;
int?read(char?[]?buffer)?throws?IOException;
//关闭流,释放内存
void?close()?throws?IOException;
?
?
Writer类的基本方法:
//向输出流中写入一个字符数据
void?write(int?c)?throws?IOException;
//将一个字符数组写入输出流
void?write(char?[]?c)?throws?IOException;
//将一个字符串写入输出流
void?write(String?s)?throws?IOException;
//关闭流,释放内存
void?close()?throws?IOException;
//将输出流中的数据全部写出到目的地
void?flush()?throws?IOException;
?
public?static?void?main(String?[]?args)?{
FileWriter?fw?=?new?FileWriter(“d:\\share\\hello.java”);
for(int?i=0;i<100;i++){
fw.write((char)i);
}
fw.close();
?
FileReader?fr?=?new?FileReader(“d:\\share\\hello.java”);
int?c?=?0;
int?ln?=?0;
while((c?=?fr.read())?!=?-1){
System.out.println((char)c);
}
fr.close();
?
}
?
?
处理流的类型
处理流类型
字符流
字节流
Buffering
BufferedReader
BufferedWriter
BufferedInputStream
BufferedOutputStream
Filtering
FilterReader
FilterWriter
FilterInputStream
FilterOutputStream
Converting?between?bytes?and?charactors
InputStreamReader
OutputStreamWriter
--
Object?Serialization
--
ObjectInputStream
ObjectOutputStream
Data?conversion
--
DataInputStream
DataOutputStream
Counting
LineNumberReader
LineNumberInputStream
Peeking?ahead
PushbackReader
PushbackInputStream
Printing
PrintWriter
PrintStream
?
?
缓冲流
缓冲流套接在相应的节点流之上,对读写的数据提供了缓冲功能,提高了读写的效率,同时增加了一些新的方法;
JDK提供了4种缓冲流,其常用的构造方法为:
BufferedReader(Reader?in);
BufferedReader(Reader?in,?int?size);?//size为自定义缓冲区的大小
BufferedWriter(Writer?out);
BufferedWriter(Writer?out,?int?size);
BufferedInputStream(InputStream?in);
BufferedInputStream(InputStream?in,?int?size);
BufferedOutputStream(OutputStream?in);
BufferedOutputStream(OutputStream?in,?int?size);
?
BufferedReader?提供了?readLine()?方法,用于读取一行字符串(以\r或\n分隔);
BufferedWriter?提供了?newLine()?方法,用于写入一个行分隔符;
对于输出的缓冲流,写出的数据会先在内存中缓存,使用?flush()?方法可将内存中的数据立刻写出。
?
public?static?void?main(String?[]?args)?{
BufferedWriter?bw?=?new?BufferedWriter(new?FileWriter(“d:\\share\\hello.java”));
for(int?i=0;i<100;i++){
String?s?=?String.valueOf(Math.random());
bw.write(s);
bw.newLine();
}
bw.flush();
bw.close();
?
BufferedReader?br?=?new?BufferedReader(new?FileReader(“d:\\share\\hello.java”));
String?str?=?null;
while((str?=?br.readLine())?!=?null){
System.out.println(str);
}
br.close();
}
?
?
转换流
InputStreamReader?和?OutputStreamWriter?用于字节数据到字符数据之间的转换。
InputStreamReader?需要和?InputStream?套接;
OutputStreamWriter?需要和?OutputStream?套接;
转换流在构造时可指定其编码集合,例如:
InputStream?is?=?new?InputStreamReader(System.in,”GBK”);
?
public?static?void?main(String?[]?args)?{
OutputStreamWriter?osw?=?new?OutputStreamWriter(
new?FileOutputStream(“d:\\share\\hello.java”));
osw.write(“helloworld”);
System.out.println(osw.getEncoding());
osw.close();
?
osw?=?new?OutputStreamWriter(
new?FileOutputStream(“d:\\share\\hello.java”,true),”GBK”);
osw.write(“helloworld”);
System.out.println(osw.getEncoding());
osw.close();
?
InputStreamReader?isr?=?new?InputStreamReader(System.in);//System.in?标准输入流,阻塞式
BufferedReader?br?=?new?BufferedReader(isr);
String?s?=?null;
while((s?=?br.readLine())?!=?null){
if(“exit”.equalsIgnoreCase(s)){
}
System.out.println(s.toUpperCase());
}
br.close();
?
}
?
?
数据流
DataInputStream?和?DataOutputStream?分别继承自?InputStream?和?OutputStream;
它们属于处理流,需要分别套接在InputStream?和?OutputStream?类型的节点流上;
DataInputStream?和?DataOutputStream?提供了存取与机器无关的Java原始数据类型(如int,double等)的方法。
?
?
Print流
PrintStream?和?PrintWriter?都属于输出流,提供了重载的?print()?方法;
println()?方法用于多种数据类型的输出;
PrintStream?和?PrintWriter?的输出操作不会抛出异常,用户通过检测错误状态获取错误信息;
PrintStream?和?PrintWriter?有自动?flush?功能。
?
PrintWriter(Writer?w);
PrintWriter(Writer?w,?boolean?autoFlush);
PrintWriter(OutputStream?os);
PrintWriter(OutputStream?os,?boolean?autoFlush);
PrintStream(OutputStream?os);
PrintStream(OutputStream?os,?boolean?autoFlush);
?
?
public?static?void?main(String?[]?args)?{
FileOutputStream?fos?=?new?FileOutputStream(“D:\\file.txt”);
PrintStream?ps?=?new?PrintStream(fos);
?
if(null?|=?ps){
System.setOut(ps);
}
?
int?i?=?0?;
for(char?c=0;c<=60000;c++){
System.out.println(c?+?””);
if(i++?>=?100){
System.out.println();
i?=?0;
}
}
}
?
?
Object流:直接将Object写入或者读出。
?
public?class?T?implements?Serializable?[标识接口]{
int?i?=?0;
int?j?=?9;
double?d?=?2.3;
int?k?=?0;
}
public?class?TestObjectIO?{
public?static?void?main(String?[]?args)?{
T?t?=?new?T();
t.k?=?8;
FileOutputStream?fos?=?new?FileOutputStream(“D:\a.txt”);
ObjectOutputStream?oos?=?new?ObjectOutputStream(fos);
oos.writeObject(t);
oos.flush();
oos.close();
?
FileInputStream?fis?=?new?FileInputStream(“D:\a.txt”);
ObjectInputStream?ois?=?new?ObjectInputStream(fis);
T?tReader?=?(T)ois.readObject();
System.out.println(tReader.i);
}
}
?
Serializable[标识接口]:序列化接口,实现此接口的类,可以被序列化。
externalizable:自定义序列化过程。
transient:透明,用来修饰成员变量,对象序列化时,该修饰符修饰的成员变量不予考虑。
?
?
多线程(Thread)
?
线程和进程的区别:
a.?每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有比较大的开销;
b.?线程可以看做是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程间的切换开销比较小;
c.?多进程:在操作系统中同时运行多个任务(程序);
d.?多线程:一个程序中,有多个顺序流同时执行。
?
java的线程是通过java.lang.Thread类来实现的。VM启动时会有一个由主方法(public?static?void?main(String?[]?args){})所定义的线程。
每个线程都是通过Thread对象的run()方法来完成特定操作,方法run()称为线程体。
通过调用Thread类的start()方法来启动一个线程(不能通过直接调用run方法来启动一个线程,属于方法调用)。
一个CPU同一时间只能支持一个线程;如果是多CPU或者多核,可支持多线程。
?
?
创建线程的方法:
第一种:继承java.lang.Thread类,重写run()方法,如下:
package?com.thread;
public?class?TestThread?{
public?static?void?main(String[]?args)?{
ThreadChild?t?=?new?ThreadChild();
t.start();
?
for?(int?i?=?0;?i?<?10000;?i++)?{
System.out.println("main?thread:"?+?i);
}
}
}
?
class?ThreadChild?extends?Thread?{
@Override
public?void?run()?{
for(int?i=0;i<1000;i++)?{
System.out.println("RunnableOne:"?+?i);
}
}
}
?
第二种:定义类c,实现java.lang.Runnable接口,创建Thread的实例,将c作为参数传递到Thread实例中;
查看API可知,Thread类本身已经实现了Runnable接口,如下:
package?com.thread;
public?class?TestThread?{
public?static?void?main(String[]?args)?{
RunnableOne?one?=?new?RunnableOne();
Thread?thread?=?new?Thread(one);
thread.start();
?
for?(int?i?=?0;?i?<?10000;?i++)?{
System.out.println("main?thread:"?+?i);
}
}
}
?
class?RunnableOne?implements?Runnable?{
@Override
public?void?run()?{
for(int?i=0;i<1000;i++)?{
System.out.println("RunnableOne:"+i);
}
}
}
?
?
线程状态转换
?
?
?
?
线程控制基本方法
isAlive();?//判断线程是否仍然可用
getPriority();?//获得线程的优先级数
setPriority();?//设置线程的优先级数
Thread.sleep(long?millis);?//将当前线程睡眠指定的毫秒数
join();?//调用某线程的该方法,将当前线程与该线程合并,即等待该线程结束,再恢复当前线程的运行
yield();?//让出CPU,当前线程进入队列等待调度
wait();?//当前线程进入对象的等待线程池(wait?pool)
notify()/notifyAll();?//唤醒等待线程池中的一个/所有等待线程
?
?
线程的优先级
a.?Java提供了一个线程调度器来监控程序中启动后进入就绪状态的所有线程;线程调度器按照线程的优先级决定应调度哪个线程来执行;
b.?线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5;
c.?有三个默认的int类型常量表示常用的优先级:
Thread.MIN_PRIORITY?=?1;
Thread.NORM_PRIORITY?=?5;
Thread.MAX_PRIORITY?=?10;
?
?
线程的关闭
Thread中有stop()方法用来关闭线程,但是已经过时,不推荐使用。应该使用如下方法来关闭线程,其中的原理为:
只需使线程跳出run()方法,即可使线程关闭(重点掌握原理)!
public?class?TestThread?implements?Runnable?{
private?boolean?flag?=?true;
?
@Override
public?void?run()?{
while(flag)?{
System.out.println("RunnableOne:");
}
}
?
public?void?shutdown(){
this.flag?=?false;
}
}
?
?
对于同一份资源,进行线程同步(加锁,线程独占)
public?class?Timer{
public?static?int?num?=?0;
public?void?add(String?name){
synchronized(this){?//对资源加锁,线程同步
num++;
Thread.sleep(1000);
System.out.println(name+",你是第"+num+"个使用timer的线程");
}
}
}
或者如下写法:
public?class?Timer{
public?static?int?num?=?0;
public?synchronized?void?add(String?name){?//执行该方法时,当前对象被锁定
num++;
Thread.sleep(1000);
System.out.println(name+",你是第"+num+"个使用timer的线程");
}
}
?
?
死锁(解决方法之一:将锁的粒度加粗)
public?class?DeadLock?implements?Runnable?{
public?static?void?main(String[]?args)?{
DeadLock?dl1?=?new?DeadLock();?dl1.flag?=?1;
DeadLock?dl2?=?new?DeadLock();?dl2.flag?=?0;
Thread?t1?=?new?Thread(dl1);?t1.start();
Thread?t2?=?new?Thread(dl2);?t2.start();
}
?
public?int?flag?=?0;
static?Object?obj1?=?new?Object();
static?Object?obj2?=?new?Object();
?
@Override
public?void?run()?{
if(flag?==?1)?{
synchronized(obj1)?{?Thread.sleep(500);?}
synchronized(obj2)?{?System.out.println("1");?}
}
?
if(flag?==?0)?{
synchronized(obj2)?{?Thread.sleep(500);?}
synchronized(obj1)?{?System.out.println("0");?}
}
}
}
?
一道面试题:
public?class?Synchro?implements?Runnable?{
public?static?void?main(String[]?args)?{
Synchro?s?=?new?Synchro();
Thread?t?=?new?Thread(s);
t.start();
?
Thread.sleep(1000);
s.methodTwo();
}
?
@Override
public?void?run()?{
methodOne();
}
?
public?int?b?=?10;
?
public?synchronized?void?methodOne(){
b?=?20;
Thread.sleep(5000);
}
?
public?void?methodTwo(){
System.out.println("b="+b);
}
}
?
看看b的值,思考原因:对方法加锁,仅仅表示其他线程不能同时执行该方法体内的语句。但是可以调用该对象的其他方法。
延伸一道题,如下:
?
public?class?Synchro?implements?Runnable?{
public?static?void?main(String[]?args)?{
Synchro?s?=?new?Synchro();
Thread?t?=?new?Thread(s);
t.start();
?
s.methodTwo();
}
?
@Override
public?void?run()?{
methodOne();
}
?
public?int?b?=?10;
?
public?synchronized?void?methodOne(){
b?=?20;
Thread.sleep(5000);
System.out.println("b="?+?b);
}
?
public?void?methodTwo(){
Thread.sleep(2500);
b?=?30;
}
}
?
结果:b=30
思考:对方法加锁,指的是方法体的语句不会同时被其他线程调用,除此之外,别无其他!!!认真体会。
?
经典线程题:生产者消费者问题(可以参考马士兵多线程视频)
/**
?*?生产者消费者问题模拟
?*/
public?class?ProduceConsumer?{
public?static?void?main(String[]?args)?{
Lanzi?lanzi?=?new?Lanzi();
Producer?producer?=?new?Producer(lanzi);
Consumer?consumer?=?new?Consumer(lanzi);
new?Thread(producer).start();
new?Thread(consumer).start();
}
}
?
/**
?*?生产者,不断的生产馒头
?*/
class?Producer?implements?Runnable?{
Lanzi?lanzi?=?null?;
?
Producer(Lanzi?lanzi)?{
this.lanzi?=?lanzi;
}
?
@Override
public?void?run()?{
for(int?i=0;i<10;i++)?{
Mantou?mantou?=?new?Mantou(i);
lanzi.push(mantou);
System.out.println("生产第"?+?mantou.id?+?"个馒头");
try?{
Thread.sleep((long)(200?*?Math.random()));//此行代码的作用是能够看到效果,非程序必须代码
}?catch?(InterruptedException?e)?{
e.printStackTrace();
}
}
}
}
?
/**
?*?消费者,不断的消费馒头
?*/
class?Consumer?implements?Runnable?{
Lanzi?lanzi?=?null;
?
Consumer(Lanzi?lanzi)?{
this.lanzi?=?lanzi;
}
?
@Override
public?void?run()?{
for(int?i=0;i<10;i++){
Mantou?mantou?=?lanzi.get();
System.out.println("消费第"?+?mantou.id?+?"个馒头");
try?{
Thread.sleep((long)(1000?*?Math.random()));//此行代码的作用是能够看到效果,非程序必须代码
}?catch?(InterruptedException?e)?{
e.printStackTrace();
}
}
}
}
?
/**
?*?馒头类
?*/
class?Mantou?{
int?id?;
Mantou(int?id){
this.id?=?id;
}
}
?
/**
?*?容器类
?*/
class?Lanzi?{
int?index?=?0;
Mantou?[]?arr?=?new?Mantou[10];
?
//增加馒头
public?synchronized?void?push(Mantou?mantou)?{
while(index?==?arr.length){?//此处必须是?while,不能是?if
try?{
this.wait();
}?catch?(InterruptedException?e)?{
e.printStackTrace();
}
}
this.notifyAll();
arr[index]?=?mantou;
index?++;
}
?
//减少馒头
public?synchronized?Mantou?get()?{
while(index?<=?0)?{?//此处必须是?while,不能是?if
try?{
this.wait();
}?catch?(InterruptedException?e)?{
e.printStackTrace();
}
}
this.notifyAll();
index?--;
return?arr[index];
}
}
?
wait()?方法和?sleep()?方法区别:
wait()?是java.lang.Object类的方法;
sleep()?是java.lang.Thread类的方法;
wait()?方法会使当前线程进入睡眠状态,除非被叫醒,否则不会自己醒过来;同时会将锁放开;
sleep()?方法睡眠一定时间后,会自行醒过来继续执行代码;而且睡眠过程中不会将锁放开,保持锁住状态;
?
?
网络编程
(略)
?