22.JAVA核心技术—集合

集合框架图:
     ((Iterator接口  <----))  Iterable接口  ← Collection接口                                                                              
                                                                 ↑                
                              ┌--------------------------------┬---------------┐                         
                               Set接口                                 List接口         Queue接口                                            Map接口
                                   ↑                                          ↑                    ↑                                                          ↑
                            ┌----------┐                    ┌-----------+---------┐ ┌-----------┐                               ┌----------┐       
                        HashSet   SortedSet接口    Vector    ArrayList   LinkedList   PriorityQueue                     HashMap  SortedMap接口
                                              ↑                                                                                                                              ↑ 
                                         TreeSet                                                                                                                    TreeMap                                          

1.集合接口

  1)Iterable接口只有一个方法,public Iterator iterator(),返回类型是Iterator,它与Iterator接口没有关系。

  2)迭代器:(Iterator)遍历元素,所有实现了Iterable接口的集合都可以使用迭代器遍历元素。

      Iterator接口的三个方法使用说明:hasNext():是否还有一个元素

                                                   next():指向下一个元素,并返回跨过的元素

                                                   remove():将最近一次next返回的元素删除(安全的从Collection底层中删除)

 3)Collection接口是集合接口的父接口(除了Map接口)。与Collections的区别在于Collections是个工具类,而Collection是个接口。

 4)List、Set、Queue、Map接口:List接口是有序的、元素可重复;Set接口是无序的、元素不可重复;Map接口每个元素是个键值对,键不可重复,值可以,可

                                               以有空键;Queue接口,队列,先进先出。

 5)SortedSet接口和SortedMap接口是排序接口。

注:集合类库中提供了一个Iterator的子接口ListIterator。这个子接口的功能如下:

   List接口有两个返回ListIterator接口的方法。listIterator()、listIterator(int index)

   ListIterator接口:   add(E newElement)将一个元素添加到当前位置的前面。

                             set(E newElement)以指定的元素取代next或previous方法访问的那个元素;

                             hasPrevious()和previous()跟Iterator接口中的hasNext()和next()方法功能相似。

