Java学习记录六

    LinkedHashMap

         * LinkedHashMap:是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。
         * 由哈希表保证键的唯一性
         * 由链表保证键盘的有序(存储和取出的顺序一致)

		LinkedHashMap l = new LinkedHashMap();
		l.put(1, "hello");
		System.out.println(l);

   案例:统计字符串中 出现的字符数量。

      *数据类型的选择和代码熟练不够啊。。。

		String string="aababcabcdabcde";
		HashMap<String, Integer> hm = new HashMap<>();
		char[] chars = string.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			Set<String> set3 = hm.keySet();
			String key=chars[i]+"";
			if(!set3.contains(key)){
				hm.put(key, 1);
			}else{
				hm.put(key, hm.get(key)+1);
			}
		}
——————————————————————————————————————————————————————↑ 自己的
		String string="aababcabcdabcde";
		HashMap<Character, Integer> hm = new HashMap<>();
		char[] chars = string.toCharArray();
		for (char c : chars) {
			Integer count = hm.get(c);
			if(count==null){
				hm.put(c, 1);
			}else{
				count++;
				hm.put(c,count);
			}
		}

    HashTable和HashMap的区别

       注:Map本身就是一个顶层接口。

       * 1:Hashtable和HashMap的区别?
        * Hashtable:线程安全,效率低。不允许null键和null值
        * HashMap:线程不安全,效率高。允许null键和null值

   Collection和Collections的区别?
         * Collection:是单列集合的顶层接口,有子接口List和Set。
         * Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法

   final,finally,finalize的区别?

        final 不写了。。

       finally是异常捕获机制的一部分,其中代码总会执行除非jvm提前退出,一般用于资源释放工作。

扫描二维码关注公众号,回复: 3712945 查看本文章

        finalize是Object中的方法方。垃圾收集器在确定这个对象没有被引用时会对这个对象调用的。将对象从内存中清除出去之前做必要的清理工作

  关于File的一些操作:

        注:File可以指向文件,也可以指向文件夹。用下面的这些方法时要注意当前对象的指向。

       *public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
       *public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
       *public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来

       * 删除功能:public boolean delete()

 *         A:如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
 *         B:Java中的删除不走回收站。
 *         C:要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹

        * 重命名功能:public boolean renameTo(File dest)
 *         如果路径名相同,就是改名。
 *         如果路径名不同,就是改名并剪切。

		 // 创建一个文件对象
		 File file = new File("林青霞.jpg");
		 // 需求:我要修改这个文件的名称为"东方不败.jpg"
		 File newFile = new File("东方不败.jpg");
		 System.out.println("renameTo:" + file.renameTo(newFile));

		File file2 = new File("东方不败.jpg");
		File newFile2 = new File("e:\\林青霞.jpg");
		System.out.println("renameTo:" + file2.renameTo(newFile2));

         * 获取功能
                   * public String getAbsolutePath():获取绝对路径
                   * public String getPath():获取相对路径

                    * public String getName():获取名称
                    * public long length():获取长度。字节数
                    * public long lastModified():获取最后一次的修改时间,毫秒值


                     * public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
                     * public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组

         关于异常需要了解的东西

                 * 在try里面发现问题后,jvm会帮我们生成一个异常对象,然后把这个对象抛出,和catch里面的类进行匹配。
                 * 如果该对象是某个类型的,就会执行该catch里面的处理信息。

                  * public String getMessage():异常的消息字符串        
                  * public String toString():返回异常的简单信息描述

try {
	int num=1/0;
} catch (ArithmeticException e) {
	System.out.println(e.getMessage());     ---->/ by zero
	System.out.println(e.toString());   ---->java.lang.ArithmeticException: / by zero
}

        自定义异常:

               * 两种方式:
               * A:继承Exception
               * B:继承RuntimeException

public class MyException extends Exception {
	public MyException() {
	}

