集合

集合概念:
       用于存储多个对象的单一对象(容器)。存储的数据叫元素。元素都是引用类型。(容器内存储的都是对象的地址)

集合框架中包含多种接口,抽象类,实现类等,用此来满足我们,所需要的用于存储数据的数据结构。

JDK1.5新特性:
在1.5以前,容器可以存储Object的任何子类型,但是在对元素进行操作时,比如调用元素的方法等。我们必需知道元素的类型,因此在编程中增加了大量代码,来进行强制转换,增加了开发难度。因此1.5开始支持了一个新特性,叫泛型机制。用来规定容器中存储的元素的类型。此机制可以在编译期间就进行判断元素的类型。
===============================================================
泛型机制:
   (1)概念             
                jdk1.5版本开始使用的新特性,本质是进行"参数化类型",在类,接口,方法的定义上都可以使用,用来指定数据类型名的。
   (2)集合在定义时,可以用泛型机制来指定元素的类型,这样编译器在编译期间就可以进行检查元素类型是否匹配,
        避免了程序在运行时出现过多的错误  
   (3)集合框架中的所有类型(接口,抽象类,实现类)都是用了泛型机制    
   (4)泛型机制的参数只能传引用类型。 
   ==============================================================
集合与数组的区别:
   相同点:都是容器(数据结构),用来存储多个数据的,
   不同点:
            数组:可以存储基本数据类型
            集合:只能存储引用数据类型
            
 Collection与Collections的区别
   Collection:是集合的父接口,定义了集合框架中常用的抽象方法
   Collections:是集合的工具类,定义了很多用于操作集合对象的工厂/工具方法
   
Collection接口:
    是集合框架的顶级父接口,用来定义常用的抽象方法。子类需要实现相应的方法逻辑。
    
   常用方法:
    boolean add(E e):                                  将对象e添加到集合中
    int size() :                                            返回集合元素的个数
    boolean addAll(Collection c):            将集合c里的元素添加到此集合中
    void clear():                                      清空集合元素
    boolean contains(Object obj):            用于判断集合中是否存在于obj相同的元素
    boolean containsAll(Collection c)  :用于判断此集合中是否包含集合c中的所有元素
    boolean isEmpty():                                用于判断集合元素是否为空
    boolean remove(Object o)    :                用于移除集合中的某一元素
    boolean removeAll(Collection c):    用于移除此集合中与c中共有元素
    boolean retainAll(Collection c);         用于保留此集合中与c中共有元素 
    
