java-API 全——超过4000行

1.什么是JDK API:
1).JDK中包含大量的API类库,所谓API就是一些已写好,可提供直接调用的功能(这些功能以类的形式封装)
2). JDK API 包含的类库功能强大,经常使用的又:字符串操作,集合操作,文件操作,输入输出造成,网络操作,多线程等等。
2.JDK包结构
为了便于使用和维护,JDK类库按照包结构划分,不同功能的类划分在不同的包中;
经常使用的包如下:
包 功能
java.lang java程序的基础类,如字符串,多线程等,不需要import,可以直接使用
java.util 常用工具类,如集合,随机数产生器,日历,时钟等
java.io 文件操作,输入/输出操作
java.net 网络操作
java.math 数学运算相关操作
java.security 安全相关操作
java.sql 数据库访问
java.text 处理文字,日期,数字,信息的格式
3.文档注释
3.1) 以/开头,以/结束;
3.2)加在类和方法的开头,用于说明作者,时间,版本,要实现功能的纤细描述等信息
3.3)通过javadoc工具,可以轻松的讲次注释转换为HTML文档说明,学习者和程序员主要通过文档了解API的功能
4.文档注释规范:
/
*
*类功能说明…
*@author Lee Boynton (作者)
*@version 1.4(版本)
*@see java.lang.StringBuffer(参见)
*@since JDK1.0 (始于JDK版本)
*@param charsetName(参数说明)
*@return The resultant byte array (返回值说明)
@throws UnsupporteE…(异常抛出说明)
/
5.生成javadoc文档
5.1)为带骂添加文档注释/
*/
5.2)使用eclipse生成文档注释,首先点击file-Export-java–Javadoc-Next,然后选择你要生成的Javadoc的包,以及生成的Javadoc所存路径(Use Standard doclet),默认生成当前工程目录,点击Finish 即可。

StringBuffer 和 StringBuilder 的区别
StringBuffer是线程安全的,同步处理的,性能稍慢
StringBuilder是非线程安全的,并法处理的,性能稍快

———————————————————————————————————


                        **API**
字符串一旦创建,对象永远无法改变,但字符串引用可以重新赋值。
 java字符串中任何一个字符对应16(两个字节)的定长Unicode编码。

	/**
 	* int length()
 * 返回当前字符串长度(字符个数)
 	* @author Mr.Cui
	 */
	public static void main(String[] args) {
		String str = "我爱java";
		System.out.println("len:"+str.length());
	}}

         /**
         * int indexOf(String str)
* 返回给定字符串在当前字符串中的位置,若当
         * 前字符串不包含该内容则返回值为-1
 	* @author Mr.Cui
 	*/
	public static void main(String[] args) {
		//            0123456789012345
		String str = "thinking in java";
		
		int index = str.indexOf("in");
		System.out.println("index:"+index);
   //可以从指定位置开始查找
		index = str.indexOf("in", 3);
		System.out.println("index:"+index);
   //查找最后一次出现的位置
		index = str.lastIndexOf("in");
		System.out.println("index:"+index);
	
	}}

/**
 * String substring(int start,int end)
 * 截取指定范围内的字符串。两个参数为开始到
 * 结束的下标。
 * 注:java api有一个特点,通常用两个数字表示
 * 范围时都是"含头不含尾"的。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		//             0123456789012
		String host = "www.baidu.com";
		
		String sub = host.substring(4, 9);
		System.out.println(sub);
		
		//一个参数为截取到末尾
		sub = host.substring(4);
		System.out.println(sub);
	}}

	/**
	 * char charAt(int index)
 * 获取当前字符串中指定位置处对应的字符
 	* @author Mr.Cui
	 */
	public static void main(String[] args) {
		//            0123456789012345
		String str = "thinking in java";
		
		char c = str.charAt(9);
		System.out.println(c);
		
		/*
		 * 判断回文
		 * 上海自来水来自海上
		 */
		str = "上海自来水自来海上";
		for(int i=0;i<str.length()/2;i++) {
			char c1 = str.charAt(i);
			char c2 = str.charAt(str.length()-1-i);
			if(c1!=c2) {
				System.out.print("不");
				break;
			}
		}
		System.out.println("是回文");		
	}}

/**
 * String支持正则表达式方法之一:
 * boolean matches(String regex)
 * 用给定的正则表达式验证当前字符串是否符合
 * 其格式要求。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String email = "[email protected]";
		/*
 * 验证email格式的正则表达式
		 * \w+@\w+(\.[a-zA-Z]+)+
		 */
		String regex = "\\w+@\\w+(\\.[a-zA-Z]+)+";
		/*
 * 注意:matches方法指定的正则表达式就算不
 * 指定边界匹配符,也是做全匹配验证的。
		 */
		boolean match = email.matches(regex);
		if(match) {
			System.out.println("是邮箱");
		}else {
			System.out.println("不是邮箱");
		}	}}

/**
 * String replaceAll(String regex,String str)
 * 将当前字符串中符合正则表达式要求的部分替换
 * 为给定内容
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "abc123def456ghi789jkl";
		/*
 * 将数字部分替换为"#NUMBER#"
		 */
		String regex = "[0-9]+";
		str = str.replaceAll(regex, "#NUMBER#");
		System.out.println(str);
	}}


import java.util.Arrays;
/**
 * String[] split(String regex)
 * 使用给定的正则表达式来拆分当前字符串。
 * 并将拆分后的内容以字符串数组形式返回。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "abc123def456jhi789klm"; 
		String[] array = str.split( "[0-9]+");//0-9全部去除
		System.out.println(array.length);
		System.out.println(Arrays.toString(array));
	}}

/**
 * boolean startsWith(String str)开始
 * boolean endsWith(String str) 结尾
 * 判断当前字符串是否是以给定字符串开始或
 * 结尾的。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "thinking in java";
		//开始
		boolean starts = str.startsWith("thi");
		System.out.println("starts:"+starts);
		//结尾
		boolean ends = str.endsWith("va");
		System.out.println("ends:"+ends);
		
	}}

/**
 * StringBuilder专门用来修改字符串内容的API.
 * String由于其优化设计导致的问题就是不能频繁
 * 修改(每次都创建新对象)
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "努力学习java";
   //默认表示空字符串
    //StringBuilder builder= new StringBuilder();
		
		StringBuilder builder
			= new StringBuilder(str);		
		/*
 * 拼接字符串append()
		 */
		builder.append(",为了找个好工作!");
		/*
		 * StringBuilder的toString方法用来
 * 获取其内部表示的字符串内容toString
		 */
		str = builder.toString();
		System.out.println(str);
		
		
		/*
		 * 努力学习java,为了找个好工作!
		 * 努力学习java,就是为了改变世界!
*定向改变字符内容replace()
		 * replace()
		 */
		builder.replace(9, 16, "就是为了改变世界");
		System.out.println(builder);
		
		
		/*
		 * 努力学习java,就是为了改变世界!
		 * ,就是为了改变世界!
*定向删除字符内容delete()
		 * delete()
		 */
		builder.delete(0, 8);
		System.out.println(builder.toString());
		
		/*
		 * ,就是为了改变世界!
		 * 活着,就是为了改变世界!
*指定位置添加内容 insert()
		 * insert()
		 */
		builder.insert(0,"活着");
		System.out.println(builder.toString());
	}}

/**
 * StringBuilder修改性能
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		StringBuilder builder = new StringBuilder("a");
		for(int i=0;i<10000000;i++) {
			builder.append("a");
		}		
		System.out.println("执行完毕!");
	}}

/**
 * 字符串频繁修改带来的性能损耗
 *String是不变对象,每次内容更改都是创建新对象
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "a";
		for(int i=0;i<10000000;i++) {
			str += "a";
      //系统需要很长很长时间才能运行出结果,a结果有无数个
		}
		
		System.out.println("执行完毕!");
	}}

/*StringBuffer 和 StringBuilder 的区别
StringBuffer是线程安全的,同步处理的,性能稍慢
StringBuilder是非线程安全的,兵法处理的,性能稍快*/
 
/**
 * String是不变对象,JVM对其做了一个优化,在内存
 * 中开辟了一段区域作为常量池,凡是通过"字面量"形
 * 式创建的字符串对象都会缓存并重用。因为会重用
 * 对象,所以该对象内容不可变。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String s1 = "123abc";
       //s2,s3重用s1创建的字符串对象
		String s2 = "123abc";
		String s3 = "123abc";
		System.out.println(s1==s2);//true
		System.out.println(s1==s3);//true
      //修改内容会创建并引用新对象
		s1 = s1+"!";
		System.out.println("s1:"+s1);
		//s2,s3不受影响
		System.out.println("s2:"+s2);
      //new则一定创建新对象
		String s4 = new String("123abc");
		System.out.println("s4:"+s4);
		System.out.println(s2==s4);//false
		/*
           * 编译器有一个优化措施,当编译源代码
           * 时发现一个计算表达式所有参数都是字面
           * 量时,会直接进行计算,并将结果编译到
           * class文件中。
		 * 所以,下面的代码在class文件中为:
		 * String s5 = "123abc";
		 */
		String s5 = "123"+"abc";
		System.out.println("s5:"+s5);
		System.out.println(s2==s5);//true	
		/*
	 * 计算表达式一方为变量,那么会在运行期
	 * 拼接,那么会创建新对象
		 */
		String s = "123";
		String s6 = s + "abc";
		System.out.println("s6:"+s6);
		System.out.println(s2==s6);//false
		
	}	}


/**
 * String substring(int start,int end)
 * 完成方法,获取给定地址中的域名
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String url = "www.sohu.com";
		String name = getHostName(url);
		System.out.println(name);//sohu
		
		url = "http://www.tedu.com.cn";
		name = getHostName(url);
		System.out.println(name);//tedu
	}
	public static String getHostName(String url) {
		int start = url.indexOf(".")+1;
		int end = url.indexOf(".",start);
		return url.substring(start, end);
	}}

/**
 * 要求用户从控制台输入一个email地址,然后获取该email的用户名(@之前的内容)
 * @author Mr.Cui
 */
import java.util.Scanner;
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入email");	
		String num = scan.next();
		/**
		 * int indexOf(String str)
	 * 返回给定字符串在当前字符串中的位置,若当
	 * 前字符串不包含该内容则返回值为-1
		 * @author Mr.Cui
		 */
		int index = num.indexOf("@");
		/**  
		 * String substring(int start,int end)
	  * 截取指定范围内的字符串。两个参数为开始到
	  * 结束的下标。
		 * 注:java api有一个特点,通常用两个数字表示
		 * 范围时都是"含头不含尾"的。
		 * @author Mr.Cui
		 */
		String ss = num.substring(0, index);
		System.out.println(ss);

import java.util.Date;
/**
 * String imageRename(name)
 * 图片重命名
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String imageName = "abc.jpg";
		imageName = imageRename(imageName);
		System.out.println(imageName);
	}
	public static String imageRename(String imageName) {
   //按照"."拆分
	         String[] data = imageName.split("\\.");
		imageName 
			= System.currentTimeMillis()+"."+data[1];
		return imageName;
	}}

/**
*replaceAll(indet,String "**")
 * 和谐用语
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String regex = "(wqnmlgdsb|mmp|nc|mdzz|cnm|djb)";
		String message = "wqnmlgdsb!你怎么这么nc!cnm,你个djb!";
		message = message.replaceAll(regex, "***");
		System.out.println(message);
	}}

/**
 * String toUpperCase()//大写
 * String toLowerCase()//小写
 * 将当前字符串中的英文部分转换为全大写或者全小写
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "我爱Java";
		//大写
		String upper = str.toUpperCase();
		System.out.println("upper:"+upper);
		//小写
		String lower = str.toLowerCase();
		System.out.println("lower:"+lower);
	}}

  /**
 * String trim()
 * 去除一个字符串两边的空白字符
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "  hello			";
		System.out.println(str);
		String trim = str.trim();
		System.out.println(trim);
	}}

/**
 * String提供了一组重载的静态方法:valueOf
 * 可以将给定的内容转换为字符串
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		int d = 1;
		String str = String.valueOf(d);
		System.out.println(str);

		double dou = 1.1;
		str = String.valueOf(dou);
		System.out.println(str);	
		str = d+"";		
	}}

/**
 * 使用当前类测试重写Object相关方法
 * @author Mr.Cui
 */
