IO流

作者: 某某宝 | 来源:发表于2019-05-09 22:33 被阅读0次

    一、对象流
    对象流 序列化 公共流(节点流)
    ObjectInputStream 反序列化输入流 新增方法 readObject()
    ObjectOutputStream 序列化输出流 新增方法 writeObject()
    注意:
    先序列化后反序列化
    输入写出的顺序必须一致
    不是所有的类都能够序列化 实现接口java.io.Serializable
    不是所有的属性都需要序列化 transient
    如果父类实现了序列化接口,子类中所有的内容都与能力序列化
    如果子类实现了序列化接口,但是父类没有实现,子类只能序列化自己的内容
    静态的内容不能序列化

    public static void write(String dest,ArrayList<Student> stu) throws FileNotFoundException, IOException {
        ObjectOutputStream oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
        for(int i=0;i<stu.size();i++) {
            System.out.println(stu.get(i));
            oos.writeObject(stu.get(i));            
        }
        oos.close();
    }
    public static boolean read(String src,int size) throws FileNotFoundException, IOException, ClassNotFoundException {
        ObjectInputStream ois=new ObjectInputStream(new BufferedInputStream(new FileInputStream(src)));
        ArrayList<Student> stu=null;
        for(int i=0;i<size;i++) {           
            if("李凯".equals(((Student)(ois.readObject())).getName()))
                return true;
            }
        ois.close();
        return false;
    }   
    

    二、、容器: 可变长的,任意数据类型的数据的集合
    1、数组:
    定长的
    数据类型相同
    有序,有索引,根据索引查询效率高
    缺点:数组长度一旦确定,不可改变,因此,不灵活:容量需要事先定义好,不能随 着需求的变化而扩容。
    2、容器类
    数组远远不能满足我们的需求。我们需要一种灵活的,容量可以随时扩充的容 器来装载我们的对象。这就是容器类,或者叫集合框架。
    手写简单容器:
    自定义容器类 : 只存储字符串,实现随着内容的增删长度可变

    class MyContainer{
        private String[] arr=null;
        private int size;   
        public MyContainer() {
            arr=new String[0];
        }   
        public String getArr(int index) {
            if(index<0||index>=size) {
                throw new ArrayIndexOutOfBoundsException();
            }
            return arr[index];
        }
        public int getSize() {
            return size;
        }   
        /*
         * 修改功能
         */
        //添加
        public void add(String str) {
            String[] temp=arr;
            arr=new String[size+1];
            for(int i=0;i<size;i++) {
                arr[i]=temp[i];         
            }
            arr[size]=str;
            size++;
        }
        //删除
        public void remove(int index) {
            if(index<0||index>=size) {
                throw new ArrayIndexOutOfBoundsException();
            }
            String[] temp=arr;
            arr=new String[size-1];
            for (int i = 0; i < temp.length; i++) {
                if(i<=index) {
                    if(i==index)
                        continue;
                    arr[i]=temp[i];
                }else {
                    arr[i-1]=temp[i];               
                }
            }
            size--;     
        }   
    }
    

    3、集合 Collection
    成员方法:
    注意:
    容器可以存储任意类型的数据
    泛型中的数据类型只能为引用类型,基本数据类型会发生非自动装箱
    遍历:
    增强for
    迭代器

    Collection col1 = new ArrayList();
    Collection col2 = new ArrayList();
    Collection<String> col3 = new ArrayList();
    col1.add("123");        
    col1.add("567");
    // boolean isEmpty() 如果此 collection 不包含元素,则返回 true。
    System.out.println(col2.isEmpty());
    // boolean addAll(Collection<? extends E> c)
    // 将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
    col2.addAll(col1);
    System.out.println(col2);
    // boolean contains(Object o)如果此 collection 包含指定的元素,则返回 true。
    System.out.println(col1.contains("123"));
    // void clear() 移除此 collection 中的所有元素(可选操作)。
    col1.clear();
    System.out.println(col1.isEmpty());
    // removeAll(Collection)
    //移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
    System.out.println(col2.removeAll(col1));
    System.out.println(col2);
    // int size() 返回此 collection 中的元素数。
    System.out.println(col1.size());
    // Object[] toArray() 返回包含此 collection 中所有元素的数组。        
    Object[] a = col1.toArray();
    System.out.println(Arrays.toString(a));
    //迭代器
    Iterator it = col2.iterator();      
    if(it.hasNext()){           
        System.out.println(it.next());
    }       
    //增强for
    for(Object o:col2)
        System.out.println(o);
    

    4、 List接口:有序的,可重复的
    新增功能:新增了一些关于索引操作的方法
    接口遍历:
    for普通for
    for .. each
    迭代器

    List<String> list=new ArrayList();
    list.add("钢铁侠");
    list.add("雷神");
    list.add("鹰眼");
    list.add("快银");
    list.add("浩克");
    list.add("美国队长");
    list.add("洛基");
    list.add("灭霸");
    System.out.println(list);
    //remove(ele|index) 如果数据和索引都是整数,默认把参数认为index
    list.remove(3);
    System.out.println(list);       
    //List<E> subList(int fromIndex, int toIndex)    toIndex取不到
    System.out.println(list.subList(1, 3));
    boolean flag=false;
    for(int i=0;i<list.size();i++) {
        if(list.get(i).equals("灭霸")) {
    list.add("惊奇队长");
        }
    }
    System.out.println(list);
    for(String str:list) {
        if(str.equals("灭霸")) {
            flag=true;                          
        }
    }
        if(flag) {
            list.add("惊奇队长");
            flag=false;
        }
    System.out.println(list);   
        for(Iterator it=list.iterator();it.hasNext();) {
            if(it.next().equals("灭霸"))
                flag=true;          
            }
        if(flag) {
            list.add("惊奇队长");
        }
    System.out.println(list);
    

    5、ArrayList :有序的可重复的
    底层:数组实现,进行动态扩容,每次使用copyOf方法进行扩容,每次扩容后的容量是原容量的1.5倍
    优点:随机获取或者遍历效率高
    缺点:增删效率低
    线程不安全的,效率高
    Vector: 向量
    底层:数组实现,使用copyOf方法进行动态扩容,每次扩容后的容量是原容量的2倍
    线程安全的,效率低

    ArrayList<Person> al=new ArrayList<>();
    al.add(new Person(1,"大锤",108));
    System.out.println(al);
    System.out.println(al.indexOf(new Person(1,"大锤",108)));
    

    6、LinkedList
    底层:双向链表实现
    优点:做增删效率高
    缺点:查询和遍历效率低
    新增功能: 新增了一些操作与头部和尾部的方法

    LinkedList<String> ls=new LinkedList<String>();
    ls.add("小明");
    ls.add("小黄");
    ls.add("小花");
    System.out.println(ls);
    //void addFirst(E e)    将指定元素插入此列表的开头。 
    // void addLast(E e)  将指定元素添加到此列表的结尾。 
    ls.addFirst("1");
    ls.addLast("0");
    System.out.println(ls);
    // E element()  获取但不移除此列表的头(第一个元素)。 
    System.out.println(ls.element());
    

    自定义LinkedList容器类(单向链表)

    public class LinkedList05 {
        public static void main(String[] args) {
            //Test for MyLinkdeList
            MylinkedList myll=new MylinkedList();
            myll.add("assassin");
            myll.add("sabor");
            myll.add("berserker");
            myll.add("lancer");
            System.out.println(myll.getSize());
            System.out.println(myll.get(3));
        }
    }
    //自定义LinkedList容器类
    class MylinkedList{
        //链表头
        private Node head;
        //链表长度
        private int size;
        //constructor
        public MylinkedList() {}
        //获取长度
        public int getSize() {
            return size;
        }
        //获取第index个数据
        public String get(int index) {
            Node temp=head;
            for (int i = 0; i < size; i++) {
                if(i==index) {
                    return temp.getData();
                }else {
                    temp=temp.getAddress();
                }
            }
            return null;
        }
        //添加元素
        public void add(String str) {
            //先创建一个新节点
            Node newNode=new Node(str,null);
            if(head==null) {
                head=newNode;
                size++;
            }else {
                Node temp=head;
                for (int i = 0; i < size; i++) {
                    if(temp.getAddress()==null) {
                        temp.setAddress(newNode);
                    }else {
                        temp=temp.getAddress();
                    }               
                }
                size++;
            }   
        }   
    }
    //节点类,模拟单向链表,存储数据和地址
    class Node{
        private String data;
        private Node address;   
        public Node() { }   
        public Node(String data, Node address) {
            super();
            this.data = data;
            this.address = address;
        }
        public String getData() {
            return data;
        }
        public void setData(String data) {
            this.data = data;
        }
        public Node getAddress() {
            return address;
        }
        public void setAddress(Node address) {
            this.address = address;
        }   
    }
    

    7、 Set 接口
    无序的 不可重复
    放入数据的顺序和内部真实存储的顺序不一致,内部有自己的存储顺序,一旦确定了存储顺序不会发生改变

    Set set=new HashSet();
    set.add(1);
    set.add(true);
    set.add("qwer");
    System.out.println(set);
    //运行结果[1, qwer, true]
    

    8、HashSet
    底层:哈希表结构(数组+链表+红黑树)
    优点:查询,添加,删除,修改效率高
    缺点:无序
    注意:
    如果两个对象的hashcode值不相同,两个对象肯定不相同,如果值相同,可能不是相同对象,可以是相同对象

    HashSet<Person> hs=new HashSet<Person>();
    hs.add(new Person(1,"张三",10));
    hs.add(new Person(3,"赵四",22));
    hs.add(new Person(3,"赵四",22));
    System.out.println(hs);
    //结果:
    //[Person [id=3, name=二锅头, age=18], 
    //Person [id=3, name=赵四, age=22],
    // Person [id=3, name=赵四, age=22]] 
    

    对对象类型数据进行去重:要重写hashCode和equals方法
    先比较hashCode,如果值不同,不会调用equals方法,如果值相同才会调用equals方法

    //重写hashCode和equals方法后运行结果:
    //[Person [id=3, name=二锅头, age=18], 
    // Person [id=3, name=赵四, age=22]] 
    

    9、TreeSet
    底层:红黑树
    优点:升序排序
    存放具有可比性的引用类型数据

                TreeSet<Integer> ts=new TreeSet<Integer>();
            ts.add(1);      
            ts.add(2);
            ts.add(3);
            System.out.println(ts);
    

    TreeSet要求加入的所有元素都可以相互比较大小;可以控制比较位置来决定排序方向;hashset只能比较可相等不能比较大小
    可以通过元素本身的类实现Comparable来自我解决

        @Override
        public int compareTo(Object o) {
            if(this.id==((Person)o).getId()) {
                return 0;
            }else if (this.id>((Person)o).getId()) {
                return -1;
            }else {
                return 1;
            }       
        }
    

    重写之后可以使用自定义对象Person

                TreeSet<Person> tsp=new TreeSet<Person>();
            tsp.add(new Person(1,"张三",10));     
            tsp.add(new Person(3,"赵四",22));
            tsp.add(new Person(3,"赵四",22));
            System.out.println(tsp);
    

    三、Map

    1、Map

    实现Map接口的类用来存储键(key)-值(value) 对。

    Map类中存储的键-值对通过键来标识,所以键值不能重复。

    键值对:

    存储的数据都是key,value键值对形式的,二者之间为映射关系

    key 可以任意数据类型 无序的,唯一的 -->set结合

    value 可以任意数据类型 无序的 ,不唯一的 -->Collection结合

    一个key只能对应一个value(value可以为集合,集合中存储多个数据)

    使用:

    Map<String, Integer> map=new HashMap();
     //添加元素 map.put("胡歌", 30); 
    map.put("胡歌", 28);//重复元素会覆盖,因为是按键值判断 
    map.put("刘德华", 50); 
    System.out.println(map); 
    //V get(Object key) 
    System.out.println(map.get("胡歌")); 
    //boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
     //boolean containsValue(Object value)
     System.out.println(map.containsKey("胡歌"));
     //remove(key) System.out.println(map.remove("胡歌"));
    

    运行结果

    {刘德华=50, 胡歌=28} 28 true 28
    

    2、HashMap

    HashSet是由HashMap维护的,但是HashMap是键值对的形式,初始容量是16,加载因子是0.75

    底层是hash表的结构

    HashMap的key如果是引用数据类型的对象,做去重要重写hashCode和equals

    如果想要实现value去重,需要手动判断

     HashMap<Person, Integer> hashmap=new HashMap();   
    hashmap.put(new Person(1,"赵",20),01);  
    hashmap.put(new Person(2,"钱",22),3);    System.out.println(hashmap);   
    

    3、TreeMap

    TreeSet是由TreeMap的key维护的,使用方式相同,但是是键值对的形式

    //创建TreeMap对象 TreeMap<Person,Integer> tm1=new TreeMap(); 
    //或调用有参构造器,传入比较器 TreeMap<Person,Integer> tm2=new TreeMap((o1,o2)->(((Person)o1).getAge()-((Person)o2).getAge()); tm1.put(new Person(1,"赵",20),01); tm2.put(new Person(2,"钱",22),3);
    

    4、Properties

    HashTable的子类,key和value都是string

    Properties pp=new Properties(); // void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。 pp.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties01")); System.out.println(pp.stringPropertyNames());
    

    四、注意点:
    1、继承关系:Collection,Set,List,Map都是接口,不能实例化,使用其实现类创建对象
    2、ConcurrentModificationException 当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

    相关文章

      网友评论

          本文标题:IO流

          本文链接:https://www.haomeiwen.com/subject/ftrnoqtx.html