javase基础知识02-Collection集合,Map集合

   

 

     (1)为什么出现集合类?
        面向对象对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储。
        集合就是存储对象最常用的一种方式.
    (2)数组和集合都是容器,两者有何不同?
       a.数组长度固定,而集合长度是可变的    
       b.数组值可以存储对象,还可以存储基本数据类型;而集合只能存储对象    
       c.数组存储数据类型是固定的,而集合存储的数据类型不固定        
    (3)集合类的特点:
        集合只能存储对象
        集合的长度可变
        集合可以存储不同类型的对象
    (4)各种集合的
  ArrayList:
            (1)当往ArrayList里面存入元素没什么要求时,即只要求有序就行时;
               
            (2)当往ArrayList里面存入元素要求不重复时,比如存入学生对象,当同名同姓时
               视为同一个人,则不往里面存储。则定义学生对象时,需复写equals方法
               public boolean equals(Object obj)
               {
                if(!(obj instanceof Student))
                    return false;
                Student stu = (Student)obj;
                return this.name.equals(stu.name)&&this.age==stu.age;
               }
               则往ArrayList集合通过add存入学生对象时,集合底层自己会调用学生类的equals方法,
               判断重复学生则不存入。

           (3)特有的列表迭代器:ListIterator

                可以用于解决并发错误,
             注:对于List集合,无论是add、contains、还是remove方法,判断元素是否相同,
                 都是通过复写equals方法来判断!

  Vector

           底层数据结构和ArrayList一样,但是是线程同步,数据安全的,效率比较低。

  LinkedList
            (1)LinkLedist的特有方法:
                 boolean offerFirst(E e)  在此列表的开头插入指定的元素。
                 boolean offerLast(E e) 在此列表末尾插入指定的元素。
                 E peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
                 E peekLast() 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
                 E pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
                 E pollLast() 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
            (2)通过LinkedList的特有方法,可以实现某些数据特殊方式的存取,比如堆栈和队列。

  一般情况下,使用哪种List接口下的实现类呢?
                如果要求增删快,考虑使用LinkedList
                如果要求查询快,考虑使用ArrayList
                如果要求线程安全,考虑使用Vector。

Set:集合,元素是无序的(因为没有索引),元素不可以重复。但可以有null元素。
         HashSet:底层数据结构是哈希表、存取速度快、元素唯一、线程不同步。

         TreeSet:底层数据结构是二叉树,元素唯一,线程不同步,元素排序。排序方法有自然排序和自定义排序。

             TreeSet可以对set集合中的元素进行排序(按字母ASCII), 底层数据结构是二叉树,保证数据唯一性的是compareTo方法return 0;TreeSet排序第一种方式:元素自身具备比较性(元素类型必须实现Comparable接口并且覆盖其compareTo方法)。

         HashMap

                 1. 底层数据结构是数组+链表+红黑树(JDK1.8才有的红黑树,链表上的值多于8个就用红黑树结构),线程不同步,可以理解成:一个数组,它的每一项都是一条链,如果这条链长度大于8,就用红黑树代替链。

                 2. Key可以为null,即键值对的可以为(null,null);

                 3. put方法参数有相同的键key会导致新的(K1,newV1)覆盖旧的键值对。put方法返回值是原来的OldValue,也就是如果put方法返回值是null,说明是第一次put这个键以及对于的值。但有时候根据hash算法计算出的存储位置有可能相同,而这个位置原来就有其他元素占用,这就是哈希冲突,HashMap解决它的办法就是用链地址法:

      首先判断key是否为null,若为null,则直接调用putForNullKey方法。若不为空则先计算key的hash值,然后根据hash值搜索在table数组中的索引位置,如果table数组在该位置处没有元素,则直接添加上去。如果table数组在该位置处有元素,则通过比较是否存在相同的key,若存在则覆盖原来key的value,否则将该元素保存在链头(最先保存的元素放在链尾)。

                 4.put到容量的0.75时候会扩容2倍,扩容的时候需冲重新add  entry对象,需要重新计算hash,然后放进Map,所有比较耗资源,如果需要用到的容量很多,可能会导致多次扩容,一般如果知道容量大概有多少先指定容量。

                  5.HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

 

          TreeMap:             

                1.实现了NavigableMap接口,意味着它支持一系列的导航方法。比如返回有序的key集合。实现了Cloneable接口,意味着它能被克隆,实现了java.io.Serializable接口,意味着它支持序列化

                 2. 底层数据结构是红黑树,红黑树是一种自平衡排序二叉树,树中每个节点的值,都大于或等于在它的左子树中的所有节点的值,并且小于或等于在它的右子树中的所有节点的值。线程不同步,每个节点包含的内容有:左右节点引用,父亲节点引用,key,value,color;

                

