javaday11

目录

Day11---IO2+泛型+集合. 1

1       IO综合练习. 1

1.1      练习1:文件复制. 1

1.2      练习2:批量读写. 1

2       序列化 / 反序列化. 1

2.1      概述. 1

2.2      特点/应用场景. 1

2.3      ObjectOutputStream1

2.4      ObjectInputStream1

2.5      练习1:将学生信息序列化至磁盘【序列化】. 1

3       泛型. 1

3.1      概念. 1

3.2      作用. 1

3.3      泛型声明. 1

3.4      常用名称. 1

3.5      用途:编译时类型检查. 1

3.6      用途:代码通用性更强. 1

4       Collection接口. 1

4.1      概述. 1

4.2      集合的继承结构. 1

4.3      常用方法. 1

4.4      练习1:测试常用方法. 1

5       List接口. 1

5.1      概述. 1

5.2      特点. 1

5.3      常用方法. 1

5.4      练习1:测试常用方法. 1

6       ArrayList1

6.1      概述. 1

6.2      创建对象. 1

6.3      练习1:测试常用方法. 1

7       LinkedList1

7.1      概述. 1

7.2      常用方法. 1

7.3      练习1:测试迭代器遍历. 1

8       扩展. 1

8.1      BIO、NIO、AIO的区别. 1

8.2      数组和链表区别. 1

 

Day11---IO2+泛型+集合

1   IO综合练习

1.1   练习1:文件复制

创建day11工程,

创建cn.tedu.io包

创建Test1_Copy.java

package cn.tedu.io;

 

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Scanner;

 

//测试文件的复制

public class Test1_Copy {

       public static void main(String[] args) {

              //1、接收键盘输入源文件路径   和    目标文件路径

              String fromStr = new Scanner(System.in).nextLine();

              File from = new File(fromStr);

             

              String toStr = new Scanner(System.in).nextLine();

              File to = new File(toStr);

             

              //2、调用copy()完成复制

              copy(from,to);

       }

 

       //复制文件

       public static void copy(File from, File to) {

              InputStream in = null;//声明in变量,保证finally可用

              OutputStream out = null;//声明out变量,保证finally可用

              try {

                     //1、高效读取from文件

                     in = new BufferedInputStream(new FileInputStream(from));

                    

                     //2、高效写出到to文件

                     out = new BufferedOutputStream(new FileOutputStream(to));

                    

                     //3、正式开始 边读边写

                     int b = 0;//定义变量,记录读取到的数据

                     while( ( b = in.read() )  != -1) {

                            out.write(b);//读到一个字节就写出一个字节

                     }

                    

                     System.out.println("文件复制完成...");

                    

              } catch (Exception e) {

                     System.out.println("文件复制失败...");

                     e.printStackTrace();

              }finally {//保证资源一定会关闭

                     //4、关闭资源

                     try {

                            in.close();

                     } catch (IOException e) {

                            e.printStackTrace();

                     }

                     try {

                            out.close();

                     } catch (IOException e) {

                            e.printStackTrace();

                     }

              }

             

       }

 

 

}

1.2   练习2:批量读写

package cn.tedu.io;

 

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Scanner;

 

//批量读写

public class Test2_Copy2 {

       public static void main(String[] args) {

              // 1、接收键盘输入源文件 路径 和 目标文件路径

              String fromStr = new Scanner(System.in).nextLine();// D:\teach\1.txt

              File from = new File(fromStr);

 

              String toStr = new Scanner(System.in).nextLine();// D:\teach\222.txt

              File to = new File(toStr);

 

              // 2、调用copy()完成复制

              copy(from, to);

       }

 

       // 复制文件

