黑马程序员技术交流社区

标题: 【石家庄校区】笔记 [打印本页]

作者: GIAO    时间: 2018-11-26 16:01
标题: 【石家庄校区】笔记
本帖最后由 小石姐姐 于 2018-11-30 15:03 编辑

day07
线程池的使用步骤:
1.使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool生产一个指定数量的线程池.ExecutorsService es=Executors.newFixedThreadPool(2); 这个返回的就是线程池的实现类
2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
3.调用ExecutorsService中的方法submit,传递线程任务(实现类),开启线程,执行run方法.
es.submit(new 实现类())
4.调用ExecutorsService中的方法shutdown.摧毁线程池.需要的话可以写.es.shutdown

线程池能够带来的三个好处
1. 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
  2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
  3. 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

Lambda表达式:(参数列表) ->{代码}
1.无参数括号也不能省略,有参数可以省略参数类型
2.->将参数传递给方法体
3.{重写接口抽象方法的方法体}
格式:
// 写成多行
(数据类型 变量名, 数据类型 变量名) -> {
一些重写方法的代码
一些重写方法的代码
...
}
// 如果代码只有一行, 也可以合并写成一行
(参数列表) -> {一些重写方法的代码}
return 大括号和分号要省略都省略

Lambda省略格式和使用前提
1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法",无论是JDK内置的 Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。(也称为"函数式接口")
普通类, 抽象类不能用
2. 使用Lambda必须具有上下文推断
接口中只能有一个抽象方法, 才能推断出来重写的是这个抽象方法,参数类型必须是函数式接口
*函数式接口:
函数式接口: "有且仅有一个抽象方法的接口"
但函数式接口对于 哪些方法算作抽象方法 有特殊规定:
1. 有方法体的方法"不算作"抽象方法, 如默认方法, 静态方法, 私有方法
2. 如果一个抽象方法 与 java.lang.Object类中的方法 定义相同的, 也"不算作"抽象方法
因为任何实现本接口的实现类, 都会直接或间接继承java.lang.Object类的public的方法, 所以
在创建实现类时其实不用重写该抽象方法, 也就不算作抽象方法
day08
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
        // 静态成员变量
    static String pathSeparator: 路径分隔符的字符串形式
    static char pathSeparatorChar: 路径分隔符的char形式
            Windows系统是 分号;  
        Linux系统是 冒号:
    static String separator: 文件名称分隔符的字符串形式
    static char separatorChar: 文件名称分隔符的char形式
            Window系统是 反斜杠\
        Linux系统是 正斜杠/
    // 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
        File File(String pathname): 根据 路径字符串 封装一个File对象
        File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
        File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
        // 常用获取方法
    String?getAbsolutePath(): 返回此File的绝对路径名字符串
    String?getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
    String?getName(): 获取File对象的文件名或目录名
    long?length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
代码实例:
[AppleScript] 纯文本查看 复制代码
public static void main(String[] args) {
        // String getAbsolutePath(): 返回此File的绝对路径名字符串
        File f1 = new File("a.txt");
        System.out.println(f1.getAbsolutePath());  // File对象是相对路径, 该方法可以获取到绝对路径

        // String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
        System.out.println(new File("a.txt").getPath());  // 创建对象时是什么路径, 获取的就是什么
        System.out.println(new File("d:\\a.txt").getPath());

        // String getName(): 获取File对象的文件名或目录名
        File f3 = new File("a\\b\\c\\d.txt");
        System.out.println(f3.getName());

        // long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
        File f4 = new File("day08\\src\\com\\itheima\\test02\\Test.java");  // 相对路径
        System.out.println(f4.length());  // 1431
    }
}

    // 常用判断方法
        boolean?exists(): 判断File对象代表的文件或目录是否实际存在
        boolean?isDirectory(): 判断File表示的是否为目录
        boolean?isFile(): 判断File表示的是否为文件
代码实例:
[AppleScript] 纯文本查看 复制代码
public class Test {
    public static void main(String[] args) {
        // boolean exists(): 判断File对象代表的文件或目录是否实际存在
        File f1 = new File("day08\\src");
        System.out.println(f1.exists());

        // boolean isDirectory(): 判断File表示的是否为目录
        File f2 = new File("day08\\src\\com\\itheima\\test03");
        System.out.println(f2.isDirectory());

        // boolean isFile(): 判断File表示的是否为文件
        File f3 = new File("day08\\src\\com\\itheima\\test03\\Test.java");
        System.out.println(f3.isFile());
    }
}
        // 常用创建删除方法
        boolean?createNewFile(): 当文件不存在时, 创建一个新的空文件
        boolean?delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
        boolean?mkdir(): 创建File表示的目录
        boolean?mkdirs(): 创建File表示的多级目录
