精华内容
参与话题
问答
  • Java集合框架总结—超详细-适合面试

    万次阅读 多人点赞 2015-03-16 15:50:29
     1、Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些接口或实现类。     Set和List接口是Collection接口派生的两个子接口,Queue是...


    0.参考文献

    http://xxxxxx


    一、精简偏:

    A、概念汇总

        1、Java的集合类主要由两个接口派生而出:CollectionMap,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些接口或实现类。

     

    image

     

    Set和List接口是Collection接口派生的两个子接口,Queue是Java提供的队列实现,类似于List。

     

    image

    Map实现类用于保存具有映射关系的数据(key-value)。


       2、Set、List和Map可以看做集合的三大类。

         List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。

         Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是不能集合里元素不允许重复的原因)。

         Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。

     

    对于Set、List和Map三种集合,最常用的实现类分别是HashSet、ArrayListHashMap三个实现类。(并发控制的集合类,以后有空研究下)。


    B、代码证明

    1、Collection接口


         Collection接口是List、Set和Queue接口的父接口,同时可以操作这三个接口。

    Collection接口定义操作集合元素的具体方法大家可以参考API文档,这里通过一个例子来说明Collection的添加元素、删除元素、返回集合中元素的个数以及清空集合元素的方法。

    复制代码
    public class TestCollection
    {
        public static void main(String[] args) 
        {
            Collection c = new ArrayList();
            //添加元素
            c.add("孙悟空");
            //虽然集合里不能放基本类型的值,但Java支持自动装箱
            c.add(6);
    
            System.out.println("c集合的元素个数为:" + c.size());
           
         //删除指定元素
            c.remove(6);
           
         System.out.println("c集合的元素个数为:" + c.size());
            //判断是否包含指定字符串
            System.out.println("c集合的是否包含孙悟空字符串:" + c.contains("孙悟空"));
    
            c.add("轻量级J2EE企业应用实战");
    
            System.out.println("c集合的元素:" + c);        
    
         Collection books = new HashSet();
    
            books.add("轻量级J2EE企业应用实战");
            books.add("Struts2权威指南");
    
            System.out.println("c集合是否完全包含books集合?" + c.containsAll(books));
    
            //用c集合减去books集合里的元素
            c.removeAll(books);
    
            System.out.println("c集合的元素:" + c);
    
            //删除c集合里所有元素
            c.clear();
    
            System.out.println("c集合的元素:" + c);
    
            //books集合里只剩下c集合里也同时包含的元素
            books.retainAll(c);
    
            System.out.println("books集合的元素:" + books);
        }
    }
    复制代码



    程序输出结果:

    c集合的元素个数为:2 
    c集合的元素个数为:1 
    c集合的是否包含孙悟空字符串:true 
    c集合的元素:[孙悟空, 轻量级J2EE企业应用实战] 
    c集合是否完全包含books集合?false 

    c集合的元素:[孙悟空] 

    c集合的元素:[] 
    books集合的元素:[]



     




    3、两种遍历集合的方法Iterator接口和foreach循环

        3.1、Iterator接口

     Iterator也是Java集合框架的成员,主要用于遍历(即迭代访问)Collection集合中的元素,也称为迭代器。

    提供的三种方法:

    boolean hasNext():返回集合里的下一个元素。

    Object next():返回集合里下一个元素。

    void remove();删除集合里上一次next方法返回的元素。

     

    复制代码
    public class TestIterator 
    { 
        public static void main(String[] args) 
        { 
            //创建一个集合 
            Collection books = new HashSet(); 
    
            books.add("轻量级J2EE企业应用实战"); 
            books.add("Struts2权威指南"); 
            books.add("基于J2EE的Ajax宝典"); 
    
            //获取books集合对应的迭代器 
            Iterator it = books.iterator(); 
    
            while(it.hasNext()) 
            { 
           //未使用泛型,需要强制转换
                String book = (String)it.next(); 
    
                System.out.println(book); 
    
                if (book.equals("Struts2权威指南")) 
                { 
                    it.remove();
    
                //使用Iterator迭代过程中,不可修改集合元素,下面代码引发异常
                //books.remove(book); 
    
                } 
    
                //对book变量赋值,不会改变集合元素本身 
                 book = "测试字符串"; 
    
            } 
            System.out.println(books); 
        } 
    }
    复制代码

     

    程序运行结果:

    Struts2权威指南 
    基于J2EE的Ajax宝典 
    轻量级J2EE企业应用实战 
    [基于J2EE的Ajax宝典, 轻量级J2EE企业应用实战]

     

    说明:

    (1)通过语句“book = "测试字符串"; ”对迭代变量book进行赋值时,当我们再次输出books集合时,集合里的元素没有任何变化。即当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给迭代变量,而是把集合元素的值传给了迭代变量。

    (2)当使用Iterator来访问Collection集合元素时,只有通过Iterator的remove方法删除(it.remove();)上一次next方法返回的集合元素才可以给集合中添加元素(book = "测试字符串"; )。否则引发java.util.ConcurrentModificationExcption异常。

     

       

    3.2、使用foreach循环遍历集合元素。

    格式:for(元素类型 t  元素变量 x : 遍历对象A) {

                         // 程序块

    }

    说明:

    (1)foreach简化了对数组和集合的遍历,如果不希望遍历整个集合,或者在循环内部需要操作下标值就需要使用传统的for循环。

    (2)简化了编程,提高了代码的可读性和安全性(不用怕数组越界)。

    (3)foreach一般结合泛型使用

    实例应用:

    复制代码
    public class TestArray {
        public static void main(String args[]) {
            TestArray test = new TestArray();
            test.test1();
            test.listToArray();
            test.testArray3();
    
        }
    
        /**
         * foreach语句输出一维数组
         */
        public void test1() {
            // 定义并初始化一个数组
            int arr[] = { 2, 3, 1 };
            System.out.println("----1----排序前的一维数组");
    
            for (int x : arr) {
                System.out.println(x); // 逐个输出数组元素的值
            }
    
            // 对数组排序
            Arrays.sort(arr);
    
            // 利用java新特性for each循环输出数组
            System.out.println("----1----排序后的一维数组");
    
            for (int x : arr) {
                System.out.println(x); // 逐个输出数组元素的值
            }
        }
    
        /**
         * 集合转换为一维数组
         */
        public void listToArray() {
            // 创建List并添加元素
            List<String> list = new ArrayList<String>();
            list.add("1");
            list.add("3");
            list.add("4");
    
            // 利用froeach语句输出集合元素
            System.out.println("----2----froeach语句输出集合元素");
    
            for (String x : list) {
                System.out.println(x);
            }
    
            // 将ArrayList转换为数组
            Object s[] = list.toArray();
    
            // 利用froeach语句输出集合元素
            System.out.println("----2----froeach语句输出集合转换而来的数组元素");
    
            for (Object x : s) {
                System.out.println(x.toString()); // 逐个输出数组元素的值
            }
        }
    
        /**
         * foreach输出二维数组测试
         */
        public void testArray2() {
            int arr2[][] = { { 4, 3 }, { 1, 2 } };
    
            System.out.println("----3----foreach输出二维数组测试");
    
            for (int x[] : arr2) {
                for (int e : x) {
                    System.out.println(e); // 逐个输出数组元素的值
                }
            }
        }
    
        /**
         * foreach输出三维数组
         */
        public void testArray3() {
            int arr[][][] = { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } } };
    
            System.out.println("----4----foreach输出三维数组测试");
    
            for (int[][] a2 : arr) {
                for (int[] a1 : a2) {
                    for (int x : a1) {
                        System.out.println(x);
                    }
                }
            }
        }
    }
    复制代码

    程序运行结果:

    ----1----排序前的一维数组 



    ----1----排序后的一维数组 



    ----2----froeach语句输出集合元素 



    ----2----froeach语句输出集合转换而来的数组元素 



    ----4----foreach输出三维数组测试 







    8



    0.线程同步问题


      关于同步问题,一般而言,非同步的类,性能比同步的要好。我们建议用Collections.synchronizedCollection(Collection<T> c)方法去处理原本非同步的类,在不丢失性能的前提下,实现同步。Java1.5提供了ConcurrentHashMap,适用于高并发的线程安全实现。

    二   Java 集合类详解

    0.参考文献

    http://blog.csdn.net/liulin_good/article/details/6213815

    1.java集合类图

    1.1

    1.2

      上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等。

      发现一个特点,上述所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法。它的一个子接口LinkedIterator在它的基础上又添加了三种方法,分别是add(),previous(),hasPrevious()。也就是说如果是先Iterator接口,那么在遍历集合中元素的时候,只能往后遍历,被遍历后的元素不会在遍历到,通常无序集合实现的都是这个接口,比如HashSet,HashMap;而那些元素有序的集合,实现的一般都是LinkedIterator接口,实现这个接口的集合可以双向遍历,既可以通过next()访问下一个元素,又可以通过previous()访问前一个元素,比如ArrayList。

      还有一个特点就是抽象类的使用。如果要自己实现一个集合类,去实现那些抽象的接口会非常麻烦,工作量很大。这个时候就可以使用抽象类,这些抽象类中给我们提供了许多现成的实现,我们只需要根据自己的需求重写一些方法或者添加一些方法就可以实现自己需要的集合类,工作流昂大大降低。

    1.3

    2.详解

     2.1HashSet

    HashSet是Set接口的一个子类,主要的特点是:里面不能存放重复元素,而且采用散列的存储方法,所以没有顺序。这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致。

    代码实例:HashSetDemo

    View Code

    代码实例:SetTest

    View Code

     

    2.2ArrayList

    ArrayList是List的子类,它和HashSet想法,允许存放重复元素,因此有序。集合中元素被访问的顺序取决于集合的类型。如果对ArrayList进行访问,迭代器将从索引0开始,每迭代一次,索引值加1。然而,如果访问HashSet中的元素,每个元素将会按照某种随机的次序出现。虽然可以确定在迭代过程中能够遍历到集合中的所有元素,但却无法预知元素被访问的次序。

    代码实例:ArrayListDemo

    View Code

    2.3LinkedList

    LinkedList是一种可以在任何位置进行高效地插入和删除操作的有序序列。

    代码实例:LinkedListTest

    View Code

     2.4HashMap

    参考之前的一篇博客:Hashmap实现原理

     

     2.5WeekHashMapDemo

    View Code

    输出结果

    View Code

     疑问:为什么value没有被回收。

     

    3.比较

        是否有序 是否允许元素重复
    Collection
    List
    Set AbstractSet
      HashSet
      TreeSet 是(用二叉排序树)
    Map AbstractMap 使用key-value来映射和存储数据,key必须唯一,value可以重复
      HashMap
      TreeMap 是(用二叉排序树)

     


    展开全文
  • java集合框架详解

    千次阅读 2016-06-04 12:40:28
    详解Java集合框架 List结构的集合类 ArrayList类,LinkedList类,Vector类,Stack类 ArrayList集合类的使用方法(无同步性,线程不安全) style="white-space:pre"> //ArrayList --- 实现了List接口,ArrayList是...
    详解Java集合框架

    Java集合框架

    List结构的集合类

    ArrayList类,LinkedList类,Vector类,Stack类

    ArrayList集合类的使用方法(无同步性,线程不安全)

    <span style="white-space:pre">        </span>//ArrayList --- 实现了List接口,ArrayList是容量大小可变的数组的实现  
            ArrayList al = new ArrayList();  
            //将元素添加到al集合中的尾部  
            String str1 = "a";  
            al.add(str1);  
            String str2 = "b";  
            al.add(str2);  
            //将元素添加到al集合中的指定位置  
            String str3 = "c";  
            al.add(0, str3);  
            //可以添加重复元素  
            al.add(str1);  
            al.add(str2);  
            //按下标移除元素  
            al.remove(0);  
            //按元素移除集合中指定元素,PS:如果该元素在集合中不止一个,移除的元素是正序第一个匹配到的元素  
            al.remove(str2);  
            //遍历输出  
            for(int i = 0; i < al.size(); i++){  
                //按下标获取元素,PS:因为get()方法返回的是Object类型的数据,所以要强制类型转换  
                String tmp = (String)al.get(i);  
                System.out.print(tmp + " ");  
            }  
            System.out.println();  
            //擦除集合中所有元素  
            al.removeAll(al);  

    LinkedList集合类的使用方法

    <span style="white-space:pre">        </span>//LinkedList --- 实现的接口比较多,用的较多的是它的双端队列的特性  
            LinkedList ll = new LinkedList();  
            //上述ArrayList所使用的方法LinkedList都能使用  
            //除此之外,还有以下这些  
    
            //将元素添加到集合的首部  
            ll.addFirst(str1);  
            //将元素添加到集合的尾部  
            ll.addLast(str2);  
            ll.addLast(str3);  
            ll.addLast(str1);  
            ll.addLast(str2);  
            ll.addLast(str3);  
            ll.addLast(str1);  
            //移除集合首部元素  
            ll.removeFirst();  
            ll.remove();  
            //移除集合尾部元素  
            ll.removeLast();  
            //移除与指定元素相同的,从首部到尾部之间第一个元素  
            ll.removeFirstOccurrence(str1);  
            //移除与指定元素相同的,从首部到尾部之间最后一个元素  
            ll.removeLastOccurrence(str2);  
            //获取首部元素  
            ll.getFirst();  
            //获取尾部元素  
            ll.getLast();  
            //移除所有元素  
            ll.removeAll(ll);  

    Vector集合类的使用方法(线程安全具有同步性)

    <span style="white-space:pre">        </span>//Vector --- Vector可以实现可增长的对象数组,Vector的大小可以根据需要增大或缩小,以适应创建 Vector后进行添加或移除项的操作。   
            Vector v = new Vector();  
            //上述ArrayList所使用的方法Vector都能使用  
            //除此之外,还有以下这些  
            //添加一个组件到向量向量末尾  
            v.addElement(str1);  
            v.addElement(str2);  
            //返回向量当前的大小  
            v.capacity();  
            //判断向量是否为空  
            v.isEmpty();  
            //获取首部组件  
            v.firstElement();  
            //获取尾部组件  
            v.lastElement();  
            //扩大该向量的大小  
            v.ensureCapacity(5);  
            //移除指定位置的组件  
            v.removeElementAt(0);  
            //移除正序第一个与指定组件相同的组件  
            v.removeElement(str1);  
            //移除所有组件,并将向量大小设置为0  
            v.removeAllElements();  

    Stack集合类(栈)的使用方法

    <span style="white-space:pre">        </span>//Stack --- Stack表示栈结构。继承至 Vector。  
            //它提供了push和 pop操作,以及取堆栈顶点的 peek方法、测试栈是否为空的empty方法、在栈中查找项并确定到栈顶距离的search方法。   
            Stack s = new Stack();  
            //压栈方法  
            s.push(str1);  
            s.push(str2);  
            s.push(str3);  
            //取栈顶元素方法  
            s.peek();  
            //出栈方法  
            s.pop();  
            //测试堆栈是否为空的方法  
            s.empty();  
            //在栈中查找项并确定到栈顶距离的方法,PS:返回值以1为栈顶基数,-1为未找到  
            System.out.println(s.search(str1));  

    ArrayList和Vector的区别

    ArrayList与Vector都是java的集合类,都可以用来存放java对象,这是他们的相同点,但是他们也有区别:

    1、同步性

    Vector是线程同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是线程异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。

    2、数据增长

    从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。

    Map结构的集合类

    HashMap类,Hashtable类

    HashMap集合类的使用方法

    <span style="white-space:pre">        </span>//Map结构常用的集合类  
            //HashMap --- 此实现假定哈希函数将元素适当地分布在各桶之间,其取出和存入的时间复杂度非常低,为常数级别,PS:不同存在相同键  
            HashMap hm = new HashMap();  
            //放入键值对  
            int num1 = 1;  
            hm.put(num1, str1);  
            //如果键以存在,则替换该键值对  
            hm.put(num1, str2);  
            int num2 = 2;  
            hm.put(num2, str2);  
            int num3 = 3;  
            hm.put(num3, str3);  
            //通过键获取相应值  
            hm.get(num1);  
            //通过键判断集合是否存在该键值对  
            hm.containsKey(num1);  
            //通过值判断集合是否存在该键值对  
            hm.containsValue(str1);  
    
            //利用迭代器遍历集合中的所有键值对  
            //keySet()返回此映射中所包含的键的Set视图  
            //iterator()返回在此 set中的元素上进行迭代的迭代器  
            Iterator it = hm.keySet().iterator();  
            //hasNext()如果仍有元素可以迭代,则返回 true。  
            while(it.hasNext()){  
                //取出key  
                //next()返回迭代的下一个元素。   
                //toString()返回String类型数据,PS:这里不能强制类型转换成String  
                int key = Integer.parseInt(it.next().toString());  
                //通过key获取value  
                String tmp = (String)hm.get(key);  
                //输出value  
                System.out.print(tmp + " ");  
            }  
            System.out.println();  

    Hashtable集合类的使用(Hashtable具有同步性,线程安全)

    <span style="white-space:pre">        </span>//HashTable --- Hashtable具有同步性,线程安全  
            //HashTable在用法上和HashMap基本相似  
            Hashtable ht = new Hashtable();  
            //放入空值会报错  
            //ht.put(null, null);  
            //测试此哈希表是否没有键映射到值。  
            ht.isEmpty();  

    HashMap和Hashtable集合类的区别

    HashMap与Hashtable都是java的集合类,都可以用来存放java对象,这是他们的相同点,但是他们也有区别。

    1、历史原因

    Hashtable是基于陈旧的Dictionary类的,HashMap是java 1.2引进的Map接口的一个实现。

    2、同步性

    Hashtable是线程同步的。这个类中的一些方法保证了Hashtable中的对象是线程安全的。而HashMap则是线程异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。

    3、值

    HashMap可以让你将空值作为一个表的条目的key或value但是Hashtable是不能放入空值的(null)

    进一步理解集合框架

    java的设计者给我们提供了这些集合类,在后面编程中是相当有用的,具体什么时候用什么集合,要根据我们刚才分析的集合异同来选取。

    如何选用集合类?

    1. 要求线程安全,使用VectorHashtable
    2. 不要求线程安全,使用ArrayList,LinkedList,HashMap
    3. 要求key和value键值,则使用HashMap,Hashtable
    4. 数据量很大,又要线程安全,则使用Vector
    Set结构的集合类

    HashSet类,TreeSet类

    • HashSet是基于HashMap实现的,HashSet底层采用HashMap来保存所有元素。
    • hashCodeequal()HashMap用的,因为无需排序所以只需要关注定位和唯一性即可
    • hashCode是用来计算hash值的,hash值是用来确定hash表索引的

    hash表中的一个索引存放的是一张链表,所以还要通过equal方法循环比较链上的每一个对象才可以真正定位到键值对应的Entry

    put时,如果hash表中没定位到,就在链表前加一个Entry,如果定位到了,则更换Entry中的value(值)并返回旧value(值)

    覆写keyhashCode()equal()时一定要注意,不要把它们和可变属性关联上,否则属性变了之后hashCode会变,equal也会为false,这样在Map中就找不到它了,而且这样的对象因为找不到它,所以得不到释放,这样就变成了一个无效引用。(相当于内存泄漏)

    HashSet集合类的使用方法

    <span style="white-space:pre">        </span>//Set结构常用的集合类  
            //HashSet --- 以HashMap为底层  
    //HashSet中无get方法,只能通过迭代器获取键  
            HashSet hs = new HashSet();  
            //添加键到集合尾部  
            hs.add(str1);  
            hs.add(str2);  
            hs.add(str3);  
            //自动去掉重复元素,PS:其实也是像HashMap一样,用新键覆盖旧键  
            hs.add(str1);  
            //返回包含全部键的Object类型数组  
            Object[] o = hs.toArray();  
            for(int i = 0; i < o.length; i++){  
                System.out.print(o[i] + " ");  
            }  
            System.out.println();  

    TreeSet集合类是一个有序集合,它的元素按照升序排序,默认是自然顺序排列,也就是说TreeSet中的对象元素需要实现Comparable接口。TreeSet与HashSet类一样没有get()方法来获取列表中的元素,所以也只能通过迭代器方法来获取。

    由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较,当然也是用Comparator定位的Comparator可以在创建TreeMap时指定,这时排序时使用Comparator.compare,如果创建时没有指定Comparator那么就会使用key.compareTo()方法,这就要求key必须实现Comparable接口。

    TreeMap是使用Tree数据结构实现的,所以使用compare接口就可以完成定位了。
    TreeSet是依靠TreeMap来实现的。

    TreeSet集合类的使用方法

    <span style="white-space:pre">        </span>//TreeSet --- 使用元素的自然顺序对元素进行排序,PS:自然顺序是升序,或者根据创建 set时提供的 Comparator进行排序,具体取决于使用的构造方法  
            TreeSet ts = new TreeSet();  
            //添加键到集合  
            ts.add(str1);  
            ts.add(str2);  
            ts.add(str3);  
            //迭代器遍历  
            for(it = ts.iterator(); it.hasNext();){  
                String tmp = it.next().toString();  
                System.out.print(tmp + " ");  
            }  
            System.out.println();  
            //返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。  
            ts.floor(str2);  
            //返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。  
            ts.ceiling(str2);  
            //返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。  
            ts.lower(str2);  
            //返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。  
            ts.higher(str2);  
            //获取并移除第一个(最低)元素;如果此 set为空,则返回 null。  
            ts.pollFirst();  
            //获取并移除最后一个(最高)元素;如果此 set为空,则返回 null。  
            ts.pollLast();  

    HashSet与TreeSet集合类的区别:

    HashSet是基于hash算法实现的,性能优于TreeSet。通常使用HashSet,在我们需要对其中元素排序的时候才使用TreeSet。

    Queue结构的集合

    Queue接口

    Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。BlockingQueue继承了Queue接口。

    队列是一种数据结构。它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素。就是说,队列以一种先进先出的方式管理数据,如果你试图向一个已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞。

    在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个慢,则第二个线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个线程集赶上来。

    • add:增加一个元索。 如果队列已满,则抛出一个IIIegaISlabEepeplian异常;
    • remove: 移除并返回队列头部的元素。 如果队列为空,则抛出一个NoSuchElementException异常;
    • element: 返回队列头部的元素。 如果队列为空,则抛出一个NoSuchElementException异常;
    • offer:添加一个元素并返回true。如果队列已满,则返回false;
    • poll:移除并返问队列头部的元素。如果队列为空,则返回null;
    • peek:返回队列头部的元素。如果队列为空,则返回null;
    • put:添加一个元素。如果队列满,则阻塞;
    • take:移除并返回队列头部的元素。如果队列为空,则阻塞。

    removeelementofferpollpeek 其实是属于Queue接口。

    阻塞队列的操作可以根据它们的响应方式分为以下三类:addremoveelement操作在你试图为一个已满的队列增加元素或从空队列取得元素时 抛出异常。当然,在多线程程序中,队列在任何时间都可能变成满的或空的,所以你可能想使用offerpollpeek方法。这些方法在无法完成任务时 只是给出一个出错示而不会抛出异常。

    注意: pollpeek方法出错进返回null。因此,向队列中插入null值是不合法的。

    offer,add区别:

    一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。这时新的 offer方法就可以起作用了。它不是对调用add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false

    poll,remove区别:

    remove()poll()方法都是从队列中删除第一个元素(head)。remove()的行为与Collection 接口的版本相似,但是新的poll()方法在用空集合调用时不是抛出异常,只是返回null。因此新的方法更适合容易出现异常条件的情况。

    peek,element区别:

    element()peek()用于在队列的头部查询元素。与 remove()方法类似,在队列为空时,element()抛出一个异常,而peek()返回null

    五个队列所提供的各有不同:

    • ArrayBlockingQueue :一个由数组支持的有界队列。基于数组的阻塞循环队列,先进先出原则对元素进行排序。

    • LinkedBlockingQueue:一个由链接节点支持的可选有界队列。基于链表的队列,先进先出排序元素。

    • PriorityBlockingQueue:一个由优先级堆支持的无界优先级队列。PriorityBlockingQueue是对PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞队列上put时是不会受阻的。但是由于资源被耗尽,所以试图执行添加操作可能会导致OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元素要具有比较能力。

    • DelayQueue:一个由优先级堆支持的、基于时间的调度队列。(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用null元素。

    • SynchronousQueue:一个利用 BlockingQueue接口的简单聚集(rendezvous)机制。SynchronousQueue 类是最简单的。它没有内部容量。它就像线程之间的手递手机制。在队列中加入一个元素的生产者会等待另一个线程的消费者。当这个消费者出现时,这个元素就直接在消费者和生产者之间传递,永远不会加入到阻塞队列中。

    注意: Queue队列是不能直接实例化的。

    总结

    Java中的List/Set和Map的区别:

    List按对象进入的顺序保存对象,不做排序和编辑操作。

    Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set而不关心它的顺序--否则使用List)。

    Map同样对每个元素保存一份,但这是基于"键"(key)的,Map也有内置的排序,因而不关心元素添加的顺序。

    如果添加元素的顺序对程序设计很重要,应该使用LinkedHashSet或者LinkedHashMap。

    List的功能方法

    实际上有两种List:一种是基本的ArrayList其优点在于随机访问元素,另一种是更强大的LinkedList它并不是为快速随机访问设计的,而是具有一套更通用的方法。

    List:次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推荐LinkedList使用)一个List可以生成Listlterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元素。

    ArrayList:由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速率很慢。Listlterator只应该用来由后向前遍历ArrayList。而不是用来插入和移除元素。因为那比LinkedList开销要大很多。

    LinkedList:对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。(使用ArrayList代替)还具有下列方法:addFirst()addLast()getFirst()getLast()removeFirst()removeLast()这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。

    Set的功能方法

    Set具有与Collection完全一样的接口,因此没有任何额外的功能,不象前面有两个不同的List。实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责)

    Set:存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必需定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。

    HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。

    TreeSet:保存次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。

    LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

    Map的功能方法

    方法put(Object key,Object value)添加一个"值"(想要得东西)和与"值"相关的"键"(key)(使用它来查找)。方法get(Object key)返回与给定"键"相关联的"值"。可以用containsKey()containsValue()测试Map中是否包含某个"键"或"值"。标准的java类库中包含了几种不同的Map:HashMap,TreeMap,LinkedHashMap,WeakHashMap,ldentityHashMap。它们都有同样的基本接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定"键"等价的策略等各不相同。

    执行效率是Map的一个大问题。看看get()要做哪些事,就会明白为什么在ArrayList中搜索"键"是相当慢的。这正是HashMap提高速度的地方。HashMap使用了特殊的值,称为"散列码"(hash code),来取代对键的缓慢搜索。"散列码"是"相对唯一"用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有java对象都能产生散列码,因为hashCode()是定义在基类Object中的方法。

    HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显著提高性能。

    Map:维护"键值对"的关联性,使你可通过"键"查找"值"

    HashMap: Map基于散列表的实现。插入和查询"键值对"的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。

    LinkedHashMap:类似于HashMap,但是迭代遍历它时,取得"键值对"的顺序是其插入次序,或者是最近最少使(LRU)的次序。只能HashMap慢一点。而在迭代访问时发而更快,因为它使用键表维护内部次序。

    TreeMap:基于红黑树数据结果的实现。查看"键"或"键值对"时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。

    -------------参考《韩顺平.循序渐进学.java.从入门到精通》

    -------------参考《JDK_API_1_6_zh_CN》

    Java学习笔记--导航http://blog.csdn.net/q547550831/article/details/49819641


    展开全文
  • Java集合框架关系图

    万次阅读 2019-03-10 18:51:45
    集合的特点: 集合用来存储不同类型的对象(基本数据类型除外),存储长度可变。...集合框架图: 上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,...

    集合的特点:

    集合用来存储不同类型的对象(基本数据类型除外),存储长度可变。
    Java集合中实际存放的只是对象的引用,每个集合元素都是一个引用变量,实际内容都放在堆内存或者方法区里面,但是基本数据类型是在栈内存上分配空间的,栈上的数据随时就会被收回的。

     

    集合框架图:

    上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等。

    再附上一个稍微简单些的

    1、Iteraor接口

    (迭代器接口)用于遍历集合中元素的接口,主要包含三种方法:

    boolean hasNext()
    E next()
    void remove()
    

    它的一个子接口ListIterator在它的基础上又添加了三种方法:

    void add()
    E previous()
    boolean hasPrevious()
    

    也就是说如果实现Iterator接口,那么在遍历集合中元素的时候,只能往后遍历,被遍历过的元素不会再遍历到,通常无序集合实现的都是这个接口,比如HashSet,HashMap;
    而实现了ListIterator接口的集合,可以双向遍历,既可以通过next()访问下一个元素,又可以通过previous()访问前一个元素,比如List。

    Iterator和Iterable的区别:
    1). Iterator是迭代器接口,而Iterable是为了只要实现该接口就可以使用foreach进行迭代。

    2). Iterable中封装了Iterator接口,只要实现了Iterable接口的类,就可以使用Iterator迭代器了。

    3). 集合Collection、List、Set都是Iterable的实现类,所以他们及其他们的子类都可以使用foreach进行迭代。

    4). Iterator中核心的方法next()、hasnext()、remove()都是依赖当前位置,如果这些集合直接实现Iterator,则必须包括当前迭代位置的指针。当集合在方法间进行传递的时候,由于当前位置不可知,所以next()之后的值,也不可知。而实现Iterable则不然,每次调用都返回一个从头开始的迭代器,各个迭代器之间互不影响。

     

    2、Collection (集合的最大接口)继承关系

    Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行,一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”,如List和Set。
    所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection;有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。
    (1)List:有序,可以存放重复的内容
    (2)Set:无序,不能存放重复的内容,所以的重复内容靠hashCode()和equals()两个方法区分
    (3)Queue:队列接口
    (4)SortedSet:可以对集合中的数据进行排序

    Collection定义了集合框架的共性功能。

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

    • List接口

    按照元素插入的顺序进行存放,元素可以重复。
    其定义的方法包括:

    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean addAll(int index, Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    void clear();
    boolean equals(Object o);
    int hashCode();
    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
    E remove(int index);
    int indexOf(Object o);
    int lastIndexOf(Object o);
    ListIterator<E> listIterator();
    ListIterator<E> listIterator(int index);
    List<E> subList(int fromIndex, int toIndex);

    实现List的子类的特点:
    ——ArrayList:线程不安全,查询速度快。底层都是基于数组来储存集合元素,封装了一个动态的Object[]数组,是一种顺序存储的线性表。
    ——Vector:线程安全,但速度慢,已被ArrayList替代。
    ——LinkedList:线程不安全,增删速度快,没有同步方法,是一个链式存储的线性变,本质上是一个双向链表。
    ——Stack: (已经不用,可由LinkedList代替)。

     

    • Set接口

    Set接口也是Collection的一种扩展,而与List不同的是,在Set中的对象元素不能重复,也就是说你不能把同样的东西两次放入同一个Set容器中。它的常用具体实现有HashSet和TreeSet类。
    HashSet能快速定位一个元素,但是你放到HashSet中的对象需要实现hashCode()方法,它使用了前面说过的哈希码的算法。
    TreeSet则将放入其中的元素按序存放,这就要求你放入其中的对象是可排序的,这就用到了集合框架提供的另外两个实用接口Comparable和Comparator。一个类是可排序的,它就应该实现Comparable接口。有时多个类具有相同的排序算法,那就不需要再分别重复定义相同的排序算法,只要实现Comparator接口即可。
    Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
    很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
    请注意:必须小心操作可变对象(MutableObject)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean retainAll(Collection<?> c);
    boolean removeAll(Collection<?> c);
    void clear();
    boolean equals(Object o);
    int hashCode();

     

    • SortedSet接口(实现了Set接口)

    其实这就是个Set接口的输出接口

    //普通    返回排序有关联的比较器
    public Comparator<? super E>                
    //普通    返回集合中的第一个元素
    public E first()                    
    //普通    返回从开始到指定元素的集合
    public SortedSet<E> headSet(E toElement)        
    //普通    返回最后一个元素
    public E last()
    //普通    返回指定对象间的元素
    public SortedSet<E> subSet(E fromElement,E toElement)    
    //普通    从指定元素到最后
    public SortedSet<E> tailSet(E fromElement)

    实现Set接口子类的特点:
    ——HashSet:底层数据结构由HashMap的键来实现。不保证集合中元素的顺序,即不能保证迭代的顺序与插入的顺序一致。是线程不安全的。
    ——TreeSet:有序的存放,线程不安全,可以对Set集合中的元素进行排序,由红黑树来实现排序,TreeSet实际上也是SortedSet接口的子类,其在方法中实现了SortedSet的所有方法,并使用comparator()方法进行排序。
    ——LinkedHashSet:底层由链表实现,按照元素插入的顺序进行迭代,即迭代输出的顺序与插入的顺序保持一致

     

    3、Map接口

    Map是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求。你可以将任意多个键都映射到一个值对象上,这不会发生任何问题(不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象)。
    请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
    注意:由于Map中作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。

    实现Map接口的子类:
    ——Hashtable:Hashtable继承Dictionary<K,V>类,实现了Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。是同步的。
    ——HashMap:HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。
    但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。
    ——LinkedHashMap:是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现。Key和Value都允许空;Key重复会覆盖、Value允许重复;非线程安全;有序。
    ——TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。

     

    4、Collections和Collection有什么区别?

    Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
    它有两个常用的子接口:
    ——List:对元素都有定义索引。有序的。可以重复元素。
    ——Set:不可以重复元素。无序。

    Collections是集合框架中的一个工具类。该类中的方法都是静态的。提供的方法中有可以对list集合进行排序,二分查找等方法。通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

     

    参考:https://blog.csdn.net/biexiaofei/article/details/77031003

               https://blog.csdn.net/snow_7/article/details/51791112

     

     

    展开全文
  • Java集合框架

    千次阅读 2018-09-03 01:58:51
    学习Java集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映射、迭代器(Iterator、Enumeration)、工具类(Arrays、Collections)。 一、集合框架图 Java集合类的整体框架如下:   ...

    Java集合工具包位于Java.util包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表等。学习Java集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映射、迭代器(Iterator、Enumeration)、工具类(Arrays、Collections)。

    一、集合框架图

    Java集合类的整体框架如下:

                          

    简化图:

    说明:对于以上的框架图有如下几点说明

    1. 所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。
    2. 集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。
    3. 抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。
    4. 实现类:8个实现类(实线表示),对接口的具体实现。
    5.  Collection 接口是一组允许重复的对象。
    6. Set 接口继承 Collection,集合元素不重复。
    7.  List 接口继承 Collection,允许重复,维护元素插入顺序。
    8.  Map接口是键-值对象,与Collection接口没有什么关系。
    9. Set、List和Map可以看做集合的三大类:
    • List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。
    • Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。
    • Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。

    二、总体分析

    大致说明:
    看上面的框架图,先抓住它的主干,即Collection和Map

    1、Collection是一个接口,是高度抽象出来的集合,它包含了集合的基本操作和属性。Collection包含了List和Set两大分支。
    (1)List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。List的实现类有LinkedList, ArrayList, Vector, Stack。

    (2)Set是一个不允许有重复元素的集合。Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。

    2、Map是一个映射接口,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。AbstractMap是个抽象类,它实现了Map接口中的大部分API。而HashMap,TreeMap,WeakHashMap都是继承于AbstractMap。Hashtable虽然继承于Dictionary,但它实现了Map接口。

    3、接下来,再看Iterator。它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。我们说Collection依赖于Iterator,是因为Collection的实现类都要实现iterator()函数,返回一个Iterator对象。ListIterator是专门为遍历List而存在的。

    4、再看Enumeration,它是JDK 1.0引入的抽象类。作用和Iterator一样,也是遍历集合;但是Enumeration的功能要比Iterator少。在上面的框图中,Enumeration只能在Hashtable, Vector, Stack中使用。

    5、最后,看Arrays和Collections。它们是操作数组、集合的两个工具类。

    有了上面的整体框架之后,我们接下来对每个类分别进行分析。 

    三、Collection接口

    Collection接口是处理对象集合的根接口,其中定义了很多对元素进行操作的方法。Collection接口有两个主要的子接口List和Set,注意Map不是Collection的子接口,这个要牢记。
    Collection接口中的方法如下:

                                                  

    其中,有几个比较常用的方法,比如方法add()添加一个元素到集合中,addAll()将指定集合中的所有元素添加到集合中,contains()方法检测集合中是否包含指定的元素,toArray()方法返回一个表示集合的数组。

    另外,Collection中有一个iterator()函数,它的作用是返回一个Iterator接口。通常,我们通过Iterator迭代器来遍历集合。ListIterator是List接口所特有的,在List接口中,通过ListIterator()返回一个ListIterator对象。

    Collection接口有两个常用的子接口,下面详细介绍。

    1.List接口

    List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。

    List接口继承于Collection接口,它可以定义一个允许重复的有序集合。因为List中的元素是有序的,所以我们可以通过使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。

    List接口为Collection直接接口。List所代表的是有序的Collection,即它用某种特定的插入顺序来维护元素顺序。用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。

    (1)ArrayList

          ArrayList是一个动态数组,也是我们最常用的集合。它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小。随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。

          size、isEmpty、get、set、iterator 和 listIterator 操作都以固定时间运行。add 操作以分摊的固定时间运行,也就是说,添加 n 个元素需要 O(n) 时间(由于要考虑到扩容,所以这不只是添加元素会带来分摊固定时间开销那样简单)。

          ArrayList擅长于随机访问。同时ArrayList是非同步的。

    (2)LinkedList

          同样实现List接口的LinkedList与ArrayList不同,ArrayList是一个动态数组,而LinkedList是一个双向链表。所以它除了有ArrayList的基本操作方法外还额外提供了get,remove,insert方法在LinkedList的首部或尾部。

          由于实现的方式不同,LinkedList不能随机访问,它所有的操作都是要按照双重链表的需要执行。在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这样做的好处就是可以通过较低的代价在List中进行插入和删除操作。

          与ArrayList一样,LinkedList也是非同步的。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List: 
    List list = Collections.synchronizedList(new LinkedList(...));

    (3)Vector

          与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样。

    (4)Stack

         Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

             

    2.Set接口

         Set是一种不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。与List一样,它同样允许null的存在但是仅有一个。由于Set接口的特殊性,所有传入Set集合中的元素都必须不同,同时要注意任何可变对象,如果在对集合中元素进行操作时,导致e1.equals(e2)==true,则必定会产生某些问题。Set接口有三个具体实现类,分别是散列集HashSet、链式散列集LinkedHashSet和树形集TreeSet。

         Set是一种不包含重复的元素的Collection,无序,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。需要注意的是:虽然Set中元素没有顺序,但是元素在set中的位置是由该元素的HashCode决定的,其具体位置其实是固定的。

         此外需要说明一点,在set接口中的不重复是有特殊要求的。
         举一个例子:对象A和对象B,本来是不同的两个对象,正常情况下它们是能够放入到Set里面的,但是如果对象A和B的都重写了hashcode和equals方法,并且重写后的hashcode和equals方法是相同的话。那么A和B是不能同时放入到Set集合中去的,也就是Set集合中的去重和hashcode与equals方法直接相关。 

      为了更好地理解,请看下面的例子:

    public class Test{ 
    public static void main(String[] args) { 
         Set<String> set=new HashSet<String>(); 
         set.add("Hello"); 
         set.add("world"); 
         set.add("Hello"); 
         System.out.println("集合的尺寸为:"+set.size()); 
         System.out.println("集合中的元素为:"+set.toString()); 
      } 
    }

    运行结果:

    集合的尺寸为:2
    集合中的元素为:[world, Hello]

    分析:由于String类中重写了hashcode和equals方法,用来比较指向的字符串对象所存储的字符串是否相等。所以这里的第二个Hello是加不进去的。

    再看一个例子:

    public class TestSet {
        
        public static void main(String[] args){
            
            Set<String> books = new HashSet<String>();
            //添加一个字符串对象
            books.add(new String("Struts2权威指南"));
            
            //再次添加一个字符串对象,
            //因为两个字符串对象通过equals方法比较相等,所以添加失败,返回false
            boolean result = books.add(new String("Struts2权威指南"));
            
            System.out.println(result);
            
            //下面输出看到集合只有一个元素
            System.out.println(books);    
    
        }
    }

    运行结果:

    false
    [Struts2权威指南]

    说明:程序中,book集合两次添加的字符串对象明显不是一个对象(程序通过new关键字来创建字符串对象),当使用==运算符判断返回false,使用equals方法比较返回true,所以不能添加到Set集合中,最后只能输出一个元素。

    (1)HashSet

         HashSet 是一个没有重复元素的集合。它是由HashMap实现的,不保证元素的顺序(这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致),而且HashSet允许使用null 元素。HashSet是非同步的,如果多个线程同时访问一个哈希set,而其中至少一个线程修改了该set,那么它必须保持外部同步。 HashSet按Hash算法来存储集合的元素,因此具有很好的存取和查找性能。

    HashSet的实现方式大致如下,通过一个HashMap存储元素,元素是存放在HashMap的Key中,而Value统一使用一个Object对象。

    HashSet使用和理解中容易出现的误区:

    a.HashSet中存放null值
      HashSet中是允许存入null值的,但是在HashSet中仅仅能够存入一个null值。

    b.HashSet中存储元素的位置是固定的
      HashSet中存储的元素的是无序的,这个没什么好说的,但是由于HashSet底层是基于Hash算法实现的,使用了hashcode,所以HashSet中相应的元素的位置是固定的。
      
    c.必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

    (2)LinkedHashSet

          LinkedHashSet继承自HashSet,其底层是基于LinkedHashMap来实现的,有序,非同步。LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。

    (3)TreeSet

         TreeSet是一个有序集合,其底层是基于TreeMap实现的,非线程安全。TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。当我们构造TreeSet时,若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。

    注意:TreeSet集合不是通过hashcode和equals函数来比较元素的.它是通过compare或者comparaeTo函数来判断元素是否相等.compare函数通过判断两个对象的id,相同的id判断为重复元素,不会被加入到集合中。

    四、Map接口

         Map与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。同时它也没有继承Collection。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它不能存在相同的key值,当然value值可以相同。

    1.HashMap

          以哈希表数据结构实现,查找对象时通过哈希函数计算其位置,它是为快速查询而设计的,其内部定义了一个hash表数组(Entry[] table),元素会通过哈希转换函数将元素的哈希地址转换成数组中存放的索引,如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构。

    2.LinkedHashMap

         LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。
         LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
         LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
         根据链表中元素的顺序可以分为:按插入顺序的链表,和按访问顺序(调用get方法)的链表。默认是按插入顺序排序,如果指定按访问顺序排序,那么调用get方法后,会将这次访问的元素移至链表尾部,不断访问可以形成按访问顺序排序的链表。
         注意,此实现不是同步的。如果多个线程同时访问链接的哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须保持外部同步。
         由于LinkedHashMap需要维护元素的插入顺序,因此性能略低于HashMap的性能,但在迭代访问Map里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。

    3.TreeMap

         TreeMap 是一个有序的key-value集合,非同步,基于红黑树(Red-Black tree)实现,每一个key-value节点作为红黑树的一个节点。TreeMap存储时会进行排序的,会根据key来对key-value键值对进行排序,其中排序方式也是分为两种,一种是自然排序,一种是定制排序,具体取决于使用的构造方法。

    自然排序:TreeMap中所有的key必须实现Comparable接口,并且所有的key都应该是同一个类的对象,否则会报ClassCastException异常。

    定制排序:定义TreeMap时,创建一个comparator对象,该对象对所有的treeMap中所有的key值进行排序,采用定制排序的时候不需要TreeMap中所有的key必须实现Comparable接口。

    TreeMap判断两个元素相等的标准:两个key通过compareTo()方法返回0,则认为这两个key相等。

    如果使用自定义的类来作为TreeMap中的key值,且想让TreeMap能够良好的工作,则必须重写自定义类中的equals()方法,TreeMap中判断相等的标准是:两个key通过equals()方法返回为true,并且通过compareTo()方法比较应该返回为0。

                          

    五、Iterator 与 ListIterator详解

    1.Iterator

    Iterator的定义如下:

    public interface Iterator<E> {}

    Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下:

    boolean hasNext():判断集合里是否存在下一个元素。如果有,hasNext()方法返回 true。
    Object next():返回集合里下一个元素。
    void remove():删除集合里上一次next方法返回的元素。

    使用示例

    public class IteratorExample {
        public static void main(String[] args) {
            ArrayList<String> a = new ArrayList<String>();
            a.add("aaa");
            a.add("bbb");
            a.add("ccc");
            System.out.println("Before iterate : " + a);
            Iterator<String> it = a.iterator();
            while (it.hasNext()) {
                String t = it.next();
                if ("bbb".equals(t)) {
                    it.remove();
                }
            }
            System.out.println("After iterate : " + a);
        }
    }

    输出结果如下:

    Before iterate : [aaa, bbb, ccc]
    After iterate : [aaa, ccc]

    注意:

    (1)Iterator只能单向移动。

    (2)Iterator.remove()是唯一安全的方式来在迭代过程中修改集合;如果在迭代过程中以任何其它的方式修改了基本集合将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个异常。

    2.ListIterator

    ListIterator是一个功能更加强大的迭代器, 它继承于Iterator接口,只能用于各种List类型的访问。可以通过调用listIterator()方法产生一个指向List开始处的ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator.

    ListIterator接口定义如下:

    public interface ListIterator<E> extends Iterator<E> {
        boolean hasNext();
     
        E next();
     
        boolean hasPrevious();
     
        E previous();
     
        int nextIndex();
     
        int previousIndex();
     
        void remove();
     
        void set(E e);
     
        void add(E e);
         
    }

    由以上定义我们可以推出ListIterator可以:

    (1)双向移动(向前/向后遍历).

    (2)产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引.

    (3)可以使用set()方法替换它访问过的最后一个元素.

    (4)可以使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素.

    使用示例:

    public class ListIteratorExample {
     
        public static void main(String[] args) {
            ArrayList<String> a = new ArrayList<String>();
            a.add("aaa");
            a.add("bbb");
            a.add("ccc");
            System.out.println("Before iterate : " + a);
            ListIterator<String> it = a.listIterator();
            while (it.hasNext()) {
                System.out.println(it.next() + ", " + it.previousIndex() + ", " + it.nextIndex());
            }
            while (it.hasPrevious()) {
                System.out.print(it.previous() + " ");
            }
            System.out.println();
            it = a.listIterator(1);
            while (it.hasNext()) {
                String t = it.next();
                System.out.println(t);
                if ("ccc".equals(t)) {
                    it.set("nnn");
                } else {
                    it.add("kkk");
                }
            }
            System.out.println("After iterate : " + a);
        }
    }

    输出结果如下:

    Before iterate : [aaa, bbb, ccc]
    aaa, 0, 1
    bbb, 1, 2
    ccc, 2, 3
    ccc bbb aaa 
    bbb
    ccc
    After iterate : [aaa, bbb, kkk, nnn]

    六、异同点

    1.ArrayList和LinkedList

    (1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
    (2)对于随机访问get和set,ArrayList绝对优于LinkedList,因为LinkedList要移动指针。 
    (3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 
    这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

    2.HashTable与HashMap

    相同点:

    (1)都实现了Map、Cloneable、java.io.Serializable接口。
    (2)都是存储"键值对(key-value)"的散列表,而且都是采用拉链法实现的。

    不同点:

    (1)历史原因:HashTable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现 。
    (2)同步性:HashTable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。
    (3)对null值的处理:HashMap的key、value都可为null,HashTable的key、value都不可为null 。
    (4)基类不同:HashMap继承于AbstractMap,而Hashtable继承于Dictionary。

          Dictionary是一个抽象类,它直接继承于Object类,没有实现任何接口。Dictionary类是JDK 1.0的引入的。虽然Dictionary也支持“添加key-value键值对”、“获取value”、“获取大小”等基本操作,但它的API函数比Map少;而且Dictionary一般是通过Enumeration(枚举类)去遍历,Map则是通过Iterator(迭代M器)去遍历。 然而由于Hashtable也实现了Map接口,所以,它即支持Enumeration遍历,也支持Iterator遍历。
          AbstractMap是一个抽象类,它实现了Map接口的绝大部分API函数;为Map的具体实现类提供了极大的便利。它是JDK 1.2新增的类。
       
    (5)支持的遍历种类不同:HashMap只支持Iterator(迭代器)遍历。而Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。

    3.HashMap、Hashtable、LinkedHashMap和TreeMap比较

         Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。遍历时,取得数据的顺序是完全随机的。HashMap最多只允许一条记录的键为Null;允许多条记录的值为Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。

         Hashtable 与 HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

         LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。对于LinkedHashMap而言,它继承与HashMap、底层使用哈希表与双向链表来保存所有元素。其基本操作与父类HashMap相似,它通过重写父类相关的方法,来实现自己的链接列表特性。

         TreeMap实现SortMap接口,内部实现是红黑树。能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。 


         一般情况下,我们用的最多的是HashMap,HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
         TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
         LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。

    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.TreeMap;
    
    public class MapTest {
    
        public static void main(String[] args) {
    
            //HashMap
            HashMap<String,String> hashMap = new HashMap();
            hashMap.put("4", "d");
            hashMap.put("3", "c");
            hashMap.put("2", "b");
            hashMap.put("1", "a");
    
            Iterator<String> iteratorHashMap = hashMap.keySet().iterator();
    
            System.out.println("HashMap-->");
    
            while (iteratorHashMap.hasNext()){
    
                Object key1 = iteratorHashMap.next();
                System.out.println(key1 + "--" + hashMap.get(key1));
            }
    
            //LinkedHashMap
            LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap();
            linkedHashMap.put("4", "d");
            linkedHashMap.put("3", "c");
            linkedHashMap.put("2", "b");
            linkedHashMap.put("1", "a");
    
            Iterator<String> iteratorLinkedHashMap = linkedHashMap.keySet().iterator();
    
            System.out.println("LinkedHashMap-->");
    
            while (iteratorLinkedHashMap.hasNext()){
    
                Object key2 = iteratorLinkedHashMap.next();
                System.out.println(key2 + "--" + linkedHashMap.get(key2));
            }
    
            //TreeMap
            TreeMap<String,String> treeMap = new TreeMap();
            treeMap.put("4", "d");
            treeMap.put("3", "c");
            treeMap.put("2", "b");
            treeMap.put("1", "a");
    
            Iterator<String> iteratorTreeMap = treeMap.keySet().iterator();
    
            System.out.println("TreeMap-->");
    
            while (iteratorTreeMap.hasNext()){
    
                Object key3 = iteratorTreeMap.next();
                System.out.println(key3 + "--" + treeMap.get(key3));
            }
    
        }
    
    }

    输出结果如下:

    HashMap-->
    3--c
    2--b
    1--a
    4--d
    LinkedHashMap-->
    4--d
    3--c
    2--b
    1--a
    TreeMap-->
    1--a
    2--b
    3--c
    4--d

    4.HashSet、LinkedHashSet、TreeSet比较

    Set接口
    Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。
    Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

    HashSet
    HashSet有以下特点:
    ->  不能保证元素的排列顺序,顺序有可能发生变化。
    ->  不是同步的。
    ->  集合元素可以是null,但只能放入一个null。
        当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等。
        注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

    LinkedHashSet
        LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
        LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

    TreeSet类
        TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
        TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0。
    自然排序
        自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。
        Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是负数,则表明obj1小于obj2。如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0。
    定制排序
        自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(T o1,T o2)方法。

    package com.test;  
      
    import java.util.HashSet;  
    import java.util.LinkedHashSet;  
    import java.util.TreeSet;  
      
    /**  
     * @description 几个set的比较  
     *    HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放;  
     *    LinkedHashSet:以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代;  
     *    TreeSet:提供一个使用树结构存储Set接口的实现,对象以升序顺序存储,访问和遍历的时间很快。  
     * @author Zhou-Jingxian  
     *  
     */  
    public class SetDemo {  
      
        public static void main(String[] args) {  
      
            HashSet<String> hs = new HashSet<String>();  
            hs.add("B");  
            hs.add("A");  
            hs.add("D");  
            hs.add("E");  
            hs.add("C");  
            hs.add("F");  
            System.out.println("HashSet 顺序:\n"+hs);  
              
            LinkedHashSet<String> lhs = new LinkedHashSet<String>();  
            lhs.add("B");  
            lhs.add("A");  
            lhs.add("D");  
            lhs.add("E");  
            lhs.add("C");  
            lhs.add("F");  
            System.out.println("LinkedHashSet 顺序:\n"+lhs);  
              
            TreeSet<String> ts = new TreeSet<String>();  
            ts.add("B");  
            ts.add("A");  
            ts.add("D");  
            ts.add("E");  
            ts.add("C");  
            ts.add("F");  
            System.out.println("TreeSet 顺序:\n"+ts);  
        }  
    }

    输出结果如下:

    HashSet 顺序:[D, E, F, A, B, C]
    LinkedHashSet 顺序:[B, A, D, E, C, F]
    TreeSet 顺序:[A, B, C, D, E, F]

    5、Iterator和ListIterator区别

         我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器)。使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了。但是在使用的时候也是有不同的。List和Set都有iterator()来取得其迭代器。对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:

    (1)ListIterator有add()方法,可以向List中添加对象,而Iterator不能
    (2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
    (3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
    (4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
    因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。

    6、Collection 和 Collections区别

    (1)java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。

     Collection   
    ├List   
    │├LinkedList   
    │├ArrayList   
    │└Vector   
    │ └Stack   
    └Set 
    (2)java.util.Collections 是一个包装类(工具类/帮助类)。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。
    代码示例:

    import java.util.ArrayList; 
    import java.util.Collections; 
    import java.util.List; 
      
    public class TestCollections { 
          
        public static void main(String args[]) { 
            //注意List是实现Collection接口的 
            List list = new ArrayList(); 
            double array[] = { 112, 111, 23, 456, 231 }; 
            for (int i = 0; i < array.length; i++) { 
                list.add(new Double(array[i])); 
            } 
            Collections.sort(list); 
            for (int i = 0; i < array.length; i++) { 
                System.out.println(list.get(i)); 
            } 
            // 结果:23.0 111.0 112.0 231.0 456.0 
        } 
    }

    原文来源:

    https://www.cnblogs.com/xiaoxi/p/6089984.html

     

    展开全文
  • java常用集合及集合框架总结

    千次阅读 2018-06-04 23:33:27
    常见集合框架结构如下图(不是全部,只包含常用的) 1、List 1.1、ArrayList1.2、LinkedList1.3、Vector1.4、List接口下各种接口实现类的比较和应用 2、Set 2.1、HashSet2.2、TreeSet2.3、SortSet2.4、...
  • 集合框架

    2020-05-16 16:36:06
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2IH2DQHN-1589618084726)(http://www.njlife123.com/upload/2020/05/praqdfjm3ki4cpufsr45vv480c.png)] List List的特点:有序(迭代顺序和...
  • 集合框架--集合框架体系概述

    万次阅读 多人点赞 2017-03-09 09:42:56
    集合框架体系主要如上图所示,集合类主要分为两大类:Collection和Map。 先简单概述几个相关问题。 1、先说明下什么是集合?  当数据多了需要存储,需要容器,但是数据的个数又不确定的时候,无法使用数组(数组...
  • 集合的概念以及集合框架的介绍

    千次阅读 2018-07-01 13:36:55
    集合框架是为表示和操作多个对象而规定的一种统一的标准体系结构 任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。 接口:即表示集合的抽象数据类型,接口提供了让我们对集合中所表示...
  • 1.Java集合框架是什么?说出一些集合框架的优点?

    千次阅读 多人点赞 2018-09-27 20:13:38
    1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和Array。随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的...
  • java集合框架总结以及源码分析(一)

    万次阅读 2018-08-25 13:53:44
    一、集合框架总体架构图分析 1、首先我们先来看看一个集合框架的总图,有一个清晰的脉络机构,非常重要,因为不管我们学习那知识点,思路很重要。下面这张张图是我从网上博客摘取的,在此谢谢你精心的绘制。说明一下...
  • 集合框架总结

    2017-10-02 11:54:00
    Collection接口 List接口及实现类 ...java集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。java集合类分为:set、list、map。其中set代表无序、不可重复的集合。list代表有序、可重
  • Map 用于保存具有映射关系的数据,因此 Map 集合里保存着两组值,一组值用于保存 Map 里的 Key,另外一组用于保存 Map 里的 Value Map 中的 key 和 value 都可以是任何引用类型的数据 Map 中的 Key 不允许重复...
  • Java集合框架总结

    万次阅读 多人点赞 2019-08-08 09:13:16
    集合框架:用于存储数据的容器。 集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。 任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。 接口:表示集合的抽象数据类型。接口...
  • Java集合框架学习总结

    千次阅读 2018-06-28 00:18:42
    Java集合类学习总结 这篇总结是基于之前博客内容的一个整理和回顾。 这里先简单地总结一下,更多详细内容请参考我的专栏:深入浅出Java核心技术 里面有包括Java集合类在内的众多Java核心技术系列文章。 ...
  • Java面向对象——集合框架总结

    千次阅读 2014-02-23 15:49:04
    ---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- ...集合体系 Collection(单列) List(有序,可重复) ArrayList: 底层数据结构是数组,查询快,
  • java集合框架总结

    千次阅读 2016-03-02 18:35:46
    Tag2:重点在于集合框架结构分析和底层数据结构实现原理。 一、集合框架结构图 二、分类分析 1、常用List总结 红色编号1:以上四个方法均直接或者间接继承自AbstractList,都可以储存相同数值。其中,...
  • 集合框架总结(一)

    2015-10-18 22:29:51
    集合框架的存在可以解决数组和链表容器的缺点。 集合框架与数组的存储区别: 数组:可存基本类型数据源与对象 集合框架:只能存对象 集合框架体系图: Java集合类主要有两个接口派生而来:...
  • 集合框架的所有常用集合总结

    千次阅读 2018-04-17 23:49:36
    Collection(单列集合) -- List 1. 有序(存取有序) 2. 有索引 3. 可重复 - ArrayList 数组 - LinkedList 链表 - Vector 数组 JDK1.0产物 已经被ArrayList取代 ...
  • Java集合框架知识总结

    2015-04-21 10:08:41
    1、综述: 所有集合类都位于java.util包下,集合中...从JDK1.5后,这种状态得到了改进:可以使用泛型来限制集合里的元素的类型,并让集合记住所有的集合元素的类型。 Java的集合类主要有两个接口派生而出:Col
  • java集合框架总结之思维导图

    千次阅读 2018-03-24 09:36:12
    思维导图
  • java集合框架

    2018-01-31 10:48:46
    集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型。接口允许集合独立操纵其代表的细节。在面向对象的语言,接口通常形成一个层次。 实现(类):是集合...
  • Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体...
  • JAVA中集合框架和泛型重点总结

    千次阅读 2018-07-28 17:16:11
    Java集合框架: Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中。 (Collection是·所有Java集合框架的父接口;Collections操作集合的工具类) Iterator:是迭代器 接口: ...
  • Java集合框架问题总结

    千次阅读 2015-08-27 14:27:59
    1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和Array。随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的...
  • 集合 1,定义:  通常情况下,把具有相同性质的一类东西,汇聚成一个整体,就可以称为集合 2.集合的表示方法:  通常集合有两种表示法, ...集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。
  • 第6章集合框架

    2020-03-21 19:29:16
    第6章集合框架 6.1集合框架概述 6.1.1引入集合框架 1.数组长度固定不变,不能很好的地适应元素的情况。 2.可以通过数组名。length获取数组的长度,无法直接获取数组中的真实存诸狗狗个数。 3.数组采用在内存中分配...
  • java 集合框架和泛型

    2017-09-06 20:58:00
    //常用的集合类: Set(集):集合中的对象不按特定的方式排序,不允许元素重复 List(列表):集合中的对象按照索引位置排序,允许元素重复 Map(映射):集合中每一个元素都包含一对key和value对象,不允许key对象重复,值对象...
  • Java集合框架Java集合框架概述 Java集合框架概述 用作自己学习笔记:如有不当的地方,还请指点~ 首先上图啦:看看Java集合相关类的关系图
  • JAVA中集合框架的知识点总结

    千次阅读 2016-10-26 09:40:13
    题外话  记得原来在学校的时候,大二选修了JAVA这门课,老师只教到多态继承就闪人了,不去评论他是否敬业。后期自己不断摸索,对JAVA的掌握还好能在简历上写下“熟悉”二字。本以为,不会再去写这样基础的博客了,...
  • Java集合框架是什么?说出一些集合框架的优点?

    千次阅读 多人点赞 2019-11-20 15:33:49
    随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的集合框架。在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久。它还包括在Java并发包中,阻塞接口以及它们的实现。 1...

空空如也

1 2 3 4 5 ... 20
收藏数 431,422
精华内容 172,568
关键字:

集合框架