IO流

一、对象流
对象流 序列化 公共流(节点流)
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 当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容