       private static void copy(File from, File to) {

              InputStream in = null;// 声明in变量,保证finally可用

              OutputStream out = null;// 声明out变量,保证finally可用

              try {

                     // 1、高效读取from文件

                     in = new BufferedInputStream(new FileInputStream(from));

 

                     // 2、高效写出到to文件

                     out = new BufferedOutputStream(new FileOutputStream(to));

 

                     // 3、正式开始 边读边写

                     int b = 0;// 定义变量,记录读取到的数据

                    

                     //字节数组,提高单字节读写效率,底层数组默认大小是8*1024

//1024字节=1KB 

                     byte[] bs = new byte[8*1024];

                    

                     while ((b = in.read(bs)) != -1) {

                            out.write(bs);// 读到一个字节就写出一个字节

                     }

 

                     System.out.println("文件复制完成...");

 

              } catch (Exception e) {

                     System.out.println("文件复制失败...");

                     e.printStackTrace();

              } finally {// 保证资源一定会关闭

                     // 4、关闭资源

                     try {

                            in.close();

                     } catch (IOException e) {

                            e.printStackTrace();

                     }

                     try {

                            out.close();

                     } catch (IOException e) {

                            e.printStackTrace();

                     }

              }

 

       }

}

2   序列化 / 反序列化 

2.1   概述

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。

在序列化期间,对象将其当前状态写入到临时或持久性存储区。

以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

序列化:利用ObjectOutputStream,对象的信息,按固定格式转成一串字节值输出并持久保存到磁盘化。

反序列化:利用ObjectInputStream,读取磁盘中序列化数据,重新恢复对象。

 

2.2   特点/应用场景

1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。

2、 不需要序列化的数据可以被修饰为static的,由于static属于类,不随对象被序列化输出。

3、 不需要序列化的数据也可以被修饰为transient临时的,只在程序运行期间,在内存中存在不会被序列化持久保存。

4、 在反序列化时,如果和序列化的版本号不一致时,无法完成反序列化。

5、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。

6、 常用于服务器之间的数据传输,序列化成文件,反序列化读取数据。

7、 常用于使用套接字流在主机之间传递对象。

2.3   ObjectOutputStream

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。

ObjectOutputStream(OutputStream out)
          创建写入指定 OutputStream 的 ObjectOutputStream。

void writeObject(Object obj)

          将指定的对象写入 ObjectOutputStream。

2.4   ObjectInputStream

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectInputStream(InputStream in)

          创建从指定 InputStream 读取的 ObjectInputStream。

Object readObject()

      从 ObjectInputStream 读取对象,读取序列化数据。

2.5   练习1:将学生信息序列化至磁盘【序列化】

package cn.tedu.seri;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

 

//对象的序列化反序列化

public class Test3_Serializable {

       public static void main(String[] args) {

//           method();//对象的序列化

              method2();//对象的反序列化

       }

       //对象的反序列化:指从磁盘中加载被序列化过的文件,变成Java对象的过程  -- 读取

       //要求:1、类必须有可序列化的标志,实现接口    2、可序列化的类必须有唯一的versionId才能反序列化成功

       private static void method2() {

              try {

                     //1、创建ObjectInputStream对象

                     ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\teach\\1.txt"));

                    

                     //2、反序列化--恢复成Student对象

                     Student s = (Student) in.readObject();//-向下转型-把父类类型转成子类类型-强转

                     System.out.println(s);//默认显示地址值,重写toString()看属性值

             

                     //3、关闭资源

                     in.close();

                    

              } catch (Exception e) {

                     e.printStackTrace();

              }

       }

      

       //对象的序列化:指把程序中产生的对象永久保存到磁盘中 -- 写出

       private static void method() {

              try {

                     //1、创建Student对象

                     Student s = new Student("jack",20,"BJ","java");

                    

                     //2、序列化

                     ObjectOutputStream out =

                                   new ObjectOutputStream(new FileOutputStream("D:\\teach\\1.txt"));

                     out.writeObject(s);

                    

                     //3、关闭资源

                     out.close();

                    

              } catch (Exception e) {

                     e.printStackTrace();

              }

             

       }

}

//创建Student类

//4、想要完成序列化,类必须有标志,实现序列化接口,接口里是空实现,只是用来做标志

class Student implements Serializable{

      

       private static final long serialVersionUID = 1L;

 

       //构造方法:source-倒数第三个-ok

       public Student() { }

       public Student(String name, int age, String addr, String subject) {

              super();

              this.name = name;

              this.age = age;

              this.addr = addr;

              this.subject = subject;

       }

      

       private String name;