public class Point {
	private int x;
	private int y;
	
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	/**
        * toString方法会被很多API调用。所以当我们
        * 定义一个类时,很常见的操作就是重写这个
         * 方法。
        * 该方法的意义是将当前对象转换为一个字符串
         * 形式。该字符串内容格式没有严格的要求。
         * 原则为包含这个对象的相关属性信息。
	 */
	public String toString() {
		//(1,2)
		return "("+x+","+y+")";
	}
	/**
 * equals的作用是比较当前对象与参数对象
 * 的内容是否一致。
	 */
	public boolean equals(Object obj) {
		if(obj==null) {
			return false;
		}
		if(this==obj) {
			return true;
		}
		if(obj instanceof Point) {
			Point p = (Point)obj;
			return this.x==p.x&&this.y==p.y;
		}
		return false;
	}}

/**
 * 测试Point重写的Object相关方法
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Point p = new Point(1,2);
		/*
	* 通常我们定义的类如果需要使用到
	 * toString方法时,就应当重写这个
	 * 方法,Object提供的输出的是该对象
	 * 的句柄,没有什么实际意义
		 */
		String str = p.toString();
		System.out.println(str);
		/*
		 * System.out.println(Object obj)
	 * 该方法会将给定对象的toString方法
	 * 返回的字符串输出到控制台
		 */
		System.out.println(p);
		
		
		Point p2 = new Point(1,2);
		System.out.println(p==p2);//false
		/*
	 * 我们定义的类如果使用equals,就应当
	 * 重写这个方法。Object提供的equals方法
	 * 本身内部就是用“==”进行比较的,没有
	 * 实际意义。
	 * 而java API提供的类,toString,equals
	 * 方法都妥善进行了重写。
		 */
		System.out.println(p.equals(p2));//true
	}}

/**
 * JDK1.5版本推出时推出了一个特性:
 * 自动拆装箱
 * 该特性是编译器认可的,当我们在基本类型和
 * 其对应的引用类型之间互相赋值时,编译器会
 * 自动补全代码在两者之间进行转换。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		/*
	 * 触发了编译器的自动拆箱特性:
	 * 编译器会补全代码,将包装类转换为
	 * 基本类型。
		 * 下面的代码会被编译器补充代码为:
		 * int d = new Integer(1).intValue();
		 */
		int d = new Integer(1);
		/*
	 * 触发自动装箱特性,编译器会补充代码
		 * Integer i = Integer.valueOf(d);
		 */
		Integer i = d;
	}}


/**
 * 包装类
 * 包装类是为了解决基本类型不能直接参与面向
 * 对象开发的问题。
 * 其中6个数字类型的包装类继承自Number类。
 * java.lang.Number是一个抽象类,定义了几个
 * 抽象方法,要求数字类型的包装类可以将其表示
 * 的数字以任意数字类型返回。
 * @author Mr.Cui
 */
public class IntegerDemo1 {
	public static void main(String[] args) {
		int d = 128;
		//转换为包装类
                            //Integer i1 = new Integer(d);
                            //Integer i2 = new Integer(d);
	//推荐用valueOf转换为包装类
		Integer i1 = Integer.valueOf(d);
		Integer i2 = Integer.valueOf(d);
		
		System.out.println(i1==i2);
		System.out.println(i1.equals(i2));
		
		/*
	 * 包装类转换为基本类型
		 */
		d = i1.intValue();
		System.out.println(d);
		
		double dou = i1.doubleValue();
		System.out.println(dou);
		
		byte b = i1.byteValue();
		System.out.println(b);
		
		
		/*
	 * 数字类型的包装类都定义了两个常量
	 * MAX_VALUE 最大值
	 * MIN_VALUE 最小值
	 * 用于表示该包装类对应的基本类型的
	 * 取值范围
		 */
		int imax = Integer.MAX_VALUE;
		System.out.println(imax);
		int imin = Integer.MIN_VALUE;
		System.out.println(imin);
		
		long lmax = Long.MAX_VALUE;
		System.out.println(lmax);
	}}


/**
 * 包装类都提供了一个静态方法:
 * parseXXX(String str)
 * 可以将字符串解析为对应的基本类型,但是需要
 * 注意,该字符串必须能够正确描述该基本类型可
 * 以保存的值,否则会抛出异常。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String str = "123";
		int d = Integer.parseInt(str);
		System.out.println(d);
		
		double dou = Double.parseDouble(str);
		System.out.println(dou);					
	}}


         /**
 * 读取文件数据
          * @author Mr.Cui
          */
	public static void main(String[] args) throws IOException {
		/*
		 * 读取当前目录中raf.dat文件内容
		 */
		RandomAccessFile raf
			= new RandomAccessFile("raf.dat","r");
		/*
		 * int read()
		 * 读取一个字节,并以int形式返回。
		 * 若返回值为-1则表示读取到了文件末尾。
		 * 00000000 00000000 00000000 00000001
		 */
		int d = raf.read();
		System.out.println(d);
		
		d = raf.read();
		System.out.println(d);//-1
		raf.close();
	}}

       
         /**
          * 若希望提高读写效率,可以通过提高每次实际读写
           * 的数据量,减少实际发生的读写操作来做到。
 * 单字节读写:随机读写
 * 一组字节读写:块读写
          * 机械硬盘(磁盘)的块读写效率还是比较好的。但是
          * 随机读写效率极差。
          * @author Mr.Cui
          */
	public static void main(String[] args) throws IOException {
		RandomAccessFile src
			= new RandomAccessFile("nox.exe","r");
		RandomAccessFile desc
			= new RandomAccessFile("nox_cp.exe","rw");
		
		/*
	 * RAF提供的块读写操作的方法:
		 * int read(byte[] data)
		 * 一次性读取给定的字节数组长度的字节
		 * 量并存入到该数组中。返回值为实际
		 * 读取到的字节量,若返回值为-1,表示
		 * 本次读取是文件末尾(没读到任何字节)
		 * 
	 * void write(byte[] data)
	 * 一次性写出给定字节数组中的所有字节
		 * 
	 * void write(byte[] data,int start,int len)
	 * 一次性写出给定字节数组中从start处开始的连续
		 * len个字节
		 */
		//记录每次实际读取到的字节量
		int len = -1;
		//每次要求读取的字节量
		//10kb
		byte[] data = new byte[1024*10];
		
		long start = System.currentTimeMillis();
		while((len = src.read(data))!=-1) {
			desc.write(data,0,len);
		}
		long end= System.currentTimeMillis();
		System.out.println("复制完毕!耗时"+(end-start)+"ms");
		src.close();
		desc.close();
	}}

          /**
 * java.io.RandomAccessFile
 * RAF是专门用来读写文件数据的API。其基于指针
          * 对文件数据进行读写操作,可以灵活的编辑文件
          * 数据内容。
 * 创建RAF时可以指定对该文件的权限,常用的有
 * 两种:
 * r:只读模式
 * rw:读写模式 
           * @author Mr.Cui
           */
	public static void main(String[] args) throws IOException {
		/*
	 * 对当前目录中的raf.dat文件读写
		 * RAF支持两种常用构造方法:
		 * RandomAccessFile(File file,String mode)
		 * RandomAccessFile(String path,String mode)
		 * 
	 * 注:相对路径中"./"是可以忽略不写的,因为
	 * 默认就是从当前目录开始。
		 * 
	 * RAF创建时含有写权限的情况下,当指定的文件
	 * 不存在时会自动将其创建出来。
		 */
		RandomAccessFile raf
			= new RandomAccessFile("raf.dat","rw");
		/*
		 * void write(int d)
	 * 向文件中写入1字节,写的是给定int值
	 * 对应2进制的“低八位”                 
		 *                            vvvvvvvv                               
		 * 00000000 00000000 00000000 00000001
		 * 11111111 11111111 11111111 11111111
		 * 
		 */
		raf.write(1);
		
		System.out.println("写出完毕!");
		
		raf.close();
	}}


           /**
 * 完成方法,实现删除给定File所表示的文件或目录
            * @author Mr.Cui
            */
	public static void main(String[] args) {
		File dir = new File("./a");
		delete(dir);
	}
	/**
        * 文件直接删除,目录的话要先清空该目录
        * 然后再删除
	 * @param f
	 */
	public static void delete(File f) {
		if(f.isDirectory()) {
			//先清空该目录
			File[] subs = f.listFiles();
			for(int i=0;i<subs.length;i++) {
				File sub = subs[i];
				//递归调用
				delete(sub);
			}
		}
		f.delete();
	}}

         /**
 * 创建一个多级目录
         * @author ta
         */
	public static void main(String[] args) {
		/*
	 * 在当前目录下创建:
		 * a/b/c/d/e/f目录
		 */
		File dir = new File("./a/b/c/d/e/f");
		if(!dir.exists()) {
			/*
	 * mkdir创建目录要求父目录必须存在
	 * mkdirs会将不存在的父目录一同的
	 * 创建出来
			 */
			dir.mkdirs();
			System.out.println("创建完毕!");
		}else {
			System.out.println("目录已存在!");
		}}}

          /**
 * 创建一个目录
           * @author Mr.Cui
           */
	public static void main(String[] args) {
		/*
            * 在当前目录中创建一个名为demo的目录
		 */
		File dir = new File("./demo");
		if(!dir.exists()) {
			dir.mkdir();
			System.out.println("目录已创建");
		}else {
			System.out.println("目录已存在");
		}}}

             /**
 * ListFiles提供了一个重载的方法,可以指定
 * 一个文件过滤器(FileFilter),然后将满足该
 * 过滤器要求的子项返回。
              * @author ta
              */
	public static void main(String[] args) {
		/*
	 * 获取当前目录中名字以"."开头的子项
		 */
		File dir = new File(".");
		
		FileFilter filter = new FileFilter() {
			public boolean accept(File file) {
				String name = file.getName();
				System.out.println("正在过滤:"+name);
				return name.startsWith(".");
			}		
		};
		
		File[] subs = dir.listFiles(filter);
		System.out.println(subs.length);
		for(int i=0;i<subs.length;i++) {
			System.out.println(subs[i].getName());
		}}}


             /**
 * 获取一个目录中的所有子项
              * @author Mr.Cui
              */
	public static void main(String[] args) {
		/*
	 * 获取当前目录中的所有子项
		 */
		File dir = new File(".");
		/*
		 * boolean isFile()
		 * boolean isDirectory()
	 * 判断当前File对象表示的是一个文件
	 * 还是一个目录
		 */
		if(dir.isDirectory()) {
			/*
			 * File[] listFiles()
	 * 该方法会将当前File表示的目录中所有
	 * 子项返回.
			 */
			File[] subs = dir.listFiles();
			for(int i=0;i<subs.length;i++) {
				File sub = subs[i];
				System.out.println(sub.getName());
			}}}}

/**
 * java.io.File
 * File的每一个实例用于表示硬盘上的一个文件或
 * 目录。
 * 使用File可以:
 * 1:访问其表示的文件或目录的属性信息(名字,大
 *   小,访问权限等信息)
 * 2:操作文件或目录(创建,删除)  
 * 3:访问目录子项
 * 但是不能访问文件数据。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		/*
       * 访问当前项目目录下的test.txt文件
		 * 
		 * 创建File时,指定的路径通常使用相对
		 * 路径,好处在于:可以跨平台。
		 * 相对路径到底相对哪里,要看程序的
		 * 运行环境指定的位置。
		 * 在eclipse中运行java程序时,指定的
		 * 相对路径中"当前目录"是当前程序所在
		 * 的项目目录,这里就是JSD1807_SE这个
		 * 目录
		 */
		File file = new File("./test.txt");
	//获取文件名
		String name = file.getName();
		System.out.println("name:"+name);
		
	//获取文件大小(字节量)
		long length = file.length();
		System.out.println("length:"+length);
	
		boolean cw = file.canWrite();//可写
		boolean cr = file.canRead();//可读
		System.out.println("可写:"+cw);
		System.out.println("可读:"+cr);
		
		boolean ih = file.isHidden();//隐藏
		System.out.println("隐藏:"+ih);
	}}


              /**
 * 删除一个文件
               * @author ta
               */
	public static void main(String[] args) {
		/*
	 * 将当前目录下的demo.txt文件删除
		 */
		File file = new File("./demo.txt");
		if(file.exists()) {
			file.delete();
			System.out.println("文件已删除");
		}else {
			System.out.println("文件不存在");
		}}}

           /**
 * 删除目录
           * @author Mr.Cui
            */
	public static void main(String[] args) {
		/*
	 * 删除当前目录下的demo目录
		 */
		File dir = new File("./demo");
		if(dir.exists()) {
			/*
		 * 删除目录要求该目录必须是一个
		 * 空目录。
			 */
			dir.delete();
			System.out.println("删除完毕!");
		}else {
			System.out.println("目录不存在!");
		}}}

          /**
 * 使用File创建一个文件
           * @author Mr.Cui
           */