代码实例;
public static void main(String[] args) throws IOException {
        // 在当前的模块中创建a目录
       /* File dirA = new File("day08\\a");
        dirA.mkdir();

        // 在a目录中创建b目录
        File dirB = new File("day08\\a\\b");
        dirB.mkdir();*/

        // 以上两步可以合并为一步
        File dirAB = new File("day08\\a\\b");
        dirAB.mkdirs();

        // 在b目录中创建b.txt文件和c.txt文件
        File fileB = new File("day08\\a\\b\\b.txt");
        fileB.createNewFile();
        File fileC = new File("day08\\a\\b\\c.txt");
        fileC.createNewFile();

        // 删除c.txt文件
        fileC.delete();

        boolean result = new File("z:\\a").mkdirs();  // 磁盘不存在, 不会创建
        System.out.println(result);  // false
    }
}
        // 常用获取目录中内容的方法
        String[]?list(): 获取当前File目录下的所有子文件或目录的名字数组
        File[]?listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
        File[] listFiles(FileFilter filter): 通过File对象过滤, 返回文件过滤器过滤后的File对象数组
        File[] listFiles(FilenameFilter filter): 通过File对象的文件名过滤, 返回文件过滤器过滤后的File对象数组

java.io.FileFilter接口: 用于File对象的过滤器
        boolean accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入

java.io.FilenameFilter接口:
        boolean accept(File dir, String name): true则会将参数的File对象加入返回的File[], false则不加入

day09
IO流
字节输出流【OutputStream】
构造方法
public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。

写入字节数据到硬盘:
写入字节write(int b) 方法,每次可以写入一个字节数据,代码使用演示:
// 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
              // 写出数据
              fos.write(97); // 写入第1个字节
              fos.write(98); // 写入第2个字节
              fos.write(99); // 写入第3个字节
              // 关闭资源
        fos.close();
输出结果为:abc

写入字节数组:write(byte[] b),每次可以写出数组中的数据,代码使用演示:
// 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
              // 字符串转换为字节数组
              byte[] b = "黑马程序员".getBytes();
              // 写出字节数组数据
              fos.write(b);
              // 关闭资源
        fos.close();
        输出:黑马程序员

写出指定长度字节数组:write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节,代码使用演示:
// 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
              // 字符串转换为字节数组
              byte[] b = "abcde".getBytes();
                // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
        fos.write(b,2,2);
              // 关闭资源
        fos.close();
输出:cd

续写:
每次程序运行,创建输出流对象,都会清空目标文件中的数据。
public FileOutputStream(File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。  
public FileOutputStream(String name, boolean append): 创建文件输出流以指定的名称写入文件。  
file和name都是写入数据的目的地
append是续写开关,true,false
// 使用文件名称创建流对象
      
[AppleScript] 纯文本查看 复制代码
 FileOutputStream fos = new FileOutputStream("fos.txt",true);     
              // 字符串转换为字节数组
              byte[] b = "abcde".getBytes();
                // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
        fos.write(b);
              // 关闭资源
        fos.close();
换行:
// 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");  
              // 定义字节数组
              byte[] words = {97,98,99,100,101};
              // 遍历数组
        for (int i = 0; i < words.length; i++) {
                  // 写出一个字节
            fos.write(words);
                  // 写出一个换行, 换行符号转成数组写出
            fos.write("\r\n".getBytes());注意"\r\n"也是字符串,所以得转换成字节
        }
              // 关闭资源
        fos.close();
Windows系统里,每行结尾是 回车+换行 ,即\r\n;
Unix系统里,每行结尾只有 换行 ,即\n;
Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。


字节输入流【InputStream】
读取字节:read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1,代码使用演示:
      
[AppleScript] 纯文本查看 复制代码
  FileInputStream fis = new FileInputStream("read.txt");
              // 定义变量,保存数据
        int b ;
        // 循环读取
        while ((b = fis.read())!=-1) {                    b为读取到的数据
            System.out.println((char)b);               强转为char
        }
                // 关闭资源
        fis.close();


使用字节数组读取:read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1 ,代码使用演示:
FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
              // 定义变量,作为有效个数
        int len ;
        // 定义字节数组,作为装字节数据的容器   
        byte[] b = new byte[2]; 数组的长度为2,每次读取两个字节
        // 循环读取
      
[AppleScript] 纯文本查看 复制代码
 while (( len= fis.read(b))!=-1) {  
                   // 每次读取后,把数组变成字符串打印
            System.out.println(new String(b));
        }
                // 关闭资源
        fis.close();

输出结果:
ab
cd
ed
错误数据d,是由于最后一次读取时,只读取一个字节e,数组中,上次读取的数据没有被完全替换,所以要通过len ,获取有效的字节,代码使用演示:
  
[Java] 纯文本查看 复制代码
      FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
              // 定义变量,作为有效个数
        int len ;
        // 定义字节数组,作为装字节数据的容器   
        byte[] b = new byte[1024];或者是1024的倍数
        // 循环读取
        while (( len= fis.read(b))!=-1) {
                   // 每次读取后,把数组的有效字节部分,变成字符串打印
            System.out.println(new String(b,0,len));//  len 每次读取的有效字节个数
        }
                // 关闭资源
        fis.close();



字节流读取中文问题
GBK编码中, 一个汉字占用2个byte
UTF-8编码中, 一个汉字占用3个byte

字符输入流:
[AppleScript] 纯文本查看 复制代码
FileReader fr = new FileReader("a.txt");

// 一次读一个字符
int ch;  // 定义变量保存每次读到的字符
while ((ch = fr.read()) != -1) {
    System.out.print((char)ch);
}

// 一次读一个字符数组
char[] cs = new char[1024];
int len;
while ((len = fr.read(cs)) != -1) {
    String s = new String(cs, 0, len);
    System.out.print(s);
}

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


字符输出流: flush与close区别
区别:
        flush(): 刷新缓冲区 (将数据从内存中写入到磁盘)
        close(): 刷新缓冲区, 并释放资源. 关闭流后不能再用同一个流对象操作

Properties集合Properties存储数据和遍历:Properties双列集合,键和值都是 String 类型
java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable
        // 构造方法
        Properties(): 创建一个Properties集合
        // 可以使用Map接口中的方法
        // 特有成员方法
        Object setProperty(String key, String value): 保存/替换键值对
        String getProperty(String key): 通过键获取值. 键不存在返回null
        Set<String> stringPropertyNames(): 返回键的集合
        void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
        void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文),并写入注释
        void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
        void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)
