集合与泛型


集合
    使用简单
    进阶:
        底层机制
        源码
        什么情况下用什么集合
        
    数组缺点:
        创建长度必须指定
        必须保持同一类型
        扩容/删除麻烦
    集合:
        动态保存任意多个对象object
        提供一系列简单操作对象的方法
        添加/删除简单
    
    集合的选择:
        一组对象:Collection接口
            允许重复List
                增删多LinkedList
                改查多ArrayList
            不允许重复Set
                无序HashSet
                有序LinkedHashSet
                排序TreeSet
        一组键值对:Map接口
            键无序HashMap
            键有序LinkedHashMap
            键排序TreeMap
            读取文件Properties
            
    Collection 单列集合,是接口,
        集合遍历方式:
            迭代器:
                继承了Iterable接口,迭代器
                所有实现Collection接口的集合类都有iterator()方法,返回一个iterator接口对象/迭代器
                iterator仅用于集合遍历,并不存放集合对象  iterator迭代器的hashNext方法与next方法
                快捷键itit   显示所有快捷键:ctrl+j
                注意:退出迭代器循环后,迭代器指向集合最后一个元素,如果要再次遍历,要重置迭代器(重新用一次iterator()方法)
            增强for循环
                【只能用于遍历】数组(底层是普通for)与集合(底层是迭代器)
                快捷键:I/iter
        存储
            可以存储object(不加泛型的情况下)
        常用方法:
            add            参数是对象,与for经常配合
            remove        参数是下标/指定对象
            contains   返回boolean
            size        
            isEmpty
            clear        清空
            addAll        参数是集合
            containsAll判断多个元素是否都存在,参数可以是集合
            removeAll    参数可以是集合
        分类:有很多,不止下面2个
            List接口,【有序】
                遍历:
                    迭代器
                    增强for循环
                    普通for+get方法
                存储:
                    可重复
                    有序,支持索引
                常用方法:
                    get方法,参数是索引
                    remove方法,参数是索引/对象
                    add        第一个参数是索引,第二个是对象,表示从哪里开始添加
                    addAll    第一个参数是索引,第二个是对象,表示从哪里开始添加
                    set        第一个参数是索引,第二个是对象,表示替换        与get配合,可以用于集合元素的交换(不用temp了)
                    indexOf            参数是对象,返回索引
                    lastIndexOf        参数是对象,返回索引
                    subList 参数是2索引,返回小集合,左闭右开
                    sort方法 参数是无,或比较器
                分类:有很多,不止下面3个
                    ArrayList类 jdk1.2
                        源码分析:
                            toString 继承的父类AbstractCollection类重写了toString,打印的是集合内容
                            底层是transient object数组实现,创建对象,无参容量默认0(jdk7默认10)
                                可以放所有元素(基本类型会先装箱),包括null,而且可以是多个
                                transient表示瞬间,短暂的,被修饰的 表示该属性不会被序列化
                                添加元素add方法,判断是否需要扩容,需要调用grow方法,不需要直接添加
                                    无参构造器,需要扩容,第一次扩容默认10,再次扩容,是1.5倍(10的)
                                    指定容量构造器,第一次指定容量,再次扩容,是1.5倍(指定容量的)jdk不一样,就不一样
                                    扩容是Arrays.copyOf方法
                                    每次add都要判断是否需要扩容(影响效率)
                                    debug可以看到扩容,但是注意:idea的debug调用的是toString,是简化的,可能看不到扩容
                                    看完整数据,要设置-settings-builddebugger-data views-java-
                                        Enable alternative view for。。与Hide null。。取消勾选
                            arraylist基本等同Vector,但是线程不安全,执行效率高,多线程不建议使用,
                                方法没有同步关键字,
                                有modCount,记录集合修改次数,多线程修改抛异常
                    Vector类  jdk1.0
                        源码分析:
                            底层也是对象数组;线程安全,效率不高
                            无参就是默认10,不够,2倍扩容
                    LinkedList类
                        源码分析:
                            底层是双向链表,增删效率高        
                                transient的size
                                实现了双向链表与双端队列的特点(first,last,内部类final Node(prev,item,next))
                                无参构造/以集合作为参数,链表不能指定长度
                            可以添加任意元素,元素可以重复,包括null,而且可以是多个
                            线程不安全,效率高
                        注意:remove==removeFirst默认删除第一个
                选择:
                    改查用arraylist  80%
                    增删用linkedlist
                    业务模块不同,集合也可以不同
            Set接口,【无序】
                遍历:
                    迭代器
                    增强for
                    不能用索引遍历
                存储:
                    无序,没有索引,虽然无序,但是取出顺序一定的,按地址哈希值取
                    不允许重复,最多一个null
                        add源码看如何确定是否重复:
                            得到哈希值-》哈希值运算放入数组-》已经有了,equals方法判断
                            -》相同,不添加;不相同,链表形式/红黑树添加            
                常用方法:
                    add        添加多次不会报错,但是还是只有一个
                    remove    参数是对象
                分类:有很多,不止下面2个
                    HashSet类
                        源码分析:
                            存储的是对象地址,对象存入后发生改变,其哈希值改变,存入位置自动变
                            实现了Set接口,实际上是hashMap(hashSet构造器),hashMap底层是数组+链表/红黑树
                            不允许添加重复元素
                            hashMap底层
                                add源码看如何确定是否重复:put方法,key变化,value一直是object,用于占位(Map-》Set)
                                    得到哈希值-》哈希值运算得到索引值,放入数组-》数组已经有了,equals方法判断
                                    -》相同,不添加;不相同,链表形式/红黑树添加    
                                    jdk8,一个链表满8(不是超过),且数组长度大于64(默认16),整体变为红黑树
                                        满8,但是数组长度(table)没有大于64,会先将table数组扩容
                                add底层:
                                    转put方法,执行hash方法,。得到key的哈希值,转putVal
                                    看table表是否存在(是否是null)不存在,转realize方法
                                    存在,计算下标值,判断数组的下标位置是否为null,是,放入;
                                    不是,判断是不是同一对象/equals,是,返回;判断是不是红黑树;
                                        判断在不在链表中,添加满8个,准备进行树化(不一定真正树化,可能是数组扩容)
                                    数组扩容有加载因子0.75,16长度,到12就开始扩容了,每次扩容2倍
                                        这个12包括加入在数组第一个位置/链表位置  都算size(不是只算数组的)
                                        数组扩容(之前的不变,之后来的重新取模?)
                        linkedHashSet
                            源码分析:
                                底层是LinkedHashMap,数组+双向链表  是Entry,静态内部类,继承了Node(也是静态内部类)
                                用链表维护元素次序,使其有序(第一个加入的指针指向下一个加入的节点【即使是不同hashcode值】)
                                不允许添加重复元素
                    TreeSet类
                        无序(String默认字典序从小到达)
                        与HashSet一样/HashTable一样,
                            但是可以排序,使用构造器,传入一个比较器(用匿名内部类)    底层add方法会自动调用
                        是key,所以加重复的是加不进去,而不是value的替换
                        底层是HashTable,是Entry
                        去重机制:构造器传入的比较器comparator的compare方法去重,没有传入比较器,
                                用对象实现的comparable接口的compareTo去重(字符串String是比较的内容)
                                适用TreeSet的对象应该要实现这个接口
    Map           双列集合,是接口
        源码:
            key不允许重复,哈希值和equals,可以为null(一个),常用String类作为key        (放入重复是替换value操作)
            value可以重复,可以为null(多个)
            key可以找到value,    
                2者真正是封装到一个Node里(Node实现了Entry接口,所以也叫一个Entry)
                为了方便程序员的遍历,还会创建 EntrySet的Set集合,该集合存放元素的类型Entry,而一个Entry对象就有k-v
                EntrySet是Map的内部类,entrySet中定义的类型是Map.EntrySet,但是实际上存放的还是HashMap$Node
                这是因为Node实现了Map.EntrySet接口
                Map.EntrySet接口实现了getKey与getValue方法方便遍历(Set实现了Collection接口)
                map.keySet获取set集合封装key        
                map.values获取value集合封装value
                    keySet与values也是map的内部类,实现了单例集合接口,方便遍历    
        常用方法:
            put 参数是2对象
            get 参数是key
            remove参数是key
            size
            isEmpty
            clear
            containsKey
            entrySet    存储Map.entry类型,其实完全可以换成Node
            keySet
            values
        遍历:
            keySet    增强for;迭代器
            entrySet 增强for;迭代器
        分类:
            HashMap类  jdk1.2
                源码:
                    无序(底层hash表与链表/红黑树)树化是jdk8才有的
                    继承父类的toString,打印内容
                    方法没有同步关键字,线程不安全,效率高
                    树结构删除不够多,就会剪枝=》重新转为链表
                LinkedHashMap类
                    有序
            HashTable类    jdk1.0
                源码:
                    键值都不能为null(抛异常)
                    线程安全,效率不高
                    put相同键是替换
                    底层是Entry数组(静态内部类),初始大小为11,加载因子0.75   阈值就是8
                    操作与hashMap基本相同
                Properties类
                    使用与hashtable类似,不能放null,也是替换
                    更多是从点Properties文件中加载数据到Properties对象,进行读取与修改
                        (点Properties文件通常作为配置文件,与IO流有关,一般保存用户名,密码,用于软编码)
            TreeMap类
                可以排序,底层是树,没有数组扩容一说
                底层是Entry
                重复会替换value
                
    Collections工具类
        静态方法操作Set,List,Map集合
        排序:
            reverse(List)反转
            shuffle(List)随机排序
            sort(List)    自然升序    (String就是字典序)
            sort(List,Compator)
            swap(List,int i,int j)交换i,j元素
        查找,替换
            max/min(Collection)返回自然顺序最大的/最小的(String就是字典序)
            max/min(Collection,compator)
            frequency(Collection,object)返回出现次数
            copy(List dest,List src)    复制集合(注意参数位置)
            replace(List,object oldVal,object newVal)使用新值替换所有旧值