public class CreateNewFileDemo {
	public static void main(String[] args) throws IOException {
		/*
		 * 在当前目录下创建一个名为:demo.txt
		 * 的文件
		 */
		File file = new File("./demo.txt");
		if(!file.exists()) {
			file.createNewFile();
			System.out.println("文件已创建");
		}else {
			System.out.println("文件已存在");
		}}}

            /**
 * 写入字符串操作
            * @author Mr.Cui
            */
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf
			= new RandomAccessFile("raf.txt","rw");
		String line = "大家好,我是渣渣辉。";
		/*
	 * String提供了转换为2进制的方法:
		 * byte[] getBytes();
		 */
                         //byte[] data = line.getBytes();
	//可以指定字符集进行转换(推荐这样的用法)
		byte[] data = line.getBytes("UTF-8");	
		raf.write(data);	
		System.out.println("写出完毕");
		raf.close();
		
	}}

              /**
 * 读取字符串
               * @author Mr.Cui
               */
	public static void main(String[] args) throws IOException {
		/*
	 * 将raf.txt文件中的字符读取出来
		 */
		RandomAccessFile raf
			= new RandomAccessFile("raf.txt","r");
		
		byte[] data = new byte[(int)raf.length()];
		raf.read(data);
		
		String str = new String(data,"UTF-8");
		System.out.println(str);
		
		raf.close();
		
	}}

             /**
 * RAF读写基本类型数据,以及RAF的指针操作
 *//创建文件 rw,读写文件r
              * @author Mr.Cui
              */
	public static void main(String[] args) throws IOException {
RandomAccessFile raf
			= new RandomAccessFile("raf.dat","rw");
		
		long pos = raf.getFilePointer();
		System.out.println("pos:"+pos);
		
		
	//写入一个int最大值到文件中
		int max = Integer.MAX_VALUE;
		/*
		 * int最大值的2进制形式:
		 *                            vvvvvvvv
		 * 01111111 11111111 11111111 11111111
		 * 
		 * max>>>24                            v这里开始溢出了
		 * 00000000 00000000 00000000 01111111 11111111 11111111 11111111
		 */
		raf.write(max>>>24);
		System.out.println("pos:"+raf.getFilePointer());
		raf.write(max>>>16);
		raf.write(max>>>8);
		raf.write(max);
		System.out.println("pos:"+raf.getFilePointer());
		/*
		 * void writeInt(int d)
	 * 连续写出4个字节,将给定的int值写出。
		 * 等同上面4次write方法。
		 */
		raf.writeInt(max);
		System.out.println("pos:"+raf.getFilePointer());
		raf.writeLong(123L);
		System.out.println("pos:"+raf.getFilePointer());
		raf.writeDouble(123.123);
		System.out.println("pos:"+raf.getFilePointer());
		System.out.println("写出完毕!");
		
	//写完后指针现在在文件末尾	
	//移动指针位置
	raf.seek(0);//移动到文件开始位置
		System.out.println("pos:"+raf.getFilePointer());
	//连续读取4字节还原int值
		int d = raf.readInt();
		System.out.println(d);
		System.out.println("pos:"+raf.getFilePointer());
		
	//读取long
		raf.seek(8);
		System.out.println("pos:"+raf.getFilePointer());
		long l = raf.readLong();
		System.out.println(l);//123
		System.out.println("pos:"+raf.getFilePointer());
		
		double dou = raf.readDouble();
		System.out.println(dou);//123.123
		System.out.println("pos:"+raf.getFilePointer());

		raf.close();
	}}


/**
 * 完成用户注册功能
 * 
 * 程序开始后,要求用户输入:
 * 用户名,密码,昵称,年龄
 * 
 * 将该记录写入到user.dat文件中。
 * 其中用户名,密码,昵称为字符串。年龄为
 * 一个int值。
 * 
 * 每条记录占用100字节,其中:用户名,密码,
 * 昵称为字符串,各占32字节,年龄为int占用
 * 4字节。
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		System.out.println("欢迎注册");
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("请输入用户名:");
		String username = scanner.nextLine();
		
		System.out.println("请输入密码:");
		String password = scanner.nextLine();
		
		System.out.println("请输入昵称:");
		String nickname = scanner.nextLine();
		
		System.out.println("请输入年龄:");
		int age = Integer.parseInt(scanner.nextLine());//字符串转为整型
		
		System.out.println(username+","+password+","+nickname+","+age);
		
		RandomAccessFile raf
			= new RandomAccessFile("user.dat","rw");
	//现将指针移动到文件末尾
		raf.seek(raf.length());
		
		
		//写用户名
		//1先将用户名转成对应的一组字节
		byte[] data = username.getBytes("UTF-8");
		//2将该数组扩容为32字节
		data = Arrays.copyOf(data, 32);
		//3将该字节数组一次性写入文件
		raf.write(data);
		
		//写密码
		data = password.getBytes("UTF-8");
		data = Arrays.copyOf(data, 32);
		raf.write(data);
		
		//写昵称
		data = nickname.getBytes("UTF-8");
		data = Arrays.copyOf(data, 32);
		raf.write(data);
		
		//写年龄
		raf.writeInt(age);
		
		System.out.println("注册完毕!");
		raf.close();
	}}

/**
 * 修改昵称
 * 
 * 程序启动后,要求用户输入要修改昵称的用户名
 * 以及新的昵称。然后将该用户昵称进行修改操作
 * 若输入的用户名不存在,则提示"无此用户"。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		/*
		 * 1:获取用户输入的用户名及新昵称
		 * 2:使用RAF打开user.dat文件
		 * 3:循环读取每条记录
		 *   3.1:将指针移动到该条记录用户名
		 *       的位置(i*100)
		 *   3.2:读取32字节,将用户名读取出来
		 *   3.3:判断该用户是否为用户输入的用户
		 *   3.4:若是此人,则移动指针到该条
		 *       记录昵称位置,将新昵称以32字节        
		 *       写入该位置,覆盖原昵称完成修改
		 *       并停止循环操作。
		 *   3.5:若不是此人则进入下次循环    
		 * 
		 * 可以添加一个开关,当修改过昵称后,改变
		 * 其值,最终在循环完毕后,根据开关的值判定
		 * 是否有修改信息来输出"无此用户"
		 * 
		 */
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入用户名:");
		String username = scanner.nextLine();
		
		System.out.println("请输入新的昵称:");
		String nickname = scanner.nextLine();
		
		RandomAccessFile raf
			= new RandomAccessFile("user.dat","rw");
		//开关,表示是否有修改过信息
		boolean update = false;
		for(int i=0;i<raf.length()/100;i++) {
			//先将指针移动到该条记录的开始位置
			raf.seek(i*100);
			//读取用户名
			byte[] data = new byte[32];
			raf.read(data);
			String name = new String(data,"UTF-8").trim();
			if(name.equals(username)) {
				//修改昵称
				//1先移动指针到昵称的位置
				raf.seek(i*100+64);
				//2重新写昵称32字节
				data = nickname.getBytes("UTF-8");
				data = Arrays.copyOf(data, 32);
				raf.write(data);
				System.out.println("修改完毕!");
				update = true;
				break;
			}
		}
		if(!update) {
			System.out.println("无此用户!");
		}
		raf.close();
	}}
         /**
 * 显示所有注册用户信息
           *  @author Mr.Cui
           */
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf
			= new RandomAccessFile("user.dat","r");
		/*
		 * 循环读取若干个100字节
		 */
		for(int i=0;i<raf.length()/100;i++) {		
			//读用户名
			//1先读取32字节
			byte[] data = new byte[32];
			raf.read(data);
			//2将字节数组转换为字符串
			String username = new String(data,"UTF-8").trim();
			
			//读取密码
			raf.read(data);
			String password = new String(data,"UTF-8").trim();
			
			//读昵称
			raf.read(data);
			String nickname = new String(data,"UTF-8").trim();
			
			//读年龄
			int age = raf.readInt();
			System.out.println(username+","+password+","+nickname+","+age);
			
		}
		
		raf.close();
	}}


/**
 * java IO(input,output) 输入与输出
 * IO是我们的程序与外界交换数据的方式。
 * java提供了一种统一的标准的方式与外界交换
 * 数据。
 * 
 * java将流按照功能划分为读和写,并用不同的方
 * 向来表示
 * 其中输入流(外界到程序的方向)用于读取数据
 * 输出流用于写出数据。
 * 
 * java将流划分为两大类:节点流,处理流
 * 节点流:也称为低级流,是实际链接程序与数据源
 * 的"管道",负责实际搬运数据。读写一定是建立在
 * 节点流的基础上进行的。
 * 
 * 处理流:也称为高级流,不能独立存在,必须链接
 * 在其他流上,目的是当数据流经当前流时对这些
 * 数据做某些处理,这样可以简化我们对数据的
 * 操作。 
 * 
 * 实际应用中,我们是链接若干高级流,并最终链接
 * 低级流,通过低级流读写数据,通过高级流对读写
 * 的数据进行某些加工处理,完成一个复杂的读写
 * 操作。这个过程称为"流链接"。这也是学习IO的
 * 精髓所在。
 * 
 * 文件流
 * 文件流是一对低级流,用于读写文件。就功能而言
 * 它们与RandomAccessFile一致。但是底层的读写
 * 方式有本质区别。
 * RAF是基于指针进行随机读写的,可任意读写文件指定
 * 位置的数据。可以做到对文件部分数据的编辑操作。
 * 
 * 流是顺序读写方式,所以不能做到任意读写指定
 * 位置数据,对此也无法做到对文件数据进行编辑的
 * 操作。但是配合高级流,可以更轻松的读写数据。
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		/*
		 * 使用文件流向文件中写出字节
		 * 
		 * FileOutputStream常用构造方法:
		 * FileOutputStream(String path)
		 * FileOutputStream(File file)
	 * 以上两种方式创建时,默认为覆盖写操
	 * 作,即:若创建时发现该文件已存在,会
	 * 先将该文件所有数据清除。然后将通过
	 * 当前流写出的内容作为该文件数据。
		 *
		 * 
		 * FileOutputStream(String path,boolean append)
		 * FileOutputStream(File file,boolean append)
	 * 追加写模式,即:若指定的文件存在,那么数据全
	 * 保留,通过该流写出的数据会被追加到文件最后
		 * 
		 */
		FileOutputStream fos
			= new FileOutputStream("fos.txt",true);
		
		String line = "我们一起学猫叫,一起喵喵喵喵喵~";
		byte[] data = line.getBytes("UTF-8");
		fos.write(data);
		System.out.println("写出完毕!");
		fos.close();
				
	}}

/**
 * 使用文件输入流读取文件数据
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileInputStream fis
			= new FileInputStream("fos.txt");
		
		byte[] data = new byte[200];
		int len = fis.read(data);
		System.out.println("实际读取了:"+len+"个字节");
		
		String str = new String(data,0,len,"UTF-8");
		System.out.println(str);
		
		fis.close();
	}}

/**
 * 使用文件流完成复制文件操作
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		/*
	 * 使用文件输入流读取原文件
	 * 使用文件输出流向复制文件写数据
		 * 
	 * 利用块读写操作顺序从原文件将数据
	 * 读取出来写入复制文件完成复制操作。
		 */
		FileInputStream src
			= new FileInputStream("music.mp3");
		FileOutputStream desc
			= new FileOutputStream("music_cp.mp3");		
		int len = -1;
		byte[] data = new byte[1024*10];		
		while((len = src.read(data))!=-1) {
			desc.write(data,0,len);
		}
		System.out.println("复制完毕!");
		src.close();
		desc.close();
	}}

/**
 * 缓冲流BufferedInputStream
 * 缓冲流是一对高级流,功能是提高读写效率。
 * 链接他们以后,无论我们进行随机读写还是
 * 块读写,当经过缓冲流时都会被转换为块读写
 * 操作。
 * java.io.BufferedInputStream
 * java.io.BufferedOutputStream
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileInputStream fis
			= new FileInputStream("music.mp3");
		BufferedInputStream bis
			= new BufferedInputStream(fis);
		FileOutputStream fos
			= new FileOutputStream("music_cp.mp3");
		BufferedOutputStream bos
			= new BufferedOutputStream(fos);		
		int d = -1;
		long start = System.currentTimeMillis();
		while((d = bis.read())!=-1) {
			bos.write(d);
		}
		long end = System.currentTimeMillis();
		
		System.out.println("复制完毕,耗时:"+(end-start)+"ms");		
		bis.close();
		bos.close();
	}}

/**
 * 缓冲输出流的缓冲区问题
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileOutputStream fos
			= new FileOutputStream("bos.txt");
		BufferedOutputStream bos
			= new BufferedOutputStream(fos);
		
		String line = "你是隔壁的泰山,抓住爱情的藤蔓。";
		byte[] data = line.getBytes("UTF-8");
		/*
	 * 缓冲流的write方法并不是立即将数据写出,
	 * 而是先将数据存入其内部的数组中,当数组
	 * 装满时才会做一次真是写操作。(转化为块
	 * 写操作的过程)
		 */
		bos.write(data);
		/*
	 * flush方法的意义是强制将缓冲流已经缓存的
	 * 数据一次性写出。这样做可以让写出的数据
	 * 有即时性,但是频繁调用会降低写效率。
	 * 在更关注写出的即时性时应当使用该方法。
		 */
                             //bos.flush();
		System.out.println("写出完毕!");
		/*
		 * close方法中会调用一次flush方法
		 */
		bos.close();
	}}

