[toc]
一. Java集合类详解
- Connection接口
- 集合可以理解为一个动态的对象数组,不同的是集合中的对象内容可以任意扩充
- 集合的特点:
性能高
容易扩展和修改 - Collection的常用子类
List
Set
Queue List接口
- List接口可以存放任意的数据,而且在List接口中内容是可以重复的
- List接口常用子类:
ArrayList
Vector - 常用操作:
判断集合是否为空:boolean isEmpty()
查找指定的对象是否存在:int indexOf(Object o)
|比较|ArrayList|Vector|
|-|-|-|
|推出时间|JDK1.2之后推出|JDK1.0推出|
|性能|采用异步处理方式,性能高|采用同步处理方式,性能低|
|线程安全|属于非线程安全|属于线程安全|
Set接口
- Set接口中不能加入重复元素,但是可以排序
- Set接口常用子类
散列存放:HashSet
有序存放:TreeSet
- Iterator接口
- 集合输出的标准操作:
标准做法,使用Iterator接口 - 操作原理:
Iterator是专门的迭代输出接口,迭代输出就是将元素一个个进行判断,判断其是否有内容,如果有内容则把内容取出。
- 集合输出的标准操作:
- Map接口
- 保存形式:
Key—>value的方式保存 - 常用子类:
HashMap:无序存放,key不允许重复(非线程安全的)
Hashtable:无序存放,key不允许重复(线程安全的)
- 保存形式:
二. Java中的IO操作
作用:
IO也写作“I/O”,可理解为In和Out,即输入与输出。所以,IO体系的基本功能就是:读和写。IO流
- 作用:读写设备上的数据,硬盘文件、内存、键盘、网络…
- 根据数据的走向,可分为:输入流、输出流
- 根据处理的数据类型,可分为:字节流、字符流
字节流和字符流
- 字节流可以处理所有类型的数据,如MP3,图片、文字、视频等。在读取时,读到一个字节就返回一个字节。
在java中对应的类都以“Stream”结尾。
字符流仅能处理纯文本数据,如txt文本等。在读取时,读到一个或者多个字节,先查找指定的编码表,然后将查到的字符返回。
在Java中对应的类都以“Reader”或“Writer” 结尾
字符、字节和编码
字节(Byte)
- 字节是通过网络传输信息或再硬盘或内存中存储信息的单位,是计算机信息技术用于计量存储容量和传输容量的一种计量单位。
- 1个字节等于8位二进制,即一个8位二进制数,是一个狠具体的存储空间。
如0x01,0x45,0xFA,…
字符(Char)
- 字符是人们使用的几号,抽象意义上的一个符号。
如’1’,’中’,’a’,’¥’,’$’,…
字符集(Charset)
“字符集”也称为“编码”。
三者的区别,请看下表:
- 使用字节流读写数据
- 使用fileInputStream和fileOutputStream来进行文件的拷贝
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("Java01/text.txt");
FileOutputStream fileOutputStream = new FileOutputStream("Java01/newText.txt");
byte input[] = new byte[50];
while (fileInputStream.read(input) != -1) {
fileOutputStream.write(input);
}
fileInputStream.close();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
- 使用带缓冲的字节流读写数据
public static void main(String[] args){
try {
FileInputStream fileInputStream = new FileInputStream("Java01/text.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream,1000000);//设置缓冲区的大小
//大型文件对应的数组可以大一些,小文件对应的数组小一些
byte input[] = new byte[100000];
int count = 0;
long before = System.currentTimeMillis(); //读取之前的时间
while (bufferedInputStream.read(input)!=-1){
count++;
}
bufferedInputStream.close();
fileInputStream.close();
System.out.println(System.currentTimeMillis()-before+"ms"); //读取之后和之前的差值
System.out.println("都去了"+ count +"次");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
说明:通过多次调试缓冲区和字节数组的大小,来寻找文件读取效率最高的数据。
- 使用字符流读写数据
同样是,进行文件拷贝,现在使用字符流来读写数据,实例如下:
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("Java01/text.txt");
FileOutputStream fileOutputStream = new FileOutputStream("Java01/newText.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");//InputStreamReader使用指定的 charset 读取字节并将其解码为字符。
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
char input[] = new char[100];
int l = 0;
while ((l = inputStreamReader.read(input)) != -1) {
outputStreamWriter.write(input, 0, l); //将字符读入数组中的某一部分。
}
// while (inputStreamReader.read(input) != -1) { //读入数组的的字符会存在偏移,即多读出字符
// outputStreamWriter.write(input);
// }
outputStreamWriter.close();
inputStreamReader.close();
fileOutputStream.close();
fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
- 使用带有缓冲的字符流读写数据
即添加BufferedReader和BufferedWriter,会出现一个问题,就是写入文件的时候会丢弃换行符,可使用PrintWriter
PrintWriter实例化:
PrintWriter pw = new PrintWriter(outputStreamWriter,true);//实例化并强制自动刷新缓冲区数据
- FileReader与FileWriter
- 使用FileReader和FileWriter来读写一些纯文本文件,读写以字符为基准的文件。用法同上述几种文件读出方式类似,不做赘述。
- RandomAccessFile随机文件读写
实例代码:
MultiwriterFile.java
package com.william.RandomAccessFileTest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Created by william on 2016/11/25.
*/
public class MultiwriterFile {
static File file = new File("Java01/text.txt");
public static void main(String[] args) {
// if (file.exists()) {
// file.delete();
// }
// new WriteFile(file,1).start();
// new WriteFile(file,2).start();
// new WriteFile(file,3).start();
// new WriteFile(file,4).start();
// new WriteFile(file,5).start();
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
randomAccessFile.seek(300);
byte input[] = new byte[20];
randomAccessFile.read(input);
String str = new String(input);
System.out.print(str);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
WriteFile.java
package com.william.RandomAccessFileTest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Created by william on 2016/11/25.
*/
public class WriteFile extends Thread {
File file;
int block;
int L = 100;
public WriteFile(File file, int block) {
this.file = file;
this.block = block;
}
/**
* 文件随机读取示意图:
* 1 2(100) 3 4(300) 5
* |-----------------|-----------------|-----------------|-----------------|--------
* 0xL<-----100----->1xL
*/
public void run() {
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
randomAccessFile.seek((block - 1) * L);
randomAccessFile.writeBytes("This is block" + block);
for (int i=0;i<20;i++) {
randomAccessFile.writeBytes("-");
}
randomAccessFile.writeBytes("\n");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行写操作,输出结果:
This is block1——————–
This is block2——————–
This is block3——————–
This is block4——————–
This is block5——————–
执行读操作输出结果:
输出:输出20个字节长度
This is block4——
- 使用Apache IO库操作IO与文件
对原始java对文件的操作做了封装,使用起来更加的方便,详细请看Apache的官方API文档。
三. Java多线程编程
- 线程与进程
线程:
- 程序中的单独顺序的控制流
- 新城本身依靠程序进行运行
- 线程是程序中的顺序控制流,只能使用分配给程序的资源和环境
进程:
- 执行中的程序
- 一个进程可以包含一个或多个线程
- 一个进程至少要包含一个线程
单线程:
- 程序中只存在一个线程,实际上主方法就是一个主线程
多线程:
- 多线程是在一个程序中运行多个任务
- 多线程的目的是更好的利用cpu资源
- 线程的实现
- 在java中,线程的实现有两种:
①. 继承Thread类
②. 实现Runnable接口 - Thread类:
Thread类是在java.lang包中定义的,继承Thread类必须重写run()方法
定义格式:
class className extends Thread{
run(){};
}
实例:
public class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(name + ":" + i);
}
super.run();
}
}
说明:当在主方法中使用Start启动线程时,我们可以看到两个线程时并行执行的,即谁先拿到cpu的资源,谁就执行,并不是顺序执行的。
看部分输出结果:
…
B:25
B:26
B:27
B:28
B:29
A:0
B:30
A:1
A:2
A:3
…
- Runnable接口
实现Runnable接口中的run方法,与Thread的run方法一样,在主方法中调用时,如下调用:
MyRunnable r = new MyRunnable("A");
Thread t = new Thread(r);
t.start();
- 线程的状态
线程也有固定的操作状态:
- 创建状态:准备好了一个多线程的对象
- 就绪状态:调用了start()方法,等待cpu进行调度
- 运行状态:执行run()方法
- 阻塞状态:暂时停止执行,可能将资源交给其他线程使用
- 终止状态(死亡状态):线程销毁
- 线程的常用方法
- 取得线程名称
getName() - 取得当前线程对象
currentThread() - 判断线程是否启动
isAlive() - 线程的强行运行
join() - 线程的休眠
sleep() - 礼让
yield()
- 线程的优先级
优先级顺序设置:
- 1-MIN_PRIORITY
- 10-MAX_PRIORITY
- 5-NORM_PRIORITY
如果什么都不设置默认值是5
- 同步与死锁
- 同步代码块
在代码块上加上“synchronized”关键字,则此代码块就称为同步代码块 - 同步代码块格式:
synachronized(同步对象){
需要同步的代码块;
} - 同步方法
除了代码块可以同步,方法也是可以同步的 - 方法同步格式:
synchronized void 方法名称(){}
同步实例:
class MyThreadDemo implements Runnable {
private int ticket = 5;
public void run() {
for (int i = 0; i < 10; i++) {
tell();
}
}
public synchronized void tell() {
if (ticket > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车票:" + ticket--);
}
}
}
public class synchronizedtest {
public static void main(String[] args) {
MyThreadDemo m = new MyThreadDemo();
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
Thread t3 = new Thread(m);
t1.start();
t2.start();
t3.start();
}
}
而死锁,就相当与两个人耍赖皮,比如说:张三有十块钱,李四有一本书,张三说,你先把书给我,我就给你钱,李四说你先给我钱,我就给你书,两个人互不想让,就会陷入等待,就会出现死锁的状况。
- 线程的生命周期
不解释,上图:
四. Java中的HTTP通信
- 使用Http的Get方法读取网络数据
看下面博客吧,视频上讲的挺散,但是要感谢视频的老师,同时感谢博客的博主。:)
http://blog.csdn.net/luckyzhoustar/article/details/50259209
- 使用Http的Post方式与网络交互通信
啥都不说了,还是博客文章:
http://blog.csdn.net/thl331860203/article/details/51783434
- 使用HttpClient进行Get方式通信
使用Apache的HttpClient的jar包,具体的操作,自己网上查去吧,不像写了。
- 使用HttpClient进行Post方式通信
使用Apache的HttpClient的jar包,具体的操作,自己网上查去吧,不像写了。
做参考吧:
https://www.oschina.net/code/snippet_1591393_46723
五. Java中内部类,匿名内部类理解
http://blog.csdn.net/zzjjiandan/article/details/9189943
一般来说,有4种内部类:常规内部类、静态内部类、局部内部类、匿名内部类。
常规内部类
常规内部类和普通类最大的不同就是,它能访问(这里,访问的意思包括读和写)外部类的私有实例域。
具体参考博客:
http://blog.csdn.net/l294265421/article/details/46574009静态内部类
静态内部类和普通类的对比使用,讲的很好,感谢博主:
http://kenby.iteye.com/blog/1603803局部内部类
- 在局部内部类前不能用修饰符public和private,protected.
可以定义与外部类同名的变量
如果内部类没有与外部类同名的变量,在内部类中可以直接访问外部类的实例变量如果内部类中有与外部类同名的变量,直接用变量名访问的是内部类的变量,用this.变量名访问的也是内部类变量.
用外部类名.this.内部类变量名访问的是外部类变量
- 不可以定义静态变量和方法
- 可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的
- 可以访问外部类的所有成员
实例:
http://blog.csdn.net/l294265421/article/details/46583475
- 匿名内部类
如果只需要创建一个内部类的一个对象,就没必要给这个类一个名字。这个没有名字的内部类叫做匿名内部类。
实例:
http://blog.csdn.net/l294265421/article/details/46583759
小插曲:关于类的实例化顺序
1.在实例化一个类的对象时,先要实例化该类的成员变量,再执行该类的构造函数。
- 在实例化一个类的成员变量时,先要实例化静态成员变量,再实例化非静态成员变量。
- 一个类的静态成员变量只实例化一次,即只有一个拷贝,在该类的所有对象中共享。
- 执行一个类的静态成员函数时,该类的对象并没有生成,因此,只会实例化该类的静态成员变量,而不会实例化非静态成员变量,也不会执行构造函数。
最好自己写一个小的实例,然后自己debugger一下,这样更容易理解上述的总结,可以用下面的小实例:
class A{
private int a = 10;
private static int AA = 100;
public A(int a) {
this.a = a;
}
public void printA(){
System.out.println("this is A");
}
public static void printText(){
System.out.println("come here!");
}
}
public class newclasstest {
public static void main(String[] args){
A.printText();
A a = new A(22);
a.printA();
}
}