一、Map集合和Collection集合的区别?
    1
    Map中一次存储是键值对。
    Collection中一次存储是单个元素。
    2
    Map的存储使用的put方法。
    Collection存储使用的是add方法。
    3
    Map集合没有迭代器,Map的取出,是将Map转成Set,在使用迭代器取出。
    Collection取出,使用就是迭代器。
    4
    如果对象很多,必须使用集合存储。
    如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
    如果没有映射关系,可以使用Collection存储。

 

二、集合类各种容器的使用注意细节:
    (1)迭代器:
        **迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
          也就是在迭代循环中调用一次next方法一次就要hasNext判断一次,比如语句
          sop(it.next()+"..."+it.next())会发生上述异常。
        **迭代器的next方法返回值类型是Object,所以要记得类型转换,应用泛型后就不用强转
    (2)List集合:
        **List集合里面的元素因为是带角标,所以List集合里面的元素都是有序的,
          另外List集合可以包含重复元素,也可以包含null。  
        **List集合有迭代器Iterator,还有一个特有迭代器列表ListIterator
        **List集合中判断元素是否相同都是用equals方法,无论contains、remove都依赖equals方法
          比如往ArrayList集合里面存放学生,同名同年龄视为同一个人,此时就需要在学生类复写Object类
          里面的equals方法(非常重要!!!要注意!!)
    (3)Set集合:
        **Set接口里面存放的是元素是无序的,不可以有重复元素,可以包含null
        **Set集合只有一种取出方式,就是迭代器Iterator
        **Set集合功能和Collection是一致的,没有特殊方法
        HashSet:
        **集合里面存放的元素是无序的,唯一的
        **底层数据结构是哈希表,哈希表结构的数据都是无序的,哈希表结构的操作效率都高效
        **线程不同步
        **保证元素唯一性的原理是:通过复写hashCode和equals方法
            ****如果两元素的hashCode值相同,则继续判断两元素equals是否为真
            ****如果两元素的hashCode值不同,则不会调用equals方法。
        **当我们往HashSet集合存放自定义的元素时(比如学生对象),通常都要复写hashCode和equals方法,
          而且hashCode和equals方法不通过我们调用,HashSet集合底层内部自己调用,自己拿元素去比较
        TreeSet
        **TreeSet集合可以对存放的元素进行排序,弥补了Set集合元素无序的缺点,且元素是唯一的
        **底层数据结构是二叉树,二叉树结构都是有序的
        **线程不同步
        **TreeSet集合要求往集合里存放的元素自身具备比较性,否则会报错
        **TreeSet集合保证元素唯一性的依据是:通过compareTo或者compare方法中的来保证元素的唯一性。
            TreeSet排序的第一种方式:让元素自身具备比较性,
                        定义元素类实现Compareble接口,覆盖compare方法,
                        此方式是元素的自然顺序。
            TreeSet排序的第二种方式:让集合具备比较性
                        当元素自身不具备比较性或者具备的比较性不是
                        我们所需要的比较性时,此时就需要让集合具备自定义的比较性。
                        那如何让集合自身具备比较性呢?
                        可在集合初始化时,就让集合具备比较方式。
                        即定义一个类,实现Comparator接口,覆盖compare方法。
            注:
            **判断元素唯一时,当主要条件一样时,判断次要条件
            **两种排序方式都在时,以比较器为主!!!

三、Map的两种取出方式:
      第一种:Set<K> keySet()
        返回此映射中包含的键的Set视图,将Map集合中所有的键存入Set集合,然后再通过Set集合的
        迭代器取出所有的键,再根据get方法获取每个键的值;
      第二种:Set<Map.Entry<K,V>> entrySet()
        返回此映射中包含的映射关系的Set视图,将Map集合中的映射关系存入到Set集合中,
        这个映射关系的数据类型是Map.entry,再通过Map.Entry类的方法再要取出关系里面的键和值
        Map.Entry的方法摘要:
            boolean equals(Object o)  比较指定对象与此项的相等性。              
            K getKey()  返回与此项对应的键。              
            V getValue() 返回与此项对应的值。               
            int hashCode() 返回此映射项的哈希码值。
            V setValue(V value) 用指定的值替换与此项对应的值(特有!!!)。