/**
 * 对象流
 * 对象流也是一对高级流,提供的功能是读写java
 * 中的任何对象。
 * 
 * 对象输出流:
 * java.io.ObjectOutputStream
 * 它可以将给定的java对象转换为一组字节然后
 * 通过其连接的流将这些字节写出。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		Person p = new Person();
		p.setName("苍老师");
		p.setAge(18);
		p.setGender("女");
		String[] otherInfo = {"是一名演员","爱好是写毛笔字","已婚","促进中日文化交流","广大男性同胞的启蒙老师"};
		p.setOtherInfo(otherInfo);
		System.out.println(p);
		
		FileOutputStream fos
			= new FileOutputStream("person.obj");
		
		ObjectOutputStream oos
			= new ObjectOutputStream(fos);
		/*
	 * 通过对象流写出对象的这个方法经历了
	 * 两个步骤:
	 * 1:对象流先将给定的对象转换为了一组
	 *   字节,这组字节包含对象本身保存的
	 *   数据信息,还包含该对象的结构信息
	 *   然后将这组字节通过其连接的流写出
		 *   
	 *   上述操作对应的术语:对象序列化
		 *   
		 *   
	 * 2:经过文件流时,文件流将这组字节写
	 *   入到了文件中
		 *   
		 *   将数据写入磁盘做长久保存的过程
		 *   对应的术语:数据持久化
		 * 
		 * 
		 */
		oos.writeObject(p);
		System.out.println("写出完毕!");
		
		oos.close();
	}}

/**
 * 对象输入流
 * 可以进行对象的反序列化操作。
 * 
 * 使用对象流读取的字节必须是通过对象输出流
 * 序列化的一组字节才可以。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException,              ClassNotFoundException {
		FileInputStream fis
			= new FileInputStream("person.obj");
		ObjectInputStream ois
			= new ObjectInputStream(fis);
		
		Person p = (Person)ois.readObject();
		System.out.println(p);
		
		ois.close();
		
	}}

/**
 * 使用当前类实例测试对象流的对象读写操作
 * 
 * 当一个类的实例希望可以被对象流进行读写,那
 * 么该类必须实现:java.io.Serializable接口
 * 与此同时,当前类中所有引用类型的属性,他们
 * 对应的类也必须实现该接口。
 * @author Mr.Cui
 */
public class Person implements Serializable{
	/**
        * 当一个类实现了Serializable接口后,要求
         * 应当定义一个常量:serialVersionUID,即:
         * 序列化版本号
	 * 
	 * 序列化版本号影响反序列化是否成功。当对象
	 * 输入流在进行对象反序列化时会检查该对象与
	 * 当前类的版本是否一致,不一致则反序列化时
	 * 会抛出异常导致反序列化失败。
	 * 一致则可以进行反序列化,原则时对应的属性
	 * 进行还原。
	 * 
	 * 如果我们不定义该版本号,编译器会在编译当前
	 * 类时根据结构生成一个版本号,但是一旦当前类
	 * 发生改变,那么版本号一定会改变。这样以前的
	 * 对象一定是不可以反序列化了。
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private String gender;
	/*
 * transient关键字修饰的属性在对象序列化时
	 * 会被忽略。
	 * 忽略不必要的属性可以达到对象瘦身的作用。
	 * 
	 */
	private transient String[] otherInfo;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String[] getOtherInfo() {
		return otherInfo;
	}
	public void setOtherInfo(String[] otherInfo) {
		this.otherInfo = otherInfo;
	}
	
	public String toString() {
		return name+","+age+","+gender+","+
	           Arrays.toString(otherInfo);
	}}


/**
 * 字符流
 * java将流按照读写单位又进行了一种划分方式
 * 字节流与字符流
 * 字节流的读写单位是字节,而字符流的读写单位
 * 是字符
 * 所以字符流只适合读写文本数据!
 * 
 * java.io.Reader,java.io.Writer
 * 这两个类也是抽象类,是所有字符输入流与
 * 字符输出流的父类,规定了读写字符的相关
 * 方法。
 * 
 * 转换流
 * java.io.InputStreamReader
 * java.io.OutputStreamWriter
 * 他们是一对常用的字符流实现类,经常在我们做
 * 字符数据读写操作中使用。并且在流链接中是
 * 非常重要的一个环节。但是我们很少直接对它
 * 做操作。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileOutputStream fos
			= new FileOutputStream("osw.txt");
		
		OutputStreamWriter osw
			= new OutputStreamWriter(fos,"UTF-8");	
		String line = "摩擦摩擦,在光滑的马路牙子上打出溜滑!";
		osw.write(line);		
		line = "我的滑板鞋,时尚时尚最时尚!";
		osw.write(line);
		System.out.println("写出完毕!");
		
		osw.close();
	}}

/**
 * 字符流
 * java将流按照读写单位又进行了一种划分方式
 * 字节流与字符流
 * 字节流的读写单位是字节,而字符流的读写单位
 * 是字符
 * 所以字符流只适合读写文本数据!
 * 
 * java.io.Reader,java.io.Writer
 * 这两个类也是抽象类,是所有字符输入流与
 * 字符输出流的父类,规定了读写字符的相关
 * 方法。
 * 
 * 转换流
 * java.io.InputStreamReader
 * java.io.OutputStreamWriter
 * 他们是一对常用的字符流实现类,经常在我们做
 * 字符数据读写操作中使用。并且在流链接中是
 * 非常重要的一个环节。但是我们很少直接对它
 * 做操作。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileOutputStream fos
			= new FileOutputStream("osw.txt");
		
		OutputStreamWriter osw
			= new OutputStreamWriter(fos,"UTF-8");	
		String line = "摩擦摩擦,在光滑的马路牙子上打出溜滑!";
		osw.write(line);		
		line = "我的滑板鞋,时尚时尚最时尚!";
		osw.write(line);
		System.out.println("写出完毕!");
		
		osw.close();
	}}


/**
 * 转换流
 * java.io.InputStreamReader
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileInputStream fis
			= new FileInputStream("osw.txt");
		
		InputStreamReader isr
			= new InputStreamReader(fis,"UTF-8");
		/*
	 * 字符流的方法:
	 * int read()
	 * 该方法是一次读取一个字符,实际读取
	 * 的字节量要根据指定的字符集决定。但
	 * 是当读取到该字符后在java中都是以一
	 * 个char形式保存(unicode)占2个字节。
		 */
		//int d = -1;
		//while((d = isr.read())!=-1) {
		//char c = (char)d;
		//System.out.print(c);
		//}
		
		char[] data = new char[100];
		int len = isr.read(data);
		String str = new String(data,0,len);
		System.out.println(str);
		isr.close();
	}}

/**
 * java.io.PrintWriter
 * 具有自动行刷新的缓冲字符输出流
 * 开发中比较常用的字符高级流
 * 
 * 可以按行写出字符串。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		/*
	 * PW提供了专门针对写文件的构造方法
		 * PrintWriter(String path)
		 * PrintWriter(File file)
		 */
		PrintWriter pw 
			= new PrintWriter("pw.txt","UTF-8");
		
		pw.println("像一颗海草海草海草海草~");
		pw.println("随波飘摇~");
		
		System.out.println("写出完毕!");
		pw.close();
		
	}}


/**
 * 在流链接中使用PW
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileOutputStream fos
			= new FileOutputStream("pw.txt");
		OutputStreamWriter osw
			= new OutputStreamWriter(fos,"UTF-8");
		BufferedWriter bw
			= new BufferedWriter(osw);
		PrintWriter pw
			= new PrintWriter(bw);
		
		pw.println("你好!");
		System.out.println("写出完毕!");
		
		pw.close();
	}}


/**
 * 完成简易记事本工具
 * 
 * 程序启动后,要求用户输入文件名,然后对该
 * 文件进行写操作。
 * 之后用户输入的每一行字符串都按行写入到该
 * 文件中。
 * 创建PW时要求使用流链接模式。
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("请输入文件名:");
		String fileName = scanner.nextLine();
		
		FileOutputStream fos
			= new FileOutputStream(fileName);
		OutputStreamWriter osw
			= new OutputStreamWriter(fos,"UTF-8");
		BufferedWriter bw
			= new BufferedWriter(osw);
		/*
	 * 当在流链接当中创建PrintWriter时
	 * 允许指定第二个参数,该参数为一个
	 * boolean值,当这个值为true时,当前
	 * PW具有自动行刷新功能。
	 * 即:每当调用println方法写出一行字符串
	 * 时就会自动flush.
	 * 注意:print方法是不会自动flush的
		 */
		PrintWriter pw
			= new PrintWriter(bw,true);
		System.out.println("请开始输入内容:");
	//用来记录每次用户输入的字符串
		String line = null;
		while(true) {
			line = scanner.nextLine();
			if("exit".equals(line)) {
				break;
			}
			pw.println(line);
		            //pw.flush();
		}
		System.out.println("再见!");
		pw.close();
	}}

/**
 * 缓冲字符输入流:
 * java.io.BufferedReader
 * 特点:可以按行读取字符串
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		/*
	 * 将当前源代码输出到控制台
		 */
		FileInputStream fis
			= new FileInputStream(
				"src/io/BrDemo.java"
			);
		InputStreamReader isr
			= new InputStreamReader(fis);
		
		BufferedReader br
			= new BufferedReader(isr);
		/*
		 * String readLine()
	 * 读取一行字符串
	* 顺序读取若干字符,当读取到了换行
	 * 符时停止,并将换行符之前的字符组
	 * 成一个字符串返回。返回的字符串中
	 * 是不含有最有的换行符的。
	 * 若返回值为null,说明流读取到了
	 * 末尾。
		 */
		String line = null;
		while((line = br.readLine())!=null) {
			System.out.println(line);
		}
		
		br.close();	
	}}

/**
 * 使用文件输入流读取文件数据
 * @author Mr.Cui
 */
	public static void main(String[] args) throws IOException {
		FileInputStream fis
			= new FileInputStream("fos.txt");
		
		byte[] data = new byte[200];
		int len = fis.read(data);
		System.out.println("实际读取了:"+len+"个字节");
		
		String str = new String(data,0,len,"UTF-8");
		System.out.println(str);
		
		fis.close();
	}}

/**
 * java异常处理机制中的try-catch
 * try语句块用来包含可能出错的代码片段,catch
 * 用来捕获这些错误并针对该错误进行处理。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println("程序开始了");
		try {
			String str = "a";
			System.out.println(str.length());
			System.out.println(str.charAt(0));
			System.out.println(Integer.parseInt(str));
		//try语句块中出错代码以下内容不执行
			System.out.println("!!!!!");
			
		}catch(NullPointerException e) {
			System.out.println("出现了空指针");
		}catch(StringIndexOutOfBoundsException e) {
			System.out.println("字符串下标越界了!");
		/*
	 * 应当在最后一个catch处捕获Exception
	 * 尽量避免一个未捕获异常导致程序中断
		 */
		}catch(Exception e) {
			System.out.println("反正就是出了个错!");
		}
		System.out.println("程序结束了");
	}}


/**
 * finally块
 * finally是异常处理机制的最后一块,可以直接
 * 跟在try之后或者最后一个catch之后。
 * finally可以确保只要程序运行到try语句块中
 * 那么无论是否抛出异常,finally中的代码必定
 * 执行。
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println("程序开始了");
		try {
			String str = null;
			System.out.println(str.length());
			return;
		} catch (Exception e) {
			System.out.println("出错了");
		} finally {
			System.out.println("finally!!!");
		}	
		System.out.println("程序结束了");
	}}
/**
 * 在IO操作中使用异常处理机制
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		FileOutputStream fos = null;
		try {			
			fos	= new FileOutputStream("fos.dat");
			fos.write(1);			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(fos!=null) {
					fos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}}}

/**
 * JDK7之后推出了一个新特性:autoclose
 * 允许编译器在编译过程中自动处理诸如流的关闭
 * 工作。
 * @author Mr.Cui
 */
	public static void main(String[] args) {		
		try(
			/*
		 * 实现了AutoCloseable接口的类可以在
		 * 这里定义。编译器最终会将代码改变,
		 * 在finally中将其关闭
			 */
			FileOutputStream fos
				= new FileOutputStream("fos.dat");	
		){
			fos.write(1);
		} catch (IOException e) {
			e.printStackTrace();
		}
		}}