	public MyException(String message) {
		super(message);
	}
}

       异常注意事项:  其实就是方法重新安歇规则,异常定义中显的格外冒尖。
               * A:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
               * B:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
               * C:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

     IO流

      流的分类:输入是读,输出是写。

 *         流向:
 *             输入流    读取数据         InputStream      Reader
 *             输出流    写出数据         OutputStream   Writer
 *         数据类型:
 *             字节流
 *                 字节输入流    读取数据    InputStream
 *                 字节输出流    写出数据    OutputStream
 *             字符流
 *                 字符输入流    读取数据    Reader
 *                 字符输出流    写出数据    Writer
 *
 *         注意:一般我们在探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况下是按照数据类型来分的。

     数据的追加写入和换行

 * 如何实现数据的换行?
 *         为什么现在没有换行呢?因为你只写了字节数据,并没有写入换行符号。
 *         如何实现呢?写入换行符号即可呗。
 *         刚才我们看到了有写文本文件打开是可以的,通过windows自带的那个不行,为什么呢?
 *         因为不同的系统针对不同的换行符号识别是不一样的?
 *         windows:\r\n
 *         linux:\n
 *         Mac:\r
 *         而一些常见的个高级记事本,是可以识别任意换行符号的。

		FileOutputStream fos = new FileOutputStream("fos3.txt", true);
		for (int x = 0; x < 10; x++) {
			fos.write(("hello" + x).getBytes());
			fos.write("\r\n".getBytes());
		}

		// 释放资源
		fos.close();

    案例:

		File file = new File("D:\\temp\\wutong.txt");
		FileOutputStream out = new FileOutputStream(file);
		File file2 = new File("D:\\temp\\Hello.java");
		FileInputStream input = new FileInputStream(file2);
		byte[] bys=new byte[1024];
		while((input.read(bys))!=-1){
			out.write(bys);
		}
		input.close();
		out.close();

     给的字节数组太大了,会出现下图

    

     可以这样改,去除空格。

        int len;
        while((len=input.read(bys))!=-1){
            out.write(bys,0,len);
        }

   中文问题:

     * 计算机是如何识别什么时候该把两个字节转换为一个中文呢?
     * 在计算机中中文的存储分两个字节:
     *         第一个字节肯定是负数。
     *         第二个字节常见的是负数,可能有正数。但是没影响。

		String s="耄耋";
		byte[] bys = s.getBytes();
		System.out.println(Arrays.toString(bys)); [-21, -93, -15, -13]

  逆向的把这个字节数组通过流的方式写入文件,文件成功的显示:耄耋。个人向,字节数组两个为一组与汉字的标识进行匹配,匹配成功,就显示汉字,谨慎使用。

      以前最头疼的递归:方法定义中调用方法本身的现象

      * 注意事项:
      *         A:递归一定要有出口,否则就是死递归
      *         B:递归的次数不能太多,否则就内存溢出
      *         C:构造方法不能递归使用

	private static int jiecheng(int n){     ----->n的阶乘名字略土。。。
		if(n==1){
			return 1;
		}
		return n*jiecheng(n-1);
	}

          案例: 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?

         分析:    月份       兔子对数

          1         1

          2         1

          3         2

          4         3

          5         5

          6         8

   感觉很复杂,代码。。。数组也可以实现,初始化前两个元素。使用循环即可。

	private static int tuzi(int n){
		if(n==1 || n==2){
			return 1;
		}
		return tuzi(n-1)+tuzi(n-2);
	}

   字符流在进行操作的时候都有指定字符集的构造:

     * OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流

   字符缓冲流的,清空缓存操作

		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		// 封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

		// 两种方式其中的一种一次读写一个字符数组
		char[] chs = new char[1024];
		int len = 0;
		while ((len = br.read(chs)) != -1) {
			bw.write(chs, 0, len);
			bw.flush();    ------>清一下缓存,别满了再请。
		}

		// 释放资源
		bw.close();
		br.close();

         文件夹筛选功能

		File[] fileArray = srcFolder.listFiles(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				return new File(dir, name).isFile() && name.endsWith(".java");
			}
		});

     BufferedReader源码解读
     *debug状态下无法查看局部变量。

     参考文章:https://blog.csdn.net/appleprince88/article/details/21873807

                      第五步中,不需要全部复制,只需要复制一个rt.jar即可,放到jdk_src同级目录下即可

                            

    自定义BufferedReader的readLine()方法

         * 我要返回一个字符串,我该怎么办呢? 我们必须去看看r对象能够读取什么东西呢? 两个读取方法,一次读取一个字符或者一次读取一个字符数组
         * 那么,我们要返回一个字符串,用哪个方法比较好呢? 我们很容易想到字符数组比较好,但是问题来了,就是这个数组的长度是多长呢?
         * 根本就没有办法定义数组的长度,你定义多长都不合适。 所以,只能选择一次读取一个字符。
         * 但是呢,这种方式的时候,我们再读取下一个字符的时候,上一个字符就丢失了 所以,我们又应该定义一个临时存储空间把读取过的字符给存储起来。
         * 这个用谁比较和是呢?数组,集合,字符串缓冲区三个可供选择。
         * 经过简单的分析,最终选择使用字符串缓冲区对象。并且使用的是StringBuilder

	public String readLine() throws IOException {
		StringBuilder sb = new StringBuilder();
		int ch = 0;
		while ((ch = r.read()) != -1) { //104,101,108,108,111
			if (ch == '\r') {
				continue;
			}
			if (ch == '\n') {
				return sb.toString(); //hello
			} else {
				sb.append((char)ch); //hello
			}
		}

		// 为了防止数据丢失,判断sb的长度不能大于0
		if (sb.length() > 0) {
			return sb.toString();
		}

		return null;
	}

       内存操作流有点怪,记录在这里。需要输入流的的一个byte数组初始化输出流

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		for (int i = 0; i < 10; i++) {
			baos.write(("hello"+i).getBytes());
		}
		byte[] buf = baos.toByteArray();
		ByteArrayInputStream bais = new ByteArrayInputStream(buf);
		int by;
		while((by=bais.read())!=-1){
			System.out.println((char)by);
		}
		baos.close();
		bais.close();

      打印流实现复制文件:打印流可以直接操作文本文件但是只可以输出,不能读取

 *         println()            --->好高级的感觉。。
 *        其实等价于于:
 *        bw.write();
 *        bw.newLine();        
 *        bw.flush();

		BufferedReader br = new BufferedReader(new FileReader("D:\\temp\\wutong.txt"));
		PrintWriter pw = new PrintWriter("D:\\temp\\wutong2.txt"); --->不存在自行创建
		String line;
		while((line=br.readLine())!=null){
			pw.println(line);
		}
		pw.close();
		br.close();

 *             哪些流对象是可以直接操作文本文件的呢?
 *             FileInputStream
 *             FileOutputStream
 *             FileReader
 *             FileWriter
 *             PrintStream
 *             PrintWriter
 *             看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的。
 *
 *             流:
 *                 基本流:就是能够直接读写文件的
 *                 高级流:在基本流基础上提供了一些其他的功能

         键盘输入标准流

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line=br.readLine();
		BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\temp\\wutong.txt"));
		bw.write(line);
		bw.close();
		br.close();