       private int age;

       private String addr;

       private byte gender;

       private String subject;

       private byte snum;

   

       //get()/set()

       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 getAddr() {

              return addr;

       }

       public void setAddr(String addr) {

              this.addr = addr;

       }

       public byte getGender() {

              return gender;

       }

       public void setGender(byte gender) {

              this.gender = gender;

       }

       public String getSubject() {

              return subject;

       }

       public void setSubject(String subject) {

              this.subject = subject;

       }

       public byte getSnum() {

              return snum;

       }

       public void setSnum(byte snum) {

              this.snum = snum;

       }

      

       //默认显示地址值,重写toString()看属性值

       @Override

       public String toString() {

              return "Student [name=" + name + ", age=" + age + ", addr=" + addr + ", gender=" + gender + ", subject="

                            + subject + ", snum=" + snum + "]";

       }

      

}

 

3   泛型

3.1   概念

public class LinkedList<E>

    extends AbstractSequentialList<E>

    implements List<E>, Deque<E>, Cloneable, java.io.Serializable{}

public interface Deque<E> extends Queue<E> {}

public interface Queue<E> extends Collection<E> {}

public interface Collection<E> extends Iterable<E> {}

我们上面的代码中出现的<?>是什么东西呢 。它叫泛型,常用来和集合对象一同使用,所以我们在开始学习集合之前,必须先了解下什么是泛型。而且泛型概念非常重要,它是程序的增强器,它是目前主流的开发方式。

泛型是(Generics)JDK1.5 的一个新特性,其实就是一个『语法糖』。

本质上就是编译器为了提供更好的可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓『泛型』的概念的。

3.2   作用

l  通过泛型的语法定义,约束集合元素的类型,编译器可以在编译期提供一定的类型安全检查,避免运行时才暴露bug。

l  代码通用性更强,后面有案例

l  泛型可以提升程序代码的可读性,但它只是一个语法糖(编译后这样的东西就被删除,不出现在最终的源代码中),对于JVM运行时的性能是没有任何影响的。

3.3   泛型声明

泛型可以在接口、方法、返回值上使用:

java.util.List泛型接口/类:

public interface Collection<E> {}

泛型方法的声明:

public <E> void print(E e) {}

在方法返回值前声明了一个<E>表示后面出现的E是泛型,而不是普通的java变量。

3.4   常用名称

l  E - Element (在集合中使用,因为集合中存放的是元素)

l  T - Type(Java 类)

l  K - Key(键)

l  V - Value(值)

l  N - Number(数值类型)

l  ? - 表示不确定的java类型

3.5   用途:编译时类型检查

package cn.tedu.generic;

 

import java.util.ArrayList;

import java.util.List;

 

//泛型案例

public class Test4_Generic {

    public static void main(String[] args) {

       //数组里的元素都是相同类型

       int[] a = {1,2,3,4,5};

      

       List list = new ArrayList();

       //向集合中添加元素

       list.add("rose");

       list.add(9.9);

       list.add(10);

      

       //如果我想要把数据都获取出来

       //增强for循环 foreach结构  1 2:3  3是要遍历的数据   1是数据的类型   2就是个变量名

       for(Object obj :   list) {

           String s = (String)obj;//-向下转型,把obj是Object类型转成小类型String类型-强转

           System.out.println(s);

       }

      

//     Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String

//以上的错误就是因为,编译时期不报错,运行时期才说类型转换异常。

      

       //1、<?>是泛型的标志,?的类型必须是引用类型 --包装类类型才是引用类型基本类型

       //2、泛型常用于类型检查

       List<Integer> list2 = new ArrayList<>();

       list2.add(100);

      

      

    //3、由于list集合已经要求了元素的类型必须是String类型,所以加入的元素只要不是String各类型都会报错

       //好处:把运行时期才会报的ClassCastException提前到了编译时期

//     list2.add(“10”);

      

    }

   

}

 

3.6   用途:代码通用性更强

传统方式通过重载多态实现,方法同名,参数类型不同。

package cn.tedu.generic;

 

import java.util.ArrayList;

import java.util.List;

 

//泛型案例