子接口:List与Set,Queue
一、List:列表
     存储此接口实现类的数据,有序,可重复。能存储null元素,没有个数限制
                  有序:存储时与添加的顺序相关。有对应的索引/下标标记位置。从0开始
                  重复:存储的元素可以是同一个,也可以是对象内容相同不同对象。根据元素的equals方法进行判断
  
     常用方法:
     void add(int index,E element) :将某一元素,插入到此集合的下标index处。
     boolean remove(int index):     移除此集合中下标为index上的元素   
     E  get(int index)    :                         返回指定下标上的元素
     E set(int index,E newElement): 使用新元素newElement替换下标index上的元素,返回原元素。
     int indexOf(Object obj);             返回指定元素第一次出现的位置。如果没有,返回-1.       
     int lastIndexOf(Object obj):     返回此集合指定元素obj最后一次出现的下标。找不到返回-1.  
     List<E> subList(int fromIndex,int endIndex):截取此集合中的一部分,即截取子集,从fromIndex到endIndex包前不包后 
      PS:此方法在堆中产生了一个内部类SubList集合对象。此集合对象引用的父集的一部分。修改子集,会影响父集     
      
      数组与集合之间的转换
       1、集合转数组
      Object[] toArray()
      E[]  toArray(E[] e);
       2、数组转集合
      List Arrays.asList(数组参数);
            注意:数组转成的集合,不能进行增删操作,否则会出现运行时异常.可以进行替换操作,但是会数组变量有影响。
             如果想要成功进行增删操作,可以将元素,存入新的集合中。    
             
        Iterator:迭代器接口
        (1)迭代器的作用使用用来遍历集合元素。是一个接口。Collection接口提供一个方法 Iterator iterator()
        (2)Collection的实现类使用内部类定义了迭代器子类。
        (3)迭代器提供了统一的方法,用于遍历集合元素。
        
        常用方法:
        boolean hasNext():判断集合中是否有下一个元素
        E next():                   取出集合中的下一个元素   
        void remove():          
        在使用迭代器对集合进行遍历时,不能使用集合的移除方法移除集合的元素。必须使用迭代器自己提供的移除才行。
        
         增强for循环-foreach循环:
        for(元素类型 变量名:要遍历的集合或者数组){
           
        }
        实现原理:使用了迭代器思想
        与经典for循环的区别:
        (1)增强for循环中无法使用下标。
        (2)经典for循环中可以使用下标。跟下标有关的逻辑,随便写。
        
        List的三个实现类:
        (1)ArrayList
                 底层是基于动态数组的数据结构。有连续的索引,从0开始。           
        (2)LinkedList
                 底层是基于双链表的数据结构。每个节点上都有前后两个元素的引用。

        优缺点: 在执行get()/set()时,ArrayList的效率高,LinkedList需要移动指针,效率低
                    在增加/删除操作时,LinkedList效率高,ArrayList效率低(需要扩容,移动元素)。
        ps:当然,在元素的数量大的情况下,区别才明显。         

        (3)Vector:是一个比较古老的集合类型,线程安全,但是效率特别低。虽然安全,也不建议使用。
        
        List排序
       Comparable接口:        
       如何定义集合中元素之间的大小之分?
       我们需要在定义元素类型时实现Comparable接口,实现接口内的compareTo(Ee)。实现此接口的类型的对象之间可以进行比较。
 
 方法:
    int  compareTo(E e):
        比较规则: 
       (1)this与e比较,this-e,
                  如果大于0,返回大于0的一个数
                  如果等于0,   返回0
                  如果小于0,  返回小于0的一个数
                  按照升序排序
       (2)e-this,降序排序
 工具类:Collections
        提供了一个sort(Collection c)方法,对集合里的元素进行排序  
        
 Comparator比较器接口:
           如果元素类型已经实现了comparable接口,定义了默认的比较规则。之后,再想换其他比较规则时,不修改源码。可以利用比较器接口来重新定义比较规则  
     
     方法:
     int compare(E o1,E o2);
        比较规则:
        升序: o1-o2
        降序: o2-o1 
        
    二、    接口Queue 
        Queue也是Collection的子接口,是一种数据结构,队列。
        队列:通常都是一端进(offer),另一端出(poll)。
     
        进出原则:FIFO 
    
        因为队列要经常进行增删操作,所以使用Linkedlist实现了Queue接口.  
        
        常用方法:
        boolean offer(E e):元素从队尾进入队列。
        E poll():                     从队首移除元素,返回被移除的元素。当队列没有元素时返回null.
        E peek():                      查看队首元素,不移除。队列中没有元素时,返回null.
                
        注意: 为了避免移除队列的队首时出现null,我们最好先查看队首是不是null.
        
         Deque:是一个Queue的子接口,实现的是双端队列的数据结构。
                     双端队列:两端都可以进,也都可以出。
                  
         boolean offerFirst(E e);
         boolean offerLast(E e); 
         E pollFirst();
         E pollLast();
         E peekFirst();
         E peekLast(); 
   
       栈的数据结构:先进后出:FILO
                我们可以将双端队列的一端进行禁止操作。另一端进或出,即Stack 
                
        void push(E e):将元素 e推进栈中
        E pop():               将栈中的最顶端的元素,移除。     
                 
   三、 Set接口:
        特点1: 无序,存储的元素与添加顺序无关
        特点2: 不可重复(使用元素的equals方法来判定是否重复)
        特点3: 能存储null元素,只能存储一次。
    Hash算法机制
    Set集合设计的初衷是无序不能重复,因此向集合添加(或检索元素)时我们需要调用equals方法来一一校验。
    但是当集合中的元素过多时,我们校验的次数明显很多,因此效率就很低

    那么,如何提高效率呢?
     我们为元素对象,提供了一个hash算法,用于返回此元素的一个哈希值(int值)。
     并且在集合所占的内存中开辟很多小的区域,每个区域用于存储一定范围哈希值的元素。
     在我们添加元素或检索元素时,先获取此元素的哈希值,然后去相应区域中查找遍历(大大降低了比较次数)
   --在这个区域,哈希值对应的位置上没有元素,就将此元素存储到这个位置
   --如果有,然后查看两个对象的equals的返回值
         --如果为true,  不能添加  
         --如果为false, 可以添加,添加至对应的链表结构中(尽可能的避免发生)
         
     HashCode方法:
        Object是引用类型的父类,提供了hashCode()方法以及equals()方法
        因此我们在定义类型时,一般都重写hashCode和equals方法。
        重写的重要性:
        equals方法我们用来判断集合中的元素是否重复
        hashCode方法我们在使用Set集合时,必须要重写,因为我们采用的hash算法计算Set集合元素的存储位置。
    
    int hashCode():
        Object提供的方法是通过地址计算hash值,不可控。我们需要在自定义类中重写此方法。
        
    重写HashCode方法:
            重写规则:尽可能的让所有的成员变量都参与运算,
                             尽可能的避免出现hash值碰撞
    注意:
        重写的必要性:
        (1)如果重写了equals(), 有必要重写hashCode方法
        (2)如果equals()返回true, hashCode返回值有必要相同
        (3)如果equals()返回false,hashCode返回值不一定相同,
        如果返回值不同,可以提高检索的效率
    
   反过来说:
    (1)hashCode值相同,equals方法可能不同
    (2)hashCode值不同,equals方法一定不同      
  