/**
 * 请分别说明:
 * final finally finalize?
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println(
			test("0")+","+test(null)+","+test("")
		);	//3,3,3	
	}
	public static int test(String str) {
		try {
			System.out.println("str:"+str);
			return str.charAt(0)-'0';
		} catch( NullPointerException e) {
			System.out.println("空指针!");
			return 1;
		} catch (Exception e) {
			System.out.println("其他异常!");
			return 2;
		} finally {
			return 3;
		}}}

/**
 * 测试异常的抛出
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println("程序开始了");
		Person p = new Person();
		/*
	 * 满足语法,但是不满足业务逻辑要求
	 * 这时setAge方法中可以当做异常抛出
	 * 要求这里调用时处理
		 */
		try {
			/*
	 * 当调用一个含有throws声明异常抛出
	 * 的方法时,要求必须处理该异常
	 * 而处理方式有两种:
	 * 1:使用try-catch捕获并解决异常
	 * 2:在当前方法上继续使用throws声明
	 *   该异常的抛出 
			 */
			p.setAge(10);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(p.getAge());
		System.out.println("程序结束了");
	}}

/**
 * 使用当前类测试异常的抛出
 * @author Mr.Cui
 */
	private int age;

	public int getAge() {
		return age;
	}
	/**
	 * 通常一个方法中使用throw抛出一个异常时
	 * 就要在方法声明时使用throws声明该异常的
	 * 抛出以通知调用者解决该异常。
	 * 只有抛出RuntimeException及其子类型异常
	 * 时可以不要求这样做。
	 * @param age
	 * @throws Exception
	 */
	public void setAge(int age)throws Exception {
		if(age<0||age>100) {
			throw new Exception("年龄不合法!");
		}
		this.age = age;
	}}

/**
 * 重写超类含有throws声明异常抛出的方法时
 * 对throws的重写规则
 * @author ta
 *
 */
	public void dosome()
			throws IOException,AWTException {
		
	}}

	class Son extends ThrowsDemo{
	//public void dosome()
	//throws IOException,AWTException {		
	//}
	
	//允许仅抛出部分异常
	//public void dosome()
	//throws IOException{		
	//}
	
	//允许不再抛出任何异常
	//public void dosome(){		
	//}
	
	//允许抛出超类方法抛出异常的子类型异常
	//public void dosome()
	//throws FileNotFoundException {		
	//}
	
	//不允许抛出额外异常
	//public void dosome()
	//throws SQLException {		
	//}
	
	//不允许抛出超类方法抛出异常的父类型异常
	//public void dosome()
	//throws Exception{		
	//}}


package exception;
/**
 * 异常常用方法
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println("程序开始了");
		
		try {
			String str = "A";			
			System.out.println(Integer.parseInt(str));
		} catch (Exception e) {
		//输出错误信息,最常用
			//e.printStackTrace();
		//获取错误消息
			String message = e.getMessage();
			System.out.println(message);
		}		
		System.out.println("程序结束了");
	}}

/**
 * 年龄不合法异常
 * 
 * 自定义异常,通常是用来说明当前项目的某个
 * 业务逻辑错误。
 * @author Mr.Cui
 */
	private static final long serialVersionUID = 1L;

	public IllegalAgeException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

	public IllegalAgeException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public IllegalAgeException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public IllegalAgeException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}		}


/**
 * 使用当前类测试异常的抛出
 * @author Mr.Cui
 */
	private int age;

	public int getAge() {
		return age;
	}
	/**
	 * 通常一个方法中使用throw抛出一个异常时
	 * 就要在方法声明时使用throws声明该异常的
	 * 抛出以通知调用者解决该异常。
	 * 只有抛出RuntimeException及其子类型异常
	 * 时可以不要求这样做。
	 * @param age
	 * @throws Exception
	 */
	public void setAge(int age)throws IllegalAgeException {
		if(age<0||age>100) {
			throw new IllegalAgeException("年龄不合法!");
		}
		this.age = age;
	}		}


/**
 * 测试异常的抛出
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println("程序开始了");
		Person p = new Person();
		/*
	 * 满足语法,但是不满足业务逻辑要求
	 * 这时setAge方法中可以当做异常抛出
	 * 要求这里调用时处理
		 */
		try {
			/*
		 * 当调用一个含有throws声明异常抛出
		 * 的方法时,要求必须处理该异常
		 * 而处理方式有两种:
		 * 1:使用try-catch捕获并解决异常
		 * 2:在当前方法上继续使用throws声明
		 *   该异常的抛出 
			 */
			p.setAge(10);
		} catch (IllegalAgeException e) {
			e.printStackTrace();
		}
		System.out.println(p.getAge());
		System.out.println("程序结束了");
	}}


/**
 * 线程是并发运行代码的。
 * 有两种创建线程的方式:
 * 方式一,继承Thread并重写run方法。run方法中
 * 就是希望线程执行的逻辑。
 * @author ta
 *
 */
public class ThreadDemo1 {
	public static void main(String[] args) {
		Thread t1 = new MyThread1();
		Thread t2 = new MyThread2();
		/*
		 * 启动线程要调用start方法,而不是
		 * 直接调用run方法。当start方法调用
		 * 完毕后,run方法很快会被线程自行调
		 * 用。
		 */
		t1.start();
		t2.start();
	}
}
/**
 * 第一种创建线程的方式比较简单直接,但是缺点
 * 主要有两个:
 * 1:由于需要继承线程,这导致不能再继承其他类
 *   实际开发中经常要复用某个超类的功能,那么
 *   在继承线程后不能再继承其他类会有很多不便
 * 
 * 2:定义线程类的同时重写了run方法,这会导致
 *   线程与线程要执行的任务有一个必然的耦合
 *   关系,不利于线程的重用。
 * @author Mr.Cui
 */
	public void run() {
		for(int i=0;i<1000;i++) {
			System.out.println("你是谁啊?");
		}
	}}
class MyThread2 extends Thread{
	public void run() {
		for(int i=0;i<1000;i++) {
			System.out.println("我是查水表的!");
		}
	}}

/**
 * 第二种创建线程的方式
 * 实现Runnable接口,单独定义线程任务
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		//实例化两个任务
		Runnable r1 = new MyRunnable1();
		Runnable r2 = new MyRunnable2();
		//创建两个线程并指派任务
		Thread t1 = new Thread(r1);
		Thread t2 = new Thread(r2);
		
		t1.start();
		t2.start();
	}}

class MyRunnable1 implements Runnable{
	public void run() {
		for(int i=0;i<1000;i++) {
			System.out.println("你是谁啊?");
		}		
	}}
class MyRunnable2 implements Runnable{
	public void run() {
		for(int i=0;i<1000;i++) {
			System.out.println("我是查水表的!");
		}		
	}}


/**
 * 线程提供了获取相关信息的方法
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		/*
		 * 线程提供了一个静态方法:
		 * static Thread currentThread()
		 * 该方法用来获取运行这个方法的线程
		 * main方法也是靠一个线程运行的,当JVM启动
		 * 后会自动创建一个线程来执行main方法。而
		 * 这个线程的名字叫做"main",我们称它为主线程
		 * 
		 * 获取运行main方法的线程
		 * 
		 */
		Thread main = Thread.currentThread();
		System.out.println("运行main方法的线程:"+main);
		
		dosome();
		
		Thread t = new Thread() {
			public void run() {
				Thread t = Thread.currentThread();
				System.out.println("自定义线程:"+t);
				dosome();
			}		
                             };
		t.start();		
	}		
	public static void dosome() {
		Thread t = Thread.currentThread();
		System.out.println("运行dosome方法的线程是:"+t);
	}}


/**
 * 线程提供了获去自身信息的相关方法
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Thread main = Thread.currentThread();
		//获去线程的名字
		String name = main.getName();
		System.out.println("name:"+name);
		//获去线程的唯一标识(id)
		long id = main.getId();
		System.out.println("id:"+id);
		//获去线程的优先级
		int priority = main.getPriority();
		System.out.println("优先级:"+priority);
		//线程是否还处于活动状态
		boolean isAlive = main.isAlive();
		System.out.println("isAlive:"+isAlive);
		//线程是否是被中断了
		boolean isInterrupted = main.isInterrupted();
		System.out.println("isInterrupted:"+isInterrupted);
		//线程是否为守护线程
		boolean isDaemon = main.isDaemon();
		System.out.println("isDaemon:"+isDaemon);
				
	}}


/**
 * 线程的优先级
 * 线程不能主动获去CPU时间片,只能被动的被
 * 线程调度器分配。
 * 调整线程的优先级可以最大程度的改善某个线程
 * 获去CPU时间片的次数。
 * 理论上线程优先级约高的线程获去CPU时间片的
 * 次数就越多。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Thread max = new Thread() {
			public void run() {
				for(int i=0;i<10000;i++) {
					System.out.println("max");
				}
			}
		};
		Thread min = new Thread() {
			public void run() {
				for(int i=0;i<10000;i++) {
					System.out.println("min");
				}
			}
		};
		Thread norm = new Thread() {
			public void run() {
				for(int i=0;i<10000;i++) {
					System.out.println("nor");
				}
			}
		};
		
		max.setPriority(Thread.MAX_PRIORITY);
		min.setPriority(Thread.MIN_PRIORITY);		
		min.start();
		norm.start();
		max.start();		
	}}


/**
 * 线程提供了一个静态方法:
 * static void sleep(long ms)
 * 使运行这个方法的线程阻塞指定毫秒。超时后
 * 该线程会自动回到RUNNABLE状态,等待再次并发
 * 运行。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		System.out.println("程序开始了");
		while(true) {
			System.out.println("你好!");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}}}


/**
 * 倒计时程序
 * 程序启动后,要求输入一个数字,比如:100
 * 然后每秒输出一次,每次输出数字递减。
 * 输出到0时提示结束,程序退出。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入一个数字:");
		String line = scanner.nextLine();		
		Integer num = Integer.parseInt(line);
		for(;num>0;num--) {
			System.out.println(num);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("结束!");
	}}


/**
 * sleep方法要求必须处理中断异常,原因在于当
 * 一个线程调用了sleep方法处于阻塞状态的过程
 * 中若被调用了它的interrupt()方法中断时,它
 * 就会在sleep方法中抛出中断异常。这时并非是
 * 将这个线程直接中断,而是中断了它的阻塞状态
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		/*
		 * JDK8之前,由于JVM内存分配问题,有一个
		 * 要求:
		 * 当一个方法的局部变量被这个方法的其他
		 * 局部内部类所引用是,这个变量声明必须
		 * 是final的。
		 */
		final Thread lin = new Thread() {
			public void run() {
				System.out.println("林:刚美完容,睡一会吧!");
				try {
					Thread.sleep(1000000);
				} catch (InterruptedException e) {
					System.out.println("林:干嘛呢!干嘛呢!干嘛呢!都破了相了!");
				}
				System.out.println("林:醒了!");
			}
		};
		
		Thread huang = new Thread() {
			public void run() {
				System.out.println("黄:开始砸墙!");
				for(int i=0;i<5;i++) {
					System.out.println("黄:80!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("咣当!");
				System.out.println("黄:搞定!");
				//中断lin线程
				lin.interrupt();
			}
		};		
		lin.start();
		huang.start();
								
	}}


/**
 * 守护线程
 * 守护线程又称为后台线程,默认创建的线程都
 * 是普通线程或称为前台线程,线程提供了一个
 * 方法:
 * void setDaemon(boolean on)
 * 只有调用该方法并传入参数true时,该线程才
 * 会被设置为守护线程。
 * 
 * 
 * 守护线程在使用上与普通线程没有差别,但是在
 * 结束时机上有一个区别,即:线程结束时所有正在
 * 运行的守护线程都会被强制停止。
 * 
 * 线程的结束:当一个进程中所有的普通线程都结束
 * 时,进程即结束。
 * 
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		Thread rose = new Thread() {
			public void run() {
				for(int i=0;i<5;i++) {
					System.out.println("rose:let me go!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("rose:啊啊啊啊啊AAAAAAAaaaaaa.....");
				System.out.println("噗通!");
			}
		};
		
		Thread jack = new Thread() {
			public void run() {
				while(true) {
					System.out.println("jack:you jump!i jump!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}
			}
		};	
		rose.start();	
		/*
		 * 设置为守护线程
		 * 注意,必须在线程启动前进行设置
		 */
		jack.setDaemon(true);
		jack.start();
		
	}}