代码实例:
从Properties到硬盘:
[AppleScript] 纯文本查看 复制代码
public class Test {
    public static void main(String[] args) throws IOException {
        // 创建Properties集合对象
        Properties properties = new Properties();

        // 添加键值对 setProperty(String key, String value)
        properties.setProperty("赵丽颖", "168");
        properties.setProperty("迪丽热巴", "165");
        properties.setProperty("古力娜扎", "160");

        // 创建文件字符输出流对象
//        FileWriter fw = new FileWriter("day09\\prop.properties");
        FileWriter fw = new FileWriter("day09\\prop.txt");

        // 将Properties集合中的数据, 写入到文件 store()
//        properties.store(fw, "");
        properties.store(fw, null);  // 第二个参数注释, 传递null也可以, 这样就不会出现空行注释

        // 关闭流
        fw.close();
    }
}
从硬盘到properties:
public class Test {
    public static void main(String[] args) throws IOException {
        // 创建Properties集合对象
        Properties properties = new Properties();

        // 创建文件字符输入流对象
        FileReader fr = new FileReader("day09\\prop.properties");

        // 从硬盘上读取到集合: load()
        properties.load(fr);  // 方法调用完毕后, 集合里面就有键值对了

        // 遍历集合
        Set<String> strings = properties.stringPropertyNames();
        for (String key : strings) {
            // 通过键获取值
            String value = properties.getProperty(key);
            System.out.println(key + "=" + value);
        }
    }
}

day10



file:///C:/Users/Administrator/AppData/Local/YNote/data/qq43AEA454F9E8FC8D3CE99A4053144AD8/5ab27db79d07448186f8b43fb33b9205/clipboard.png
缓冲流的原理:
        底层也是使用基本流(FileXxx)来读写
        但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高了程序效率
字节缓冲输出流: BufferedOutputStream
构造方法
BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流BufferedOutputStream(OutputStream out, int size): size是设置缓冲区大小
1.创建Fileoutputstream,构造方法中绑定要输出的目的地
2.创建Bufferedoutputstream,构造方法中传递Fileoutputsream对象,提高Fileoutputsream效率.
3.使用Bufferedoutputstream对象的方法write,把数据写入到内存缓冲区中
4.使用Bufferedoutputstream对象的方法flush,把内存缓冲区的数据刷新到文件中
5.释放资源.close(会调用flush方法刷新数据,第四部可以省略)
代码实例:
[AppleScript] 纯文本查看 复制代码
public static void main(String[] args) throws IOException {
BufferedOutputStream bo =
new BufferedOutputStream(newFileOutputStream("D:\\test.txt"));   
bo.write("我就是爱音乐,别让我停下来".getBytes());
        bo.close();}

字节缓冲输入流: BufferedInputStream
构造方法
        BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
        BufferedInputStream(InputStream in, int size): size为设置缓冲区大小