————————————————————————————————————————————————————————————————————————
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		bw.write("hello ");
		bw.write("world");
		bw.close();

 * System类中的两个成员变量:
 *        public static final InputStream in “标准”输入流。
 *         public static final PrintStream out “标准”输出流。

         随机访问流

             *随机访问流不可以在写入数据后马上读取数据。

             *seek(4),指针开始的位置,初始化为1,在读取了100之后其值变成了4

		RandomAccessFile raf = new RandomAccessFile("D:\\temp\\wutong.txt", "rw");
//		raf.writeInt(100);
//		raf.writeChar('a');
//		raf.writeUTF("中国人");
//		int num = raf.readInt();
		raf.seek(4);
		char c=raf.readChar();
		System.out.println(c);                                     a
		System.out.println("文件当前位置:"+raf.getFilePointer());  6
		raf.close();

        混合流(两个文件):

		InputStream input=new FileInputStream("D:\\temp\\a.txt");
		InputStream input2=new FileInputStream("D:\\temp\\b.txt");
		SequenceInputStream sis = new SequenceInputStream(input, input2);
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\temp\\c.txt"));
		byte[] bys=new byte[1024];
		int len=0;
		while((len=sis.read(bys))!=-1){
			bos.write(bys,0,len);
		}
		bos.close();
		sis.close();

        混合流(多个文件):

		Vector<InputStream> v = new Vector<InputStream>();
		InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
		InputStream s2 = new FileInputStream("CopyFileDemo.java");
		InputStream s3 = new FileInputStream("DataStreamDemo.java");
		v.add(s1);
		v.add(s2);
		v.add(s3);
		Enumeration<InputStream> en = v.elements();
		SequenceInputStream sis = new SequenceInputStream(en);
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream("Copy.java"));

		// 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = sis.read(bys)) != -1) {
			bos.write(bys, 0, len);
		}

		bos.close();
		sis.close();

          对象流:传输的对象的类一定要实现序列化。以后应该会用到

	private static void read() throws IOException, ClassNotFoundException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				"oos.txt"));
		Object obj = ois.readObject();
		ois.close();
		System.out.println(obj);
	}

	private static void write() throws IOException {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
				"oos.txt"));
		Person p = new Person("林青霞", 27);
		oos.writeObject(p);
		oos.close();
	}

        Properties:属性集合类。是一个可以和IO流相结合使用的集合类。
             * Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。、

		Properties prop = new Properties();
		prop.put("1", "中国");
		prop.put("2", "中国");
		prop.put("3", "中国");
		Set<Object> set = prop.keySet();
		for (Object key : set) {
			System.out.println(prop.get(key));
		}

            *特殊功能

		Properties prop = new Properties();

		// 添加元素
		prop.setProperty("张三", "30");
		prop.setProperty("李四", "40");
		prop.setProperty("王五", "50");

		// public Set<String> stringPropertyNames():获取所有的键的集合
		Set<String> set = prop.stringPropertyNames();
		for (String key : set) {
			String value = prop.getProperty(key);
			System.out.println(key + "---" + value);
		}

 * public void load(Reader reader):把文件中的数据读取到集合中
 * public void store(Writer writer,String comments):把集合中的数据存储到文件

		Properties prop = new Properties();
		prop.setProperty("wutong", "26");
		prop.setProperty("wulu", "26");
		prop.setProperty("wuxiao", "26");
		Writer w=new FileWriter("D:\\temp\\prop.txt");
		prop.store(w, "helloworld");
		Reader r=new FileReader("D:\\temp\\prop.txt");
		prop.load(r);
		r.close();
		System.out.println(prop);

         案例:修改文件中的键值

		Properties prop = new Properties();
		Reader r=new FileReader("D:\\temp\\prop.txt");
		prop.load(r);
		r.close();
		Set<String> set = prop.stringPropertyNames();
		for (String key : set) {
			if(key.equals("wutong")){
				prop.setProperty(key, "wushuaige");
				break;
			}
		}
		Writer w=new FileWriter("D:\\temp\\prop.txt");
		prop.store(w, "描述");
		w.close();

          NIO小例子

 * Paths:有一个静态方法返回一个路径
 *         public static Path get(URI uri)
 * Files:提供了静态方法供我们使用
 *         public static long copy(Path source,OutputStream out):复制文件
 *         public static Path write(Path path,Iterable<? extends CharSequence> lines,Charset cs,OpenOption... options)

		ArrayList<String> a=new ArrayList<String>();
		a.add("hello");
		a.add("world");
		a.add("java");
		Files.write(Paths.get("D:\\temp\\a.txt"), a, Charset.forName("GBK"));

猜你喜欢

转载自blog.csdn.net/qq_34117624/article/details/83275181