zoukankan      html  css  js  c++  java
  • 08_集合概述

    1. 集合框架体系概述

         为什么出现集合类?

              面向对象语言对事物的体现都是以对象的形式,为方便对             

              多个对象的操作,就对对象进行存储,集合就是存储对象最

              常用的一种方法.

         数组和集合类同时容器,有何不可?

              数组虽然也可存储对象,但长度固定; 而集合长度可变

              数组是存储同一类型基本数据类型,集合能存储任意对象

         集合类的特点

              集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象.   


    图1: 集合框架图

    wKiom1P9-kKwGyUmAAHKTDS-Q_Y135.jpg

     

    图2: Java框架构成关系图

    wKioL1P9-3rjTnSPAAHdGd281Xk601.jpg

     每个容器对数据的存储方式不同,这种存储方式称为数据结构.


    2. 集合框架共性方法

            //发现java中对方法的学习用增删查改不能很好的概括,增,删,改可以,但查可以分为判断和获取.这样就五种操作了.增,删,判,获(查),改.

            //集合存储的都是对象的引用(地址)

         boolean add(E e)添加指定的元素(可选操作)

         boolean addAll(Collection<? extends E> c) 将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。

         clear(): 清空集合中所有元素

         boolean contains(Object o) 是否包含指定元素

         boolean containsAll(Collection<?> c) 只判断参数中的集合是否都包含在A集合内,最终A集合没有任何变化.

         boolean isEmpty() 判断是否为空

         boolean remove(Object o)   移除单个实例

         boolean removeAll(Collection<?> c)  取差集

         boolean retainAll(Collection<?> c)  取交集

         int size():返回collection中的元素.

         Object[] toArray() 这个可以理解

         <T> T[]  toArray(T[] a)  应这么写String[] y =  c.toArray(new String[collection.size()])较好

         重点讲讲用于查找的Iterator迭代器接口

              Iterator it = al.iterator(); /*实际上是集合类在List和Set都包含的iterator方法,返回Iterator对象,具体实现方式是内部类.可以认为是继承了AbstractList,实现了Iterable接口.把取出方式定义成内部类,每个容器的数据结构不同,取出的动作细节也不一样.但是都用共性的判断和取出,可以将共性方法抽取.对外提供了Iterator方法.*/

         迭代器使用

         while(it.hasNext()){

              System.out.println(it.next());

         }

         老外为了节省空间,写成这样

         for(Iterator it = al.iterator();it.hasNext(); ){

              System.out.println(it.next());

         }


    3. List序列共性方法(List也被成为序列, 它的对象的元素有序可重复,正因为有序,所以操作角标的方法都是该体系特有的方法)

          增 void add(int index, E element) 在列表的指定位置插入指定元素(可选操作)。  

          删 E remove(int index)   移除列表中指定位置的元素(可选操作)。

          查 ListIterator<E> listIterator()  返回此列表元素的列表迭代器(按适当顺序)。

          改 E set(int index, E element)   用指定元素替换列表中指定位置的元素(可选操作)。

          获取 E get(int index)  返回列表中指定位置的元素。       

            list因此多了一种取出所有元素的方法: 

                for(int i=0;i<al.size();i++){ 

                     输出al.get(i); 

                } 

          获取<E> subList(int fromIndex, int toIndex)  返回列表中指定的 fromIndex(包括)和 toIndex(不包括)之间的部分视图。      

         List有自己更强功能的的ListIterator是Iterator的子接口,是带下标的.

         集合引用和迭代器引用在同时操作元素,通过集合获取到对应的迭代器后,在迭代中,进行集合引用的元素添加,迭代器并不知道,所以会出现ConcurrentModificationException异常情况。ListIterator列表迭代器接口具备了对元素的增、删、改、查的动作。

              原 查 next() 但是 增加了previous()

              原 删 void remove() 

              增加了特有了 

                增void add(E e)  

                改 void set(E e) 

                和独有的int nextIndex(), int previousIndex() 和 int nextIndex()


    4. List集合的三个常见子类对象(List有序可重复,因为体系有索引)

         ArrayList: 底层使用数组结构, 查询块,增删稍慢. 线程不同步,JDK1.2以上

         LinkedList: 底层是链表结构, 增删块,查询稍慢,JDK1.2以上

         Vector: 底层使用数组结构, 查询块,增删慢. 线程同步.被ArrayList替代了1.0时代产物. 枚举就是Vector特有的取出方式.


         ArrayList详解:拥有角标的方法是其特有方法

             可变长度数组的原理 :当元素超出数组长度,会产生一个新数组,将原数组的数据复制到新数组中,再将新的元素添加到新数组中。

          ArrayList:是按照原数组的 50%延长构造一个初始容量为10的空列表。

          Vector:是按照原数组的 100%延长    


         LinkedList详解:特有的add,get,remove方法  

        在1.6后新方法

               boolean offerFirst(E e) 

                   在此列表的开头插入指定的元素。 

               boolean offerLast(E e) 

                   在此列表末尾插入指定的元素。 

               E peek() 

              获取但不移除此列表的头(第一个元素)。 

               E peekFirst() 

                   获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。 

               E peekLast() 

              获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。 

               E pollFirst() 

                   获取并移除此列表的第一个元素;如果此列表为空,则返回 null。 

               E pollLast() 

                   获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。  


         Vector详解

              枚举是Vector特有的取出方式hasMoreElements()和nextElement()方法,发现枚举和迭代器很像.其实枚举和迭代一样的.

              但迭代取代了枚举,不仅是名字更短一点, 还包含可移除的操作, 使用范围也更广.

              推荐使用迭代,而不是枚举.         


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //ArrayList练习一: 去除ArrayList中的重复元素
    //思路:新建一个容器,如果新容器没有就存进去,最后返回即可.
    public static ArrayList singleElement(ArrayList al){
        ArrayList newAl = new ArrayList();
        for(Iterator it = al.iterator();it.hasNext();){
            Object next = it.next();
            if(!newAl.contains(next))
                newAl.add(next);
        }
        return newAl;
    }

    //注意:使用iterator.next()取出时每次只取出一个,而不是取出多个.会造成NoSuchElementException

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //ArrayList练习二:将自定义对象作为元素存到ArrayList集合中,并取出重复元素. 比如:存人对象,同姓名同年龄视为同一个人,为重复元素.
    //思路:1.对人描述,封装成对象 2.定义容器,将人存入 3.取出重复元素 4.取出
            //主要第三部分,如何去除重复元素
        public static List singleElement(List list){
            List newList = new ArrayList();
            for(Iterator it = list.iterator();it.hasNext();){
                Person p = it.next();
                if(!newList.contains(p))
                    newList.add(p);
            }
            return newList;
        }
    //总结:本来是使用void,虽说引用是实际参数地址的拷贝,对拷贝的操作会牵扯到原来的数据,但是不能整个集合赋值给新的引用参数的地址,这是无效的,所以必须有返回值才行.

    总结: 在List下的ArrayList和LinkedList的contains和remove方法都是使用了了obj的equals方法.可以自己重写equals方法判断集合内两对象是否"一致".


    5. Set集合的两个常见子类对象(Set集合的方法和Collection是一模一样,所以不用多讲)

         元素是无序,不可重复的     

         HashSet(线程是不同步)

              底层数据结构是哈希表,线程非同步.

              通过hasHashCode()和equals()来完成

              如果元素的HashCode相同,才会判断equals是否为true

              如果元素的HashCode不同,不会调用equals,直接是不等.     

         注意,对于判断元素是否存在,以及删除等操作,依赖方法都是hashcode和equals方法. 在使用HashSet,一定要按需覆盖int hashCode()和boolean equals (Object obj)方法.按照优先级判断元素是否能添加删除.

         TreeSet(可以对Set集合中的元素进行排序)

              底层数据结构是二叉树

              通过int compareTo()来完成增,删,查          

              TreeSet排序

                   第一种方式:实现Comparable接口,覆盖int compareTo()方法,让元素自身具备比较性

                   第二种方式:构造实现Compare接口,覆盖int compare(Object o1, Object o2)方法,将比较器对象作为参数传递给TreeSet集合的构造函数.


    6. Map集合的三个常见子类对象

         将键映射到值的对象,一对一对往里存,而且要保证键的唯一性.

              添加

                   put(K key, V value)

                   putAll(Map<? extends K, ? extends V> m)

              删除

                   clear()

                   remove(Object key)

              判断

                   containsKey(Object key)

                   containsValue(Object value)

                   isEmpty()

              获取

                   get(Object key)

                   size()

                   values()

                   entrySet()

                   keySet()

    ---HashTable: 底层是哈希表,不允许空键空值,线程同步,jdk1.0,效率低

    ---HashMap: 底层是哈希表,允许空键空值,线程不同步,jdk1.2,效率高

    ---TreeMap: 底层是二叉树,线程不同步,jdk1.2

    Map和Set很像,其实Set底层就是使用了Map集合.


    Map集合的共性方法注意

         1.添加元素,如果出现相同的键,那么后添加的值会覆盖原有键对应的值, put方法会会返回被覆盖的值

         2.可通过get方法的返回值来判断一个键是否存在,通过返回null判断.

         3.获取map集合中所有的值

    两个重要的获取方法:  keySet()和entrySet()

         1.通过keyset()获取key的Set集合,然后Iterator获取key,最终get(Object key) 获取.

         2.通过entryset()获取关系,然后Iterator获取键值对,最终Map.Entry的getKey和getValue方法获取. 

    其实Map.Entry也是一个接口,它是Map接口中的一个内部接口


    练习一:使用HashMap

         每个学生都有归属地

         学生Student,地址addr

         学生属性:姓名和年龄,注意姓名和年龄相同视为同一个学生,需保证学生的唯一性

         我的主要代码

    wKiom1P9-paQnbfSAAJdj0nggJ8450.jpg

    练习二: 对学生对象的年龄进行升序排序  (使用TreeMap即可)

    练习三: "sdfkgjlsk"获取该字符串中字母出现的次数


    Map扩展: 无非就是集合套集合,用keyset()对于这种复杂的结构似乎简化了操作,但不管怎样还是利于理解的.比使用entryset要简便.

    ---------thinking、architecture、code、treasure---------
  • 相关阅读:
    题解 CF36B【Fractal】
    21清北学堂腾飞营游记
    canvas小试牛刀
    ES度量聚合(ElasticSearch Metric Aggregations)总结
    Mybatis中设计模式的运用
    Mybatis源码-SqlSession(二)
    Mybatis源码-sqlSessionFactory(一)
    Redis6.0多线程模型总结
    RocketMQ中的CommitLog、ConsumeQueue、indexFile、offsetTable以及多种偏移量对比
    SpringBoot——自动配置原理
  • 原文地址:https://www.cnblogs.com/elaa/p/3992511.html
Copyright © 2011-2022 走看看