使用步骤:
     1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
     2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象, 提高FileInputStream效率
     3.使用BufferedInputStream对象中的方法 read(), 读取文件
     4.释放资源 close()
代码实例:
[AppleScript] 纯文本查看 复制代码
public static void main(String[] args) throws IOException {
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("D:\\test.txt"));
        int len;
        while((len=bis.read())!=-1){
            System.out.println(len);
        }
        bis.close();
//        或者:
//        byte[]bytes=new byte[1024];
//        int len;
//        while((len=bis.read(bytes))!=-1){
//            System.out.print(new String(bytes,0,len)); 将数组转换成字符串,从0开始转换,len:有效个数
//        }
//        bis.close();
    }

缓冲字符输出流: BufferedWriter(与字节缓冲输出流类似)
代码实例:
[AppleScript] 纯文本查看 复制代码
BufferedWriter bw=new BufferedWriter(new FileWriter("day10\\testBufferedWriter1.txt",true));
    for (int i = 0; i < 10; i++) {
        bw.write("传智播客");
        bw.newLine();换行也可以使用"\r\n"

    }
    bw.flush();
    bw.close();

}


缓冲字符输入流: BufferedReader
代码实例:
[AppleScript] 纯文本查看 复制代码
BufferedReader br=new BufferedReader(new FileReader("day10\\testBufferedWriter1.txt"));
//        String line;
//     while((line=br.readLine())!=null){    readline一次读一行返回的是一行的数据
//            System.out.println(line);
//        }
//        br.close();
//        或者:
        int line;
        char[] chars=new char[1024];
        while((line=br.read(chars))!=-1){
            System.out.println(new String(chars,0,line));
        }
        br.close();
    }


转换流字符编码和字符集
编码: 字符 -> 字节  'a' -> 97
解码: 字节 -> 字符  97 -> 'a'

编码表: 字符和二进制数字的对应规则

字符集和编码表: 字符集包含编码表
        ASCII字符集
                ASCII编码表
        ISO-8859-1字符集:
                Latin-1: 拉丁字符. 没有中文. 每个字符由1个byte组成
        GB字符集
                GB2312编码表: 每个字符由2个byte组成
                GBK编码表: 每个字符由2个byte组成
                GB18030编码表: 每个字符由1, 2, 4个byte组成
        Unicode
                UTF-8: ASCII字符占1个byte, 拉丁字符占2个byte, 中文占3个byte, Unicode辅助字符占4个byte
                UTF-16
                UTF-32

代码实例:
[AppleScript] 纯文本查看 复制代码
public static void main(String[] args) throws IOException {
        // 创建输入转换流
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day10\\我是GBK文件.txt"), "GBK");
        // 创建输出转换流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day10\\我是UTF_8文件.txt"), "UTF-8");

        // 循环读写: 一次读写一个字符char
        int ch;
        while ((ch = isr.read()) != -1) {
            // 读到的字符, 经过InputStreamReader已经按照GBK转换为正确的"你好"
            // 接下来交给OutputStreamWriter写出去, 写的时候会按照UTF-8转换为UTF-8的byte
            osw.write(ch);
        }

        // 刷新并释放资源
        isr.close();
        osw.close();
    }

序列化流(对象流)序列化和反序列化
序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中对象转字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象字节转对象
通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态
public class Person implements Serializable(被读写的对象的类, 必须实现 java.io.Serializable 接口, 否则会抛出 NotSerializableException)

[Java] 纯文本查看 复制代码
ArrayList<Person>list =new ArrayList<>();
list.add(new Person("张三",18));
list.add(new Person("李四",19));
list.add(new Person("张王五",20));
ObjectOutputStream op=new ObjectOutputStream(new FileOutputStream("day10\\list.txt"));
ObjectInputStream oi=new ObjectInputStream(new FileInputStream("day10\\list.txt"));
op.writeObject(list);
Object o = oi.readObject();
ArrayList<Person> list1 = (ArrayList<Person>) o;
for (Person person : list1) {
    System.out.println(person);

InvalidClassException异常: 原因和解决方案
serialVersionUID序列号的作用:
        序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
        该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化
        当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException

为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是一样的
补充: IDEA设置生成序列版本号:
Setting -> Editor -> Inspections -> Java -> Serialization issues -> 勾选Serializable class without 'serialVersionUID'

打印流
可以改变输出语句的目的地(打印流的流向)
输出语句默认在控制台上输出
使用system.setout改变输出语句的目的地改为参数中传递打印流的目的地
代码实例:
[Java] 纯文本查看 复制代码
System.out.println("我是在控制台上输出");
PrintStream p=new PrintStream("目的地.txt");
System.out.println("我在打印流的目的地中输出");
p.close();








欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2