2.具体的集合(集合接口的实现类)

 1)List接口的实现类:ArrayList类、LinkedList类、Vector类

      ArrayList底层是数组,查询速度快,增删慢;Vector底层是数组,但他是个线程安全的;

      LinkList是个链表,查询效率低,增删高。链表上每个数据节点是由前继指针,数据,后继指针组成。

 

 2)Set接口的实现类和子接口及其实现类:HashSet类、SortedSet接口、TreeSet接口

       HashSet(散列集)集合是无序的,元素不可重复。底层也是一个数组(链表的数组)。

 

       如何保证元素不重复?Hash算法和equals方法。当添加元素的时候,先计算对象的hashCode(哈希吗),

                                   int hc=obj.hashCode(),int i=hc%n;(你为数组的长度),利用余数在数组相应的位置添加。如果 

                                   位置有元素了先比较哈希吗,如返回true,再调用equals比较如返回true,元素相等,不用添加。

                                   若返回false就去找其他位置添加。

             注意:我们用我们自己定义的类来使用HashSet添加对象时,这个类一定要实现hashCode和equals方法。

       TreeSet(树集)是SortedSet的实现类,是个排序集合,默认的是字典排序,元素要实现Comparable接口。

        注意:将一个元素添加到树集的速度比将它添加到散列集的速度慢,但比添加到数组和链表的速度要快

 

       集合的排序:a. Collections.sort(List list)对指定的List进行排序。如果list里的元素是个自定义对象,就不能用这个方法

                          了,就必须使用下面的方法。

                        b.实现Comparable接口,即实现这个接口的compareTo(Object obj)方法,比较当前对象与指定对象的顺

                         序。当前对象>obj 返回>0;当前对象<obj 返回<0 ;当前对象=obj 返回=0

                        c.将一个Comparator对象传递给树集的构造参数,Comparator接口有个方法compare(Object,Object)。

       注意:使用Comparable接口定义的排序具有局限性,对于给定的类该接口只能实现一次,如果在一个集合中需要按照编号进行排序,在另一个集合中需要按照

                信息排序该怎么么办?这个时候需要使用Comparator接口,如上c.

 

 3)Queue接口的实现类:LinkedList类、PriorityQueue类

      优先级队列:它是一种能够在以任意顺序插入元素后,再按排序顺序读取这些元素的数据结构。

      注意:优先级队列并不是对所有的元素进行排序,比如我们对各个元素进行迭代,各个元素不需要排序,但是调用add和

              remove方法的时候总会将最小的元素移动的根。

              优先级队列所有的元素可以实现Comparable接口的类的对象,也可是在构造器中提供实现Comparator接口的对象

 4)Map接口的实现类和子接口及其实现类:HashMap类、SortedMap接口、TreeMap类。

      映射表:用于存放键值对,键是唯一的。  映射表的两个通用实现:HashMap(散列映射表)、TreeMap(树状映射表)。

      HashMap对键进行散列,TreeMap则使用键的全局顺序进行排序,并将其组织成树。

      HashMap的运行速度比TreeMap的运行速度快。

      方法:Set<k> keySet()//得到所有的键

              Collection<K> values()//得到所有的值

              Set<Map.Entry<K,V>> entrySet()//得到键和值

                for(Map.Entry<String ,Employee> entry:hashset.entrySet()){

                       String key=entry.getKey();

                       Employee value=entry.getValue();

                          ...........

                 }

 3.视图和包装器

  1)视图:通过使用视图,我们可以获得其他实现了Collection或Map接口的对象。如映射表中的keySet方法就是一个很好的列

               子,keySet方法返回的是一个实现了Set接口的类的对象(集合),同时该类的各个方法将对源映射表进行操作,这种

               集合被 称为视图。视图只是包装了接口不是实际的集合对象。

 2)轻量级集合包装器

     a. Arrays类有个静态的方法asList(),它返回包装了一个普通的Java数组的List包装器。如:

          Card[] card=new Card[52];.........

          List<Card> cardList=Arrays.asList(card);//返回的不是一个ArrayList对象,只是一个视图。

          List<Card> cardlist=Arrays.asList("Amy","Bob","Cari");

     b. Collections工具类的静态方法nCopies()

         Collections.nCopies(n,anObject)//返回一个实现List接口的不可修改的对象,并会产生一种包含n个元素,每个元素看

                                                       上去都像是一个anObject的错觉。 

         Collections.singleton(anObject)//返回一个实现了Set接口的视图对象。

   3)子范围视图

         List group=staff.subList(10,20//从staff列表中获取第10至19个元素。

   4)不可修改视图

        Collections类拥有一些方法,用于构建集合的不可修改视图。这些视图对现有集合增加了一次运行期检查,如果发现谁视

         图对该集合进行修改,就会抛出异常,同时该集合将保持未修改的状态。

        List<String> staff=new LinkedList<String>();

        Collections.unmodifiableList(staff);//返回一个实现了List接口的某个类的对象。

       注意:不可修改视图并不是使集合本身不可修改。我们任然可以通过集合的原始引用来修改集合。

    5)同步视图

        Java类库的设计者没有实现线程—安全集合类,而是使用视图机制来保证常规的集合线程安全。

       如Collections.synchronizedMap方法可以将任何一个映射表转换成一个具有同步访问方法的Map,

           HashMap<String,Employee> hasMap=new HshMap<String,Employee>();

           Map<String,Employee>map=Collections.sychronizedMap(hasMap);

       注意:视图只是对集合的方法进行了序列化,如果想使用迭代器的话,就需要手工获取集合对象上的锁,如

              synchronized(map){

                  Iterator<String> iter=mapkeySet();....

              }

    6)被检验视图

        ArrayList<String> strings=new ArrayList<String>();

        ArrayList rawList=strings;

        rawList.add(new Date());

     上述代码中错误的add方法在运行时并不能被检测到,只有在稍后代码的另一部分调用get方法并将结果转化为String时,才

     抛出异常。此时被检验师徒可以探测到这类问题。定义:

        List<String> safeString=Collections.checked:List(strings,String.class);

4 批操作、数组和集合的转换

    批操作,如希望查找两个集合的交集,

    Set<String> result=new HashSet<String>(a);

    result.retainAll(b)//该方法保留所有在a中也在集合b中的元素。

    数组转为集合: String[] values=......;

                         HashSet<String> staff=new HashSet<String>(Arrays.asList(values));

   集合转为数组:String[] values=staff.toArray(new String[0]);

                       String[] values=(String[])staff.toArray();//Error,返回的是一个Object[]数组,我们无法改变类型。

 

 

 

posted on 2012-04-26 10:38  ssy黑桃a  阅读(277)  评论(0编辑  收藏  举报