/**
 * 线程提供了一个方法:
 * void join()
 * 该方法可以协调线程之间的同步运行
 * 
 * 同步与异步:
 * 同步运行:运行有顺序
 * 异步运行:运行代码无顺序,多线程并发运行就
 *          是异步运行
 * @author Mr.Cui
 *
 */
	//标识图片是否下载完毕
	private static boolean isFinish = false;
	
	public static void main(String[] args) {
		
		Thread download = new Thread() {
			public void run() {
				System.out.println("down:开始下载图片...");
				for(int i=1;i<=100;i++) {
					System.out.println("down:"+i+"%");
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("down:下载图片完毕!");
				isFinish = true;
			}
		};
		
		Thread show = new Thread() {
			public void run() {
				System.out.println("show:开始显示图片");
				//加载图片前应先等待下载线程将图片下载完毕	
				try {
					/*
					 * show线程在调用download.join()方法后
					 * 就进入了阻塞状态,直到download线程
					 * 的run方法执行完毕才会解除阻塞
					 */
					download.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				
				if(!isFinish) {
					throw new RuntimeException("加载图片失败!");
				}
				System.out.println("show:显示图片完毕!");
			}
		};
		download.start();
		show.start();
		
		
	}}

/**
 * 同步块
 * 语法:
 * synchronized(同步监视器对象){
 *    需要同步运行的代码片段
 * }
 * 
 * 同步块可以更精确的控制需要同步运行的代码
 * 片段。有效的缩小同步范围可以在保证并发安全
 * 的前提下提高代码并发运行的效率
 * 使用同步块控制多线程同步运行必须要求这些
 * 线程看到的同步监视器对象为[同一个]。
 * 
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		Shop shop = new Shop();
		Thread t1 = new Thread() {
			public void run() {
				shop.buy();
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				shop.buy();
			}
		};
		t1.start();
		t2.start();
	}
}

class Shop{
//	public synchronized void buy() {
	public void buy() {
		try {
			Thread t = Thread.currentThread();
			System.out.println(t.getName()+":正在挑衣服...");
			Thread.sleep(5000);
			synchronized (this) {
				System.out.println(t.getName()+":正在试衣服...");
				Thread.sleep(5000);
			}
			
			System.out.println(t.getName()+":结账离开");
		} catch (Exception e) {
			
		}
	}}


/**
 * 多线程并发的安全问题。
 * 产生:当多个线程并发操作同一资源时,由于线程
 * 切换实际的不确定性,会导致执行操作资源的代码
 * 顺序未按照设计顺序执行,出现操作混乱的情况。
 * 严重时可能导致系统瘫痪。
 * 
 * 解决:将并发操作同一资源改为同步操作,即:有
 *      先后顺序的操作。
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		Table table = new Table();
		Thread t1 = new Thread() {
			public void run() {
				while(true) {
					int bean = table.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);
				}
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				while(true) {
					int bean = table.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);
				}
			}
		};
		t1.start();
		t2.start();
	}
}

class Table{
	//20个豆子
	private int beans = 20;	
	/**
	 * 当一个方法被synchronized修饰后,该方法
	 * 称为"同步方法",即:多个线程不能同时在方
	 * 法内部运行。强制让多个线程在执行同一个
	 * 方法时变为同步操作就解决了并发安全问题
	 * 
	 * 在方法上使用synchronized,那么同步监视器
	 * 对象就是当前方法所属对象,即:方法内部看到
	 * 的this
	 * @return
	 */
	public synchronized int getBean() {
		if(beans==0) {
			throw new RuntimeException("没有豆子了!");
		}
		//模拟线程执行到这里没有时间了
		Thread.yield();
		return beans--;
	}	
}


/**
 * 静态方法若使用synchroinzed修饰,那么该方法
 * 一定具有同步效果
 * 静态方法对应的同步监视器对象为当前类的
 * 类对象(Class的实例)。类对象会在后面反射
 * 的课程中讲到。
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Thread t1 = new Thread() {
			public void run() {
				Foo.dosome();
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				Foo.dosome();
			}
		};
		t1.start();
		t2.start();
	}
}

class Foo{
	public synchronized static void dosome() {
		Thread t = Thread.currentThread();
		System.out.println(t.getName()+":正在运行dosome方法");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(t.getName()+":运行dosome方法完毕");
	}}


/**
 * 互斥锁
 * 当多个代码片段被synchronized块修饰后,这些
 * 同步块的同步监听器对象又是同一个时,这些
 * 代码片段就是互斥的。多个线程不能同时在这些
 * 方法中运行。
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		Boo boo = new Boo();
		Thread t1 = new Thread() {
			public void run() {
				boo.methodA();
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				boo.methodB();
			}
		};
		t1.start();
		t2.start();
	}
}

class Boo{
	public synchronized void methodA() {
		Thread t = Thread.currentThread();
		try {
			System.out.println(t.getName()+":正在运行A方法");
			Thread.sleep(5000);
			System.out.println(t.getName()+":运行A方法完毕");
		} catch (Exception e) {
		}
	}
	public void methodB() {
		synchronized (this) {
			Thread t = Thread.currentThread();
			try {
				System.out.println(t.getName()+":正在运行B方法");
				Thread.sleep(5000);
				System.out.println(t.getName()+":运行B方法完毕");
			} catch (Exception e) {
			}
		}}	}


/**
 * java.util.Collection
 * 集合
 * 集合与数组相似,可以保存一组元素,并且提供
 * 了操作集合元素的相关方法,使用便捷。
 * Collection接口下面有两个常见的子接口:
 * java.util.List:可重复集合,并且有序,可以
 * 通过下标操作元素。
 * 
 * java.util.Set:不可重复集合。
 * 元素是否重复是依靠元素自身equals比较进行
 * 判定的.
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		Collection c = new ArrayList();
		/*
		 * boolean add(E e)
		 * 向当前集合中添加给定元素,当该元素
		 * 成功添加则返回true。
		 */
		c.add("one");
		c.add("two");
		c.add("three");
		c.add("four");
		c.add("five");
		
		System.out.println(c);
		/*
		 * int size()
		 * 返回当前集合的元素个数
		 */
		int size = c.size();
		System.out.println("size:"+size);
		/*
		 * boolean isEmpty()
		 * 判断当前集合是否为空集(不含有任何
		 * 元素)
		 */
		boolean isEmpty = c.isEmpty();
		System.out.println("isEmpty:"+isEmpty);
		/*
		 * void clear()
		 * 清空当前集合
		 */
		c.clear();
		System.out.println("集合已清空");
		
		System.out.println(c);
		System.out.println("size:"+c.size());
		System.out.println("isEmpty:"+c.isEmpty());
	}}


/**
 * 集合提供了判断是否包含给定元素的方法:
 * boolean contains(E e)
 * 
 * @author Mr.Cui
 *
 */
public class ContainsDemo {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		c.add(new Point(1,2));
		c.add(new Point(3,4));
		c.add(new Point(5,6));
		c.add(new Point(7,8));
		c.add(new Point(9,0));
		/*
		 * 集合的toString方法会将每个元素
		 * 的toString体现出来。
		 */
		System.out.println(c);
		
		Point p = new Point(1,2);
//		c.add(p);
		/*
		 * contains方法是依靠元素自身equals比较
		 * 的结果判别集合是否包含该元素
		 */
		boolean contains = c.contains(p);
		System.out.println("包含:"+contains);
	}}


/**
 * 集合只能存放引用类型元素,并且存放的也是元
 * 素的引用(地址)
 * @author Mr.Cui
 *
 */
	public static void main(String[] args) {
		Collection c = new ArrayList();
		Point p = new Point(1,2);
		
		c.add(p);
		System.out.println("c:"+c);
		System.out.println("p:"+p);
		
		p.setX(2);
		System.out.println("c:"+c);//[(2,2)]
		System.out.println("p:"+p);//(2,2)
		
		
	}}


___________________________________________________________________{
public class Test {
	public static void main(String[] args) {
		int a = 1;
		String b = "hello";
		Point p = new Point(1,2);
		Collection c = new ArrayList();
		c.add(p);
		test(a, b, p, c);
		System.out.println("a:"+a);//?
		System.out.println("b:"+b);//?
		System.out.println("p:"+p);//?
		System.out.println("c:"+c);//?
	}
	
	public static void test(int a,String b,Point p,Collection c){
		a = 2;
		b = b+"world";
		p.setX(3);
		p = new Point(5,6);
		c.clear();
		c.add(p);
		p.setY(7);
		c = new ArrayList();
		c.add(p);
	}
}


/**
 * 使用当前类实例作为集合元素,测试集合相关
 * 操作。
 * @author Mr.Cui
 *
 */
public class Point {
	private int x;
	private int y;
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public String toString() {
		return "("+x+","+y+")";
	}
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj == this) {
			return true;
		}
		if(obj instanceof Point) {
			Point p = (Point)obj;
			return this.x==p.x&&this.y==p.y;
		}
		return false;
	}}


/**
 * 删除集合元素
 * @author Mr.Cui
 */
public class RemoveDemo {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		c.add(new Point(1,2));
		c.add(new Point(3,4));
		c.add(new Point(5,6));
		c.add(new Point(7,8));
		c.add(new Point(9,0));
		c.add(new Point(1,2));
		System.out.println(c);
		
		Point p = new Point(1,2);
		/*
		 * 删除元素也是依靠元素equals比较判定
		 */
		c.remove(p);
		System.out.println(c);
		
	}}


/**
 * 集合操作
 * @author Mr.Cui
 *
 */
public class CollectionDemo3 {
	public static void main(String[] args) {
		Collection c1 = new ArrayList();
		c1.add("java");
		c1.add("c");
		c1.add("c++");
		System.out.println("c1:"+c1);
		
		Collection c2 = new HashSet();
		c2.add("php");
		c2.add(".net");
		c2.add("java");
		System.out.println("c2:"+c2);
		/*
		 * boolean addAll(Collection c)
		 * 将给定集合中的所有元素添加到
		 * 当前集合中。
		 */
		c2.addAll(c1);
		System.out.println("c2:"+c2);
		
		Collection c3 = new ArrayList();
		c3.add("c");
		c3.add(".net");
		c3.add("android");
		System.out.println("c3:"+c3);
		/*
		 * boolean containsAll(Collection c)
		 * 判断当前集合是否包含给定集合中的
		 * 所有元素
		 */
		boolean ca = c2.containsAll(c3);
		System.out.println("全包含:"+ca);
		/*
		 * 删除当前集合与给定集合的共有元素
		 */
		c2.removeAll(c3);
		System.out.println(c2);
		
	}}


/**
 * 集合提供了同一的遍历元素方式:迭代器模式
 * 
 * 对应方法:
 * Iterator iterator()
 * 该方法可以获取一个用来遍历当前集合的迭代器
 * 实现类,通过它遍历元素
 * 
 * java.util.Iterator接口
 * 迭代器接口,规定了迭代器遍历集合的相关操作
 * 不同的集合都实现了一个用于遍历自身元素的
 * 迭代器实现类。
 * 
 * 迭代器遍历集合元素遵循的过程:问,取,删
 * 其中删除元素不是必要操作
 * 
 * @author Mr.Cui
 *
 */
public class IteratorDemo {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		c.add("one");
		c.add("#");
		c.add("two");
		c.add("#");
		c.add("three");
		c.add("#");
		c.add("four");
		c.add("#");
		c.add("five");
		System.out.println(c);	
		//获取迭代器
		Iterator it = c.iterator();
		/*
		 * boolean hasNext()
		 * 判断集合是否还有元素可以迭代
		 */
		while(it.hasNext()) {//问
			/*
			 * E next()
			 * 迭代集合下一个元素
			 */
			String o = (String)it.next();//取
			if("#".equals(o)) {
//				c.remove(o);
				/*
				 * 删除的是通过next方法取出
				 * 的元素
				 */
				it.remove();//删
			}
			System.out.println(o);
		}
	
		System.out.println(c);
	}}
——————————————————————————————}

/**
 * JDK5推出时,推出了一个新的特性:
 * 增强型for循环,也称为新循环,for each
 * 
 * 新循环不取代传统for循环的工作,它专门设计
 * 是用来遍历集合或数组的。
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String[] array = {"one","two","three","four"};
		
		for(int i=0;i<array.length;i++) {
			System.out.println(array[i]);
		}
		/*
		 * 新循环的语法也是编译器认可,而非虚拟机
		 * 认可。编译器会在编译源代码时将新循环
		 * 遍历数组改为传统for循环遍历的方式
		 */
		for(String str : array) {
			System.out.println(str);
		}
	}}