泛型        jdk5才有   编译期会有擦除机制
    引入:
        传统方法不能对加入到内的集合进行约束,是不安全的
        传统方法遍历时,需要进行类型转换,如果集合的数据量较大,对于效率有影响
    主体:    
        泛型就是一种程序员指定的一种数据类型(可以是任意引用类型),主要功能之一是限制集合类型
        可以在类声明时,表示属性类型,方法参数类型,返回值类型(类模板)    编译时确定泛型  类中getClass方法可以得到
            可以有多个,接口也可以用泛型,任意字母都行,T表示Type,一般用T    
            iterator接口返回与泛型有关的迭代器(源码有关)
        可以传入泛型子类型
        不写泛型,其实也有泛型E,只不过默认是object
    自定义泛型
        泛型类 可以有多个泛型
            使用泛型的数组不能初始化(不能确定类型,不知道开辟多少空间)
            静态变量/静态方法中不能使用类的泛型    (泛型是对象创建确定,static是类加载时期)(这里的方法是普通静态方法)
            泛型类的类型,是在创建对象时确定的,没有指定,默认object
        泛型接口    可以有多个泛型
            静态属性/静态方法不能用接口的泛型
            泛型接口,泛型的确定在继承接口/实现接口时确定(都可以)
            没有指定,默认object
        泛型方法    可以有多个泛型
            泛型放修饰符后面,    方法参数/方法体内可以使用此类型,还可以使用类定义的泛型(定义就是用的,一个类型而已)
                泛型没有在修饰符后面,不是泛型方法,只是方法使用了泛型而已(还要注意,这个泛型要是定义过的!!!)
                                                                            (使用就要先定义)
            可以定义在泛型类/普通类
            泛型方法被调用时,确定类型    (正常传参,编译器会自动确定)    
        【注意】:
            【泛型静态】方法可以使用泛型方法中定义的泛型/泛型通配符,
            不能使用类/接口有但泛型方法没有定义的泛型
            泛型方法内的泛型符号可以与类泛型一致,但只是符号一致,完全是独立的,方法中用的是方法的【方法独立?应该是静态方法独立】
                (最好避免相同)
            
    泛型继承与通配符
        泛型不具备继承性        List l=new  ArrayList();是不对的
        
        泛型通配符
            支持任意类型泛型
            支持A及A子类,规定上限
            支持A及A父类,规定下限
            ?与object区别:?收到什么就是什么,不用向下转型,object还要转

你可能感兴趣的:(java)