Set接口派生的子类       
   HashSet:底层使用hash算法计算存储位置,无序,不重复,增加删除时效率高 
   LinkedHashSet: 底层使用hash算法计算存储位置,但是通过链表来维持顺序。顺序与添加顺序一致。在查看检索时,效率比较高 
   TreeSet:是SortedSet子接口的实现类, 使用二叉树的数据结构维护元素的顺序,顺序与自然排序有关系。支持定制排序
   
Set集合的遍历
       因为Set集合是无序的,无下标可言,因此不能使用经典for循环。我们可以使用迭代器原理。
       
       (1) 调用集合的iterator()获取迭代器
       (2) 使用foreach循环
       
Set集合的元素:
         不能轻易修改参与hash值算法的成员变量。否则容易引起内存溢出。
         原因:成员变量修改后,会出现新的hash值,但是存储位置还在原hash值的位置上。因此操作时,找不到具体的存储位置。  
         
         
Map接口:集合框架中的另一个父接口
    Map集合,用于储存一一对应的元素数据,第一个对象可以作为索引,第二个对象作为值,我们称之为key-value,键值对。
 
    储存数据的特点:
     (1)以key-value形式进行存储。
     (2)key与value都必须是引用类型
     (3)key可以为null。
     (4)key与value是单向一对一映射。
     (5)key不能重复
存储机制:
     Map是基于数组和链表的数据结构进行存储数据。
           作为key的对象采用了hash算法计算存储的数组
     (散列数组,散列桶)的位置.如果计算出来的位置,
           数组中此位置没有元素,就可以添加到
           散列桶内,如果有元素,key的equals方法
           返回值为false,就会存储在散列桶元素对应的单向链表中。
           如果key的equals方法返回true,就进行替换(覆盖)。
     PS:使用Map集合,做为key的数据类型应该重写equals和
      HashCode方法   
常用方法:
      V  put(K k,V v):
            作用:用于存储一对key-value.  返回被替换的value值
                  如果不是替换就返回null
      V  get(K k):
                   作用:通过key对象,获取对应的value对象,如果集合中
                   没有此key,返回null 
 Map集合的遍历
      Set<K>  keySet();
            用于获取Map中所有的key对象,返回一个Set集合
      Set<Entry<K,V>>  entrySet();
            将key-value封装成内部类对象,返回Entry对象的Set集合                        
      Collection<V> values();
           将map集合中的所有value封装到一个Collection集合中。
装载因子和HashMap的优化
      装载因子:DEFAULT_LOAD_FACTOR = 0.75f 
      默认容量:DEFAULT_INITIAL_CAPACITY  
           16,就是数组的容量
      元素个数: size    
           
   当我们创建一个HashMap对象时,底层数组的初始容量为16。当存储的数据的
   个数 size/DEFAULT_INITIAL_CAPACITY等于DEFAULT_LOAD_FACTOR时,
   数组开始扩容。此时最佳。
   
   如果小于0.75扩容,比较占内存。
   如果大于0.75扩容,操作的元素比较多。
   
   Map接口的子类:
  
HashMap与HashTable的区别
   (1)HashTable是一个古老的类。不建议使用
   (2)HashTable是一个线程安全的类,HashMap线程不安全
   (3)HashTable的key不能是null,HashMap可以是null
LinkedHashMap:是HashMap子类,使用链表来维护key-value的顺序,在迭代时顺序与添加顺序一致。
TreeMap:是SortedMap子接口的实现类,使用了二叉树的数据结构维护填入集合的顺序。
    (1)自然排序:
               往TreeMap里添加的key对象,可以实现Comparable接口。重写compareTo方法
    (2)定制排序:做为key对象的数据类型,可以不实现Comparabel接口。
              需要创建一个比较器Comparator对象。实现compare方法
Properties:
     是HashTable的子类型,用于封装属性文件的key-value信息因为在文件里写的都是字符串,因此Properties的key与value都是字符串类型

 

              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值