public class Tes5_Generic2 {

    public static void main(String[] args) {

       Integer[] a = {100,200,300,400,500};

       print(a);

      

       Double[] b = {1.1,2.2,3.3,4.4,5.5};

       print(b);

       //这样不好,每次要打印不同类型的数据,都需要提供对应的print()

      

    }

 

    private static void print(Double[] b) {

       for (Double d : b) {

           System.out.println(d);

       }

    }

 

    private static void print(Integer[] a) {

       for (Integer i : a) {

           System.out.println(i);

       }

    }

   

}

泛型方式

package cn.tedu.generic;

 

//泛型案例

public class Tes5_Generic2 {

    public static void main(String[] args) {

       Integer[] a = {100,200,300,400,500};

       print(a);

      

       Double[] b = {1.1,1.2,1.3};

       print(b);

      

       String[] c = {"","","","",""};

       print(c);

      

    }

 

    //2、写出通用代码,不需要像以前一样,new个[],就需要提供对应的print()

    private static <E> void print(E[] e) {

       for (E e2 : e) {

           System.out.println(e2);

       }

    }

   

}

4   Collection接口

4.1   概述

英文名称Collection,

是用来存放对象的数据结构。

其中长度可变,而且集合中可以存放不同类型的对象。

并提供了一组操作成批对象的方法。

数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。

4.2   集合的继承结构

 

Collection接口

-- List接口  : 数据有序,可以重复。

   -- ArrayList子类

   -- LinkedList子类

-- Set接口  : 数据无序,不可以存重复值

   -- HashSet子类

-- Map接口  : 键值对存数据

-- HashMap

Collections工具类

4.3   常用方法

boolean add(E e):添加元素。

boolean addAll(Collection  c):把小集合添加到大集合中 。

boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。

boolean isEmpty() :如果此 collection 没有元素,则返回 true。

Iterator<E> iterator():返回在此 collection 的元素上进行迭代的迭代器。

boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。

int size() :返回此 collection 中的元素数。

Objec[] toArray():返回对象数组

4.4   练习1:测试常用方法

package cn.tedu.collection;

 

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collection;

import java.util.Iterator;

 

 

//测试collection接口

public class Test6_Collection {

      

       public static void main(String[] args) {

              //1、创建Collection对象

              //a、Collection是集合的层次结构的父接口,存放的都是对象,这些对象也叫元素,默认是Object

              Collection<String> c = new ArrayList<>();

             

              //2、常用方法

              c.add("tony");

              c.add("hanmeimei");

              c.add("lilei");

              c.add("xiongda");

              c.add("xionger");

//           c.clear();

              System.out.println(c);

//          

              System.out.println(  c.contains("lilei")  );

              System.out.println(  c.hashCode() );

              System.out.println(  c.isEmpty() );

              System.out.println(  c.equals("tony") );

              System.out.println(  c.isEmpty() );

              System.out.println(  c.remove("hanmeimei")  );

              System.out.println(c);

             

              System.out.println(  c.size() );

              System.out.println(  Arrays.toString(  c.toArray()  ) );

//          

              System.out.println();

//          

              Collection<String> c2 = new ArrayList<>();

              c2.add("华安");

              c2.add("秋香姐");

             

              System.out.println(   c.addAll(c2)  );

              System.out.println(   c.containsAll(c2)  );

//           System.out.println(   c.removeAll(c2)  );//移除c2的元素

//           System.out.println(   c.retainAll(c2)  ); //移除c的元素

             

              System.out.println(c);

             

              //!!!迭代获取集合里的每个元素

//           Iterator<E> iterator() :返回在此 collection 的元素上进行迭代的迭代器。

              Iterator it = c.iterator();//想要获取集合中的每个元素iterator()

             

              while( it.hasNext() ) {//判断有没有元素

                     Object obj = it.next();//获取遍历到的元素

                     System.out.println(obj);

              }

             

             

       }

      

      

}

 

5   List接口

5.1   概述

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

5.2   特点

1、 数据有序

2、 允许存放重复元素

3、 元素都有索引

5.3   常用方法