四、Collections类:
    (1)此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。
    (2)静态方法摘要:
        static <T> boolean addAll(Collection<? super T> c, T... elements)
            将所有指定元素添加到指定 collection 中。
        static <T> void fill(List<? super T> list, T obj)
            使用指定元素替换指定列表中的所有元素。
        static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)
            使用另一个值替换列表中出现的所有某一指定值。
        static void reverse(List<?> list)
            反转指定列表中元素的顺序。
        static <T> Comparator<T>  reverseOrder()
            返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序
        static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
            返回一个比较器,它强行逆转指定比较器的顺序。
    (3)Collections类的方法:
        集合有一个共同的缺点,那就是线程不安全,被多线程操作时,容易出现问题,虽然可以自己加锁
        但是麻烦。Collections提供特牛的方法,就是给它一个不同步的集合,它返回一个同步的安全的集合

        static <T> Collection<T> synchronizedCollection(Collection<T> c)
            返回指定 collection 支持的同步(线程安全的)collection。
        static <T> List<T>  synchronizedList(List<T> list)
            返回指定列表支持的同步(线程安全的)列表。
        static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
            返回由指定映射支持的同步(线程安全的)映射。
        static <T> Set<T> synchronizedSet(Set<T> s)
            返回指定 set 支持的同步(线程安全的)set。
        static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
            返回指定有序映射支持的同步(线程安全的)有序映射。
        static <T> SortedSet<T>  synchronizedSortedSet(SortedSet<T> s)
            返回指定有序 set 支持的同步(线程安全的)有序 set。

五、Arrays类:
    此类包含用来操作数组(比如排序和搜索)的各种方法。里面都是静态方法。
    如果指定数组引用为 null,则此类中的方法都会抛出 NullPointerException。
    (1)数组变集合:
        static <T> List<T> asList(T... a)
            返回一个受指定数组支持的固定大小的列表。
        注意:
            A:该方法将一个数组变成集合后,不可以使用集合的增删方法,因为数组的长度是固定的!
                  如果增删,则发生UnsupportedOprationException(不支持操作异常)
            B:如果数组中的元素都是基本数据类型,则该数组变成集合时,会将该数组作为集合的一个
              元素出入集合
            C:如果数组中的元素都是对象,如String,那么数组变成集合后,数组中的元素就直接转成
              集合中的元素      
    (2)集合变数组:
        方法:Collction中的toArray方法
        好处:可以限定对集合元素的操作,防止对集合的元素进行增删,因为数组长度是固定的。

六、Collections类和Arrays类的使用?
    A:Collections
        排序            sort(List<T>list)
        二分查找     binarySearch(List<T>list,t.key)
        随机置换     shuffle(List<T>list)    
        反转            reverse(List<T>list)
    B:Arrays
        把数组变成字符串输出    toString (Array a)
        排序                                 sort(Array a)

        二分查找                          binarySearch(Array a,String str)         

七、HashMap和Hashtable的不同点?

1.HashMap继承于AbstractMap,而Hashtable继承于Dictionary

2.Hashtable的几乎所有函数都是同步的,即它是线程安全的,支持多线程。而HashMap的函数则是非同步的,它不是线程安全的。

3.HashMap只支持Iterator(迭代器)遍历。而Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。

4.容量的初始值 和 增加方式都不一样

HashMap默认的容量大小是16;容量使用0.75(加载因子)后,将容量变为“原始容量x2”
Hashtable默认的容量大小是11;容量使用超过阈值后,将容量变为“原始容量x2”

八、HashMap和TreeMap比较?

1)HashMap适用于Map中插入,删除和定位元素。

2)TreeMap时候用于需要排列的时候,遍历键。

3)线程都不是安全的,要安全就用Hashtable

4)HashMap遍历结果不排序,TreeMap排序。

5)HashMap基于哈希表实现(底层为数组+链表+红黑树),TreeMap基于红黑树实现

6)HashMap效率高一些

九、ArrayList和LinkedList区别?Vector?

1.ArrayList底层数据结构是数组,LinkedList。。是链表

2.当访问ArrayList的时候可以随机通过索引直接访问,而LinkedList要指针按顺序从前往后依次查找,故访问效率LinkedList不如ArrayList

3.基于2,进行增删操作时候,ArrayList的下标会有有所变化,需要进行大量的数据移动,所以增删效率不如LinkedList。

4.ArrayList直接开辟一块连续的内存空间,然后通过索引存储数据,而LinkedList通过形成一个数据结点来存储数据元素。

Vector底层数据结构跟ArrayList一样,但是Vector的线程同步,数据安全,效率不如ArrayList。

十、HashSet和treeSet的异同?

相同点:

      都是单列集合;元素不重复。

不同点:

       1.底层数据结构不一样,HashSet是哈希表,treeSet是二叉树

       2.保证唯一性的方法不一样,HashSet需要先比较hashcode是不是一样,再通过equals方法判断相不相等。而treeSet只需要通过compareTo方法返回值是否为0 判断。

       3.有序性不一样,HashSet的元素无序,而treeSet有排列顺序,treeSet通过自然排序或者比较器排序可以实现排序。

十一、数组和集合的区别?

1.长度区别:数组长度固定,集合长度可变

2.数据类型:数组的存放的数据类型可以是引用类型或者基本类型,而集合只能是放引用类型

3.元素内容区别:数组最多存一种类型的元素,而集合可以存放多种,但一般都放同一种

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值