/**
 * 使用新循环遍历集合
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Collection c = new ArrayList();
		c.add("one");
		c.add("two");
		c.add("three");
		c.add("four");
		c.add("five");
		System.out.println(c);
		/*
		 * 新循环遍历集合会被编译器改为使用
		 * 迭代器遍历。所以在遍历的过程中是
		 * 不能通过集合的方法增删元素的。
		 */
		for(Object o : c) {
			String str = (String)o;
			System.out.println(str);
		}		
	}}


/**
 * 泛型
 * 泛型是JDK5推出的特性, 也称为参数化类型
 * 它允许将一个类中属性的类型,方法参数的类型
 * 以及方法返回值类型等的定义权移交给使用者。
 * 这使得实际应用中使用这个类更加灵活便捷。
 * @author Mr.Cui
 */
public class Location<E> {
	private E x;
	private E y;
	public Location(E x, E y) {
		super();
		this.x = x;
		this.y = y;
	}
	public E getX() {
		return x;
	}
	public void setX(E x) {
		this.x = x;
	}
	public E getY() {
		return y;
	}
	public void setY(E y) {
		this.y = y;
	}
	
	@Override
	public String toString() {
		return "("+x+","+y+")";
	}}

/**
 * 测试泛型
 * @author Mr.Cui
 */
public class TypeDemo {
	public static void main(String[] args) {
		Location<Integer> loc1 = new Location<Integer>(1,2);
		loc1.setX(2);
		int x1 = loc1.getX();
		System.out.println("loc1:"+loc1);
		System.out.println("x1:"+x1);
		Location<Double> loc2 = new Location<Double>(1.1,2.2);
		loc2.setX(2.2);
		double x2 = loc2.getX();
		System.out.println("loc2:"+loc2);
		System.out.println("x2:"+x2);
		Location<String> loc3 = new Location<String>("一","二 ");
		loc3.setX("三");
		String x3 = loc3.getX();
	}}


**
 * 泛型是编译器认可,而非虚拟机。
 * 编译器会将泛型改为Object。所以泛型的实际
 * 类型就是Object
 * 在使用泛型时,编译器会辅助做两个操作
 * 1:对泛型设置值时,编译器会检查该值的类型
 *   是否与泛型一致,不一致则编译不通过。
 * 2:在获取泛型值时,编译器会添加向下造型的
 *   代码。  
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Location<Integer> loc1 = new Location<Integer>(1,2);
		/*
		 * 编译器会检查实际赋值是否符合泛型类型
		 * 要求,不符合编译不通过。
		 */
		loc1.setX(1);
//		loc1.setX("1");//编译不通过
		/*
		 * 编译器会在编译时补全向下造型的代码为:
		 * int x1 = (Integer)loc1.getX();
		 * 然后还会触发自动拆箱,改为
		 * int x1 = ((Integer)loc1.getX()).intValue();
		 */
		int x1 = loc1.getX();
		System.out.println("loc1:"+loc1);
		System.out.println("x1:"+x1);
		/*
		 * 泛型可以不指定,不指定则按照默认的
		 * Object看待
		 */
		Location loc2 = loc1;
		System.out.println("loc2:"+loc2);
		loc2.setX("三");
		System.out.println("loc2:"+loc2);
		
		//再次以loc1角度获取x
		//x1 = (Integer)loc1.getX();
		x1 = loc1.getX();//类造型异常
		System.out.println("x1:"+x1);
	}}


/**
 * 泛型在集合当中的应用---约束集合中的元素类型
 * @author M.Cui
 */
	public static void main(String[] args) {
		Collection<String> c = new ArrayList<String>();
		/*
		 * 指定后add方法只能传入泛型要求的
		 * 元素
		 */
		c.add("one");
		c.add("two");
		c.add("three");
		c.add("four");
		System.out.println(c);
		/*
		 * 新循环可以直接用实际类型接收元素
		 */
		for(String str: c) {
			System.out.println(str);
		}
		/*
		 * 迭代器也支持泛型,指定的类型与
		 * 集合的泛型一致即可
		 */
		Iterator<String> it = c.iterator();
		while(it.hasNext()) {
			String str = it.next();
			System.out.println(str);
		}
	}}


/**
 * java.util.List接口
 * List继承自Collection
 * List的特点:可重复,并且有序,提供了一组可以
 * 通过下标操作元素的方法。
 * 
 * 常用实现类:
 * java.util.ArrayList:内部由数组实现,查询
 * 性能更好。
 * java.util.LinkedList:内部由链表实现,增删
 * 元素性能更好,尤其首尾增删元素。
 * 在对性能没有特别苛刻要求下,通常使用的是
 * ArrayList即可。
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		List<String> list 
			= new ArrayList<String>();
		list.add("one");
		list.add("two");
		list.add("three");
		list.add("four");
		list.add("five");
		System.out.println(list);
		/*
		 * E get(int index)
		 * 获取给定下标对应的元素
		 */
		String str = list.get(1);
		System.out.println(str);
		//List可以用普通的for循环遍历
		for(int i=0;i<list.size();i++) {
			str = list.get(i);
			System.out.println(str);
		}
		
		/*
		 * E set(int index, E e)
		 * 将给定元素设置到指定位置,返回值为
		 * 原位置对应元素。所以set方法的意义是
		 * 替换元素操作
		 */
		//[one,2,three,four,five]
		String old = list.set(1, "2");
		System.out.println(list);
		System.out.println(old);
		
	}}


/**
 * List提供了一对重载的add,remove方法
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		List<String> list 
			= new ArrayList<String>();
		list.add("one");
		list.add("two");
		list.add("three");
		list.add("four");
		list.add("five");
		System.out.println(list);
		/*
		 * void add(int index,E e)
		 * 将给定元素插入到指定位置
		 * 
		 * [one,2,two,three,four,five]
		 */
		list.add(1, "2");
		System.out.println(list);
		/*
		 * E remove(int index)
		 * 删除并返回给定位置对应的元素
		 * [one,2,three,four,five]
		 */
		String old = list.remove(2);
		System.out.println(list);
		System.out.println(old);
	}}


/**
 * 使用当前类实例作为集合元素,测试集合相关
 * 操作。
 * @author Mr.Cui
 */
public class Point
			implements Comparable<Point>{
	private int x;
	private int y;
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public String toString() {
		return "("+x+","+y+")";
	}
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj == this) {
			return true;
		}
		if(obj instanceof Point) {
			Point p = (Point)obj;
			return this.x==p.x&&this.y==p.y;
		}
		return false;
	}
	/**
	 * 当一个类实现了Comparable接口后必须重写
	 * 方法:compareTo
	 * 该方法的作用是比较当前对象this与方法的
	 * 参数对象o之间的大小。
	 * 
	 * 返回值不关心具体取值,只关心取值范围
	 * 当返回值>0:当前对象大于参数对象(this>o)
	 * 当返回值<0:当前对象小于参数对象
	 * 当返回值=0:两个对象相等 
	 */
	public int compareTo(Point o) {
		int len = this.x*this.x+this.y*this.y;
		int olen = o.x*o.x+o.y*o.y;
		return len-olen;
	}
}



/**
 * 获取子集操作
 * List subLis(int start,int end)
 * 获取当前集合指定下标对应范围内的元素
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		List<Integer> list 
			= new ArrayList<Integer>();
		for(int i=0;i<10;i++) {
			list.add(i);
		}
		System.out.println(list);
		
		List<Integer> subList = list.subList(3, 8);
		System.out.println(subList);
		/*
		 * 将子集每个元素扩大10倍
		 */
		for(int i=0;i<subList.size();i++) {
			subList.set(i,subList.get(i)*10);
		}
		System.out.println(subList);
		/*
		 * 操作子集就是对原集合对应元素的操作
		 */
		System.out.println(list);
		
		/*
		 * 将list集合中2-8删除
		 */
		list.subList(2, 9).clear();
		System.out.println(list);
		
	}}


/**
 * 集合转换为数组
 * 集合提供了一个方法:toArray,可以将当前
 * 集合转换为一个数组
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Collection<String> c = new ArrayList<String>();
		c.add("one");
		c.add("two");
		c.add("three");
		c.add("four");
		System.out.println(c);
		
//		Object[] array = c.toArray();
		String[] array 
			= c.toArray(new String[c.size()]);
		System.out.println(array.length);
		System.out.println(Arrays.toString(array));
	}}


/**
 * 数组转换为List集合。
 * 通过数组的工具类:Arrays的静态方法asList
 * 可以将一个数组转换为一个List
 * 
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		String[] array = {"one","two","three","four"};
		
		List<String> list 
			= Arrays.asList(array);
		System.out.println(list);
		/*
		 * 数组转换的集合对其元素操作就是对
		 * 原数组对应元素的操作
		 */
		list.set(1, "2");
		System.out.println(list);
		System.out.println("array:"+Arrays.toString(array));
		/*
		 * 由于数组是定长的,所以不支持集合
		 * 的增删操作,下面的操作会抛出异常
		 */
//		list.add("five");
	
		/*
		 * 所有的集合都提供了一个参数为Collection
		 * 的构造方法,作用是在创建当前集合的同时
		 * 包含给定集合中的所有元素
		 */
		List<String> list2 
			= new ArrayList<String>(list);

		list2.add("five");
		System.out.println(list2);
				
	}}



/**
 * 集合工具类:java.util.Collections
 * 其提供了一个静态方法:sort,可以对List集合
 * 进行自然排序(从小到大)
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		List<Integer> list 
			= new ArrayList<Integer>();
		Random random = new Random();
		for(int i=0;i<10;i++) {
			list.add(random.nextInt(100));
		}
		System.out.println(list);
		Collections.sort(list);
		System.out.println(list);
		
	}}


/**
 * 排序自定义类型元素
 * @author Mr.Cui
 */
public class SortListDemo2 {
	public static void main(String[] args) {
		List<Point> list = new ArrayList<Point>();
		list.add(new Point(3,4));
		list.add(new Point(4,9));
		list.add(new Point(2,7));
		list.add(new Point(8,1));
		list.add(new Point(6,0));
		list.add(new Point(4,4));
		System.out.println(list);
		/*
		 * Collections的sort方法排序的集合要求
		 * 元素必须实现Comparable接口。
		 */
		Collections.sort(list);
		System.out.println(list);
		
	}}


/**
 * 创建一个List集合,并存放10个随机数,然后排序该集合
 * 后输出
 * @author Mr.Cui
 */
  public static void main(String[] args){
	  List<Integer> l = new ArrayList<Integer>();
	  Random random = new Random();
	  for(int a =0; a<10;a++){	  
		
		 l.add(random.nextInt(100));
	  }
	  System.out.println("10个"+"随机数:"+l);
	 Collections.sort(l);
	 System.out.println("排序后为:"+
	 l);
  }}


/**
 * 使用当前类实例作为集合元素,测试集合相关
 * 操作。
 * 
 * 侵入性
 * @author Mr.Cuis
 */
public class Point
			implements Comparable<Point>{
	private int x;
	private int y;
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public String toString() {
		return "("+x+","+y+")";
	}
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj == this) {
			return true;
		}
		if(obj instanceof Point) {
			Point p = (Point)obj;
			return this.x==p.x&&this.y==p.y;
		}
		return false;
	}
	/**
	 * 当一个类实现了Comparable接口后必须重写
	 * 方法:compareTo
	 * 该方法的作用是比较当前对象this与方法的
	 * 参数对象o之间的大小。
	 * 
	 * 返回值不关心具体取值,只关心取值范围
	 * 当返回值>0:当前对象大于参数对象(this>o)
	 * 当返回值<0:当前对象小于参数对象
	 * 当返回值=0:两个对象相等 
	 */
	public int compareTo(Point o) {
		int len = this.x*this.x+this.y*this.y;
		int olen = o.x*o.x+o.y*o.y;
		return len-olen;
	}}


/**
 * 排序自定义类型元素
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		List<Point> list = new ArrayList<Point>();
		list.add(new Point(3,4));
		list.add(new Point(4,9));
		list.add(new Point(2,7));
		list.add(new Point(8,1));
		list.add(new Point(6,0));
		list.add(new Point(4,4));
		System.out.println(list);
		/*
		 * Collections的sort方法排序的集合要求
		 * 元素必须实现Comparable接口。
		 * 
		 * 如果是排序自定义类型元素,强烈建议
		 * 不使用这种方式,因为这个sort方法对
		 * 我们的代码有侵入性(它要求Point必须
		 * 为它实现接口,并重写方法)
		 * 由于java API中很多类已经实现了该接口,
		 * 比如包装类,String等,那么在排序这
		 * 样元素的集合时可以直接用下面这个sort
		 */