ListIterator<E> listIterator()

          返回此列表元素的列表迭代器(按适当顺序)。

 ListIterator<E> listIterator(int index)

          返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

 void add(int index, E element)

          在列表的指定位置插入指定元素(可选操作)。

 boolean addAll(int index, Collection<? extends E> c)

          将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

 List<E> subList(int fromIndex, int toIndex)

     返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

E get(int index)

          返回列表中指定位置的元素。  

int indexOf(Object o)

          返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

5.4   练习1:测试常用方法

package cn.tedu.collection;

 

import java.util.ArrayList;

import java.util.List;

import java.util.ListIterator;

 

//测试List接口

public class Test7_List {

 

    public static void main(String[] args) {

       //1、创建对象

       //List是接口

       List<Integer> list = new ArrayList<>();

      

       //2、常用方法

       list.add(100);

       list.add(101);

       list.add(102);

       list.add(103);

       list.add(102);

       list.add(105);

      

       System.out.println(list);

      

//     list.clear();

       System.out.println(list.contains(100));

       System.out.println(list.equals(101));

       System.out.println(list.hashCode() );

       System.out.println( list.isEmpty() );

       System.out.println(list.remove(2) );

       System.out.println(list.size() );

       System.out.println(list.toArray() );

      

       //特有方法

       System.out.println(list+"======");

       System.out.println( list.indexOf(105) );

       System.out.println(list.lastIndexOf(102) );

       list.add(3,105);

       System.out.println(list);

       System.out.println(list.get(3));

       System.out.println(list.set(0,99));

       System.out.println(list);

       System.out.println(list.subList(2, 4));//含头不含尾,类似于String.subString()

       System.out.println(list);

      

       //遍历集合中元素

       //ListIterator继承了Iterator,并提供了更加完善的功能,除了正常向后遍历还增加了向前遍历的功能

       ListIterator it = list.listIterator();

       while(it.hasNext()) {

           Object obj = it.next();

           System.out.println(obj);

       }

      

       //TODO 子接口提供的遍历方式-如:向前遍历

    }

}

 

 

6   ArrayList

6.1   概述

1)     存在于java.util包中。

2)     内部用数组存放数据,封装了数组的操作,每个对象都有下标。

3)     内部数组默认初始容量是10。如果不够会以1.5倍容量增长。

4)     查询快,增删数据效率会降低。

 

 

6.2   创建对象

new ArrayList():初始容量是10

6.3   练习1:测试常用方法

常用API,包括下标遍历,迭代器遍历

 

7   LinkedList

7.1   概述

双向链表,两端效率高。底层就是数组和链表实现的。

 

7.2   常用方法

add()

get()

size()

remove(i)

remove(数据)

iterator()

addFirst()  addLast()

getFirst()  getLast()

removeFirst()  removeLast()

7.3   练习1:测试迭代器遍历

双向链表:下标遍历效率低,迭代器遍历效率高

 

8   扩展

8.1   BIO、NIO、AIO的区别

阻塞IO,BIO 就是传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。

非阻塞IO,NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。

异步IO,AIO 是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,所以人们叫它 AIO(Asynchronous IO),异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。但目前还不够成熟,应用不多。

8.2   数组和链表区别

List是一个接口,它有两个常用的子类,ArrayList和LinkedList,看名字就可以看得出一种是基于数组实现另一个是基于链表实现的。

数组ArrayList遍历快,因为存储空间连续;链表LinkedList遍历慢,因为存储空间不连续,要去通过指针定位下一个元素,所以链表遍历慢。

数组插入元素和删除元素需要重新申请内存,然后将拼接结果保存进去,成本很高。例如有100个值,中间插入一个元素,需要数组重新拷贝。而这个动作对链表来说,太轻松了,改变一下相邻两个元素的指针即可。所以链表的插入和修改元素时性能非常高。

实际开发就根据它们各自不同的特点来匹配对应业务的特点。业务一次赋值,不会改变,顺序遍历,就采用数组;业务频繁变化,有新增,有删除,则链表更加适合。

 

posted @ 2020-05-25 16:11  白驼山庄庄主  阅读(94)  评论(0编辑  收藏  举报