//排序.sort	Collections.sort(list);
		System.out.println(list);
		
	}}


/**
 * 排序字符串
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("小泽老师");
		list.add("传奇");
		list.add("苍老师");	
		System.out.println(list);
		/*
		 * String已经实现了Comparable接口
		 * 比较规则为按照每个字符的unicode编码
		 * 比较。
		 * 对于排序中文时,没有什么意义。
		 * 
		 * 对此,该sort方法的使用相对局限。
		 * 所以当:
		 * 排序自定义类型元素或java提供的已经实现
		 * 过Comparable接口的元素,但是比较方法不
		 * 满足我们排序需求时,都不应当使用下面的
		 * sort方法
		 * 
		 */
		Collections.sort(list);
		System.out.println(list);
						
	}}


/**
 * Collections提供了一个重载的sort方法,该
 * 方法除了要求传入要排序的集合外,还要求再
 * 传入一个比较器(Comparator),该比较器可以
 * 定义一种比较规则,该sort方法会用这个比较
 * 规则对集合元素比较后进行排序。
 * 
 * @author Mr.Cui
 */
public class SortListDemo4 {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("传奇");
		list.add("小泽老师");
		list.add("苍老师");
		System.out.println(list);
		/*
		 * 这种排序方法不要求集合元素必须实现Comparable
		 * 接口,对此在排序自定义元素时不对我们的代码
		 * 产生额外侵入,由于可以自定比较规则,对于像
		 * String这样已经实现类比较方法的可以做到按照
		 * 我们的比较规则排序。
		 * 开发中推荐中这种方式排序.
		 */
		Collections.sort(
		 list,new Comparator<String>() {
			public int compare(String o1, String o2){
				//按照字符多少比大小
				return o1.length()-o2.length();
			}
		});
		System.out.println(list);
	}}


/**
 * java.util.Queue
 * Queue接口继承自Collection。
 * 队列也可以保存一组元素,但是存取元素必须
 * 遵循先进先出模式。
 * 常用实现类:LinkedList
 * @author Mr.Cui
 */
public class QueueDemo {
	public static void main(String[] args) {
		Queue<String> queue
			= new LinkedList<String>();
		/*
	 * offer是入队操作,向队列末尾追加
		 * 元素
		 */
		queue.offer("one");
		queue.offer("two");
		queue.offer("three");
		queue.offer("four");
		queue.offer("five");
		queue.offer("six");
		System.out.println(queue);
		/*
	 * poll方法是出队操作
		 * 获取队首元素后该元素即从队列中
		 * 被删除
		 */
		String str = queue.poll();
		System.out.println(str);
		System.out.println(queue);
		/*
	 * peek是引用队首元素,元素不做出队
		 * 操作
		 */
		str = queue.peek();
		System.out.println(str);
		System.out.println(queue);
		
		
		/*
	 * 遍历队列
	 * 使用迭代器遍历,元素不会因此被队列
	 * 删除
		 * 
		 */
		for(String s : queue) {
			System.out.println(s);
		}
		System.out.println(queue);
		
		/*
	 * 使用poll方法遍历队列
		 */
		while(queue.size()>0) {
			String s = queue.poll();
			System.out.println(s);
		}
		System.out.println(queue);
		
	}}


/**
 * 双端队列
 * java.util.Deque接口
 * Deque继承自Queue接口
 * 双端队列是指队列两端都可以做进出队操作。
 * 常用实现类:LinkedList
 * @author Mr.Cui
 */
public class DequeDemo {
	public static void main(String[] args) {
		Deque<String> deque 
			= new LinkedList<String>();
		
		deque.offer("one");
		deque.offer("two");
                              // First  开始位置
		deque.offerFirst("three");
                              //Last 末端位置
		deque.offerLast("four");
		
		System.out.println(deque);
		
		String str = deque.poll(); //出队操作
		System.out.println(str);
		System.out.println(deque);
		//从开头开始删除
	               str = deque.pollFirst();
		System.out.println(str);
		System.out.println(deque);
		 //从末端开始删除
		str = deque.pollLast();
		System.out.println(str);
		System.out.println(deque);
		
	}}


/**
 * 栈结构
 * 栈也可以保存一组元素,但是存取元素必须遵循
 * 先进后出原则。
 * Deque双端队列可以实现栈,并且为栈专门提供
 * 了两个方法:push,pop
 * 通常我们使用栈是为了实现"后退"这样等功能
 * @author Mr.Cui
 *
 */
public class StackDemo {
	public static void main(String[] args) {
		Deque<String> stack 
			= new LinkedList<String>();	
                              //stack 后退输出 如123输出321  	
		stack.push("one");
		stack.push("two");
		stack.push("three");
		stack.push("four");
		stack.push("five");
		System.out.println(stack);
//remove,poll,pop,均表示删除
		String str = stack.pop();
		System.out.println(str);//删除元素
		System.out.println(stack);//输出删除后的元素
		
	}}


/**
 * 集合有线程安全的实现。我们可以借助Collections
 * 将现有的集合转换为一个线程安全的。
 * @author Mr.Cui
 *
 */
public class SyncDemo {
	public static void main(String[] args) {
		/*
	 * List中常用的实现类:
	 * ArrayList,LinkedList它们都不是
	 * 线程安全的。
		 */
		List<String> list 
			= new ArrayList<String>();
		list.add("one");
		list.add("two");
		list.add("three");
		System.out.println(list);
		/*
	 * 将给定的集合转换为一个线程安全的
		 */
	list = Collections.synchronizedList(list);
		System.out.println(list);
		/*
	 * HashSet同样也不是线程安全的
		 */
		Set<String> set 
			= new HashSet<String>(list);
		set = Collections.synchronizedSet(set);
		System.out.println(set);
		
		/*
	 * 文档上有说明一个事情:
	 * 即使是一个线程安全的集合,它也不同
	 * 迭代器遍历做互斥,所以这个操作要自行
	 * 维护。
		 */
				
		/*
	 * 队列也有并发安全的实现
	 * 阻塞队列
	 * BlockingQueue,BlockingDeque
	 * 阻塞队列内部使用双缓冲实现,在保证
	 * 并发安全的前提下解决了存取互斥问题
	 * 所以并发效率更好
		 */
		BlockingQueue<String> queue
			= new LinkedBlockingQueue<String>();
		
		queue.offer("one");
		try {
                             //500是时间(毫秒),Time.MILLISECONDS是单位
			queue.offer("two", 500, TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}	
	}}


/**
 * 判断Map是否包含给定元素。
 * 可以分别判断是否包含key和value
 * boolean containsKey(Object k)
 * boolean containsValue(Object v)
 * @author Mr.Cui
 */
	public static void main(String[] args) {
		Map<String,Integer> map
			= new HashMap<String,Integer>();
		map.put("语文", 98);
		map.put("数学", 97);
		map.put("英语", 96);
		map.put("物理", 95);
		map.put("化学", 98);		
		System.out.println(map);		
		/*
		 * 查看是否包含指定的key
		 */
		boolean ck = map.containsKey("语文");
		System.out.println("包含key:"+ck);
		
		boolean cv = map.containsValue(95);
		System.out.println("包含value:"+cv);
		
	}}


/**
 * HashMap是查询速度最快的数据结构,内部使用
 * 数组实现,它通过Key的hashcode值计算该元素
 * 在数组中的下标位置,从而避免了遍历数组的操
 * 作,从而查询不受元素多少影响。
 * 
 * 由于Key的hashcode方法(决定其在HashMap内部
 * 数组的位置)和equals方法(决定Key是否为重复)
 * 直接影响HashMap是否会出现链表,对此这两个
 * 方法在Object类中有明确的重写说明。
 * 
 * 当一个HashMap内部出现链表时,会降低其查询
 * 性能,应当尽量避免。而出现链表的情况在于:
 * 当两个Key的hashcode值相同,而equals比较不
 * 为true时就会形成。
 * 
 * API手册中在Object类里说明了这两个方法的重
 * 写规则:
 * 1:成对重写
 *   当我们需要重写一个类的equals方法时,就
 *   应当连同重写hashcode方法
 * 2:一致性
 *   当两个对象的equals比较为true时,hashcode
 *   方法返回的数字必须相等。反之则不是必须的,
 *   但是应当尽量保证当两个对象hashcode值相同
 *   时equals方法比较为true,否则在HashMap中
 *   作为Key使用时会出现链表!
 * 3:稳定性
 *   当一个对象参与equals比较的属性值没有发生
 *   过改变的前提下,多次调用hashcode方法返回
 *   的数字应当相同    
 * 
 * @author Mr.Cui
 *
 */
public class Key {
	private int x;
	private int y;
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Key other = (Key) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}	}

/**
 * java.util.Map
 * Map 查找表,结构看起来像是一个多行两列的
 * 表格。左列称为key,右列称为value。
 * 所以Map总是以key-value对的形式保存元素。
 * 并且总是根据key去获取对应的value.
 * 对此我们经常将“查询条件”作为key,将要查询
 * 的数据作为value进行保存。
 * 
 * Map本身是一个接口,规定了Map操作的相关方法。
 * 常用实现类:java.util.HashMap
 * 
 * HashMap又称为散列表,哈希表
 * 使用散列算法实现的Map,当今世界上查询速度
 * 最快的数据结构,查询速度最快,查询速度最快!
 * 
 * @author Mr.Cui
 */
public class MapDemo1 {
	public static void main(String[] args) {
		Map<String,Integer> map
			= new HashMap<String,Integer>();
		/*
		 * V put(K k,V v)
		 * 将给定的一组键值对存入到Map中
		 * 
		 * Map有一个要求,即:key不允许重复,
		 * 是否重复是依靠key自身equals比较的
		 * 结果。
		 * 如果使用map中已有的key保存value,
		 * 则这个操作为替换value操作,那么
		 * 这时put方法会将被替换的value返回。
		 * 否则返回值为null。
		 */
		/*
		 * 如果value是一个包装类,那么接收时
		 * 应当避免直接用基本类型。因为这会
		 * 导致自动拆箱,若没有做替换操作,返
		 * 回的value为null时就引发了空指针异常
		 */
		Integer d = map.put("语文", 98);
		System.out.println(d);
		map.put("数学", 97);
		map.put("英语", 96);
		map.put("物理", 95);
		map.put("化学", 98);		
		System.out.println(map);
		
		d = map.put("语文", 55);
		System.out.println(d);
		System.out.println(map);
		
		
		/*
		 * V get(Object key)
		 * 根据给定的key获取对应的value,若
		 * 给定的key不存在,则返回值为null
		 */
		d = map.get("数学");
		System.out.println("数学:"+d);
		/*
		 * int size()
		 * 获取Map中的元素个数,每组键值对算
		 * 一个元素
		 */
		int size = map.size();
		System.out.println("size:"+size);
		
		/*
		 * V remove(K k)
		 * 将给定的key所对应的键值对删除。
		 * 返回值为该key对应的value。
		 */
		d = map.remove("语文");
		System.out.println(map);
		System.out.println(d);
		
	}}


/**
 * Map的遍历
 * 遍历Map有三种方式
 * 1:遍历所有的key
 * 2:遍历每一组键值对
 * 3:遍历所有的value(相对不常用)
 * 
 * @author Mr.Cui
 */
public class MapDemo2 {
	public static void main(String[] args) {
		Map<String,Integer> map
			= new LinkedHashMap<String,Integer>();
		map.put("语文", 98);
		map.put("数学", 97);
		map.put("英语", 96);
		map.put("物理", 95);
		map.put("化学", 98);		
		System.out.println(map);
		
		/*
		 * 遍历所有的key
		 * Set keySet()
		 * 将当前Map中所有的key以一个Set集合
		 * 形式返回。遍历这个集合就等同于遍历
		 * 了所有的key
		 */
		Set<String> keySet = map.keySet();
		for(String key : keySet) {
			System.out.println("key:"+key);
		}
		
		/*
		 * 遍历每一组键值对
		 * Set entrySet()
		 * 
		 * java.util.Map.Entry
		 * Entry的每一个实例用于表示当前Map中的
		 * 一组键值对。其中有两个常用的方法:
		 * getKey(),getValue()分别用于获取对应的
		 * key与value
		 */
		Set<Entry<String,Integer>> entrySet 
							= map.entrySet();
		
		for(Entry<String,Integer> e: entrySet) {
			String key = e.getKey();
			Integer value = e.getValue();
			System.out.println(key+":"+value);
		}		
		/*
		 * 遍历所有的value
		 */
		Collection<Integer> values = map.values();
		for(Integer value : values) {
			System.out.println("value:"+value);
		}	}}

你可能感兴趣的:(java,java,API使用大全)