zoukankan      html  css  js  c++  java
  • Java集合类

    数组是一种很常见的数据结构,开始接触编程的时候多数程序都和数组相关。刚开始接触Java时也是一直使用数组写一些程序,后来越来越觉得数组这东西没法满足需求了,这时一位“前辈”对我说了一句:不会用集合类就等于没学过Java。然后才知道有集合类。

        想想已经是3、4年前的事了,时间如白驹过隙啊。

        什么时候数组会显得力不从心,没法满足需求,需要集合类呢?

    1. 不知道具体数据长度
    2. 需要自动排序
    3. 存储键值对

        当然,上面的情况不是绝对的,只是数组比较难满足。这时集合类(也可称为容器类)就显示了它强大的功能。

        集合类的分类(图片转自http://biancheng.dnbcw.info/1000wen/359774.html)

        

        上图中不包含Queue内容,部分Map的实现类未给出。

        常见使用的有List、Set、Map及他们的实现类。

        List、Set、Map接口及各实现类的特性

    接口

    特性

    实现类

    实现类特性

    成员要求

    List

    线性、有序的存储容器,可通过索引访问元素

    ArrayList

    数组实现。非同步。

    Vector

    类似ArrayList,同步。

    LinkedList

    双向链表。非同步。

    Map

    保存键值对成员

    HashMap

    基于哈希表的 Map 接口的实现,满足通用需求

    任意Object对象,如果修改了equals方法,需同时修改hashCode方法

    TreeMap

    默认根据自然顺序进行排序,或者根据创建映射时提供的 Comparator进行排序

    键成员要求实现caparable接口,或者使用Comparator构造TreeMap。键成员一般为同一类型。

    LinkedHashMap

    类似于HashMap,但迭代遍历时取得“键值对”的顺序是其插入顺序或者最近最少使用的次序

    与HashMap相同

    IdentityHashMap

    使用==取代equals()对“键值”进行比较的散列映射

    成员通过==判断是否相等

    WeakHashMap

    弱键映射,允许释放映射所指向的对象

    ConcurrentHashMap

    线性安全的Map

    Set

    成员不能重复

    HashSet

    为快速查找设计的Set

    元素必须定义hashCode()

    TreeSet

    保持次序的Set,底层为树结构

    元素必须实现Comparable接口

    LinkedHashSet

    内部使用链表维护元素的顺序(插入的次序)

    元素必须定义hashCode()

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

       

     

     

     

     

     

        在满足要求的情况下,Map应尽量使用HashMap,Set应尽量使用HashSet。

        集合类的基本使用

        List

    复制代码
    List基本操作
    复制代码
     1 ArrayList<String> arrayList = new ArrayList<String>();
     2         arrayList.add("Tom");
     3         arrayList.add("Jerry");
     4         arrayList.add("Micky");
     5         // 使用Iterator遍历元素
     6         Iterator<String> it = arrayList.iterator();
     7         while (it.hasNext()) {
     8             String str = it.next();
     9             System.out.println(str);
    10         }
    11         // 在指定位置插入元素
    12         arrayList.add(2, "Kate");
    13         // 通过索引直接访问元素
    14         for (int i = 0; i < arrayList.size(); i++) {
    15             System.out.println(arrayList.get(i));
    16         }
    17         List<String> subList = new ArrayList<String>();
    18         subList.add("Mike");
    19         // addAll(Collection<? extends String> c)添加所给集合中的所有元素
    20         arrayList.addAll(subList);
    21         // 判断是否包含某个元素
    22         if (arrayList.contains("Mike")) {
    23             System.out.println("Mike is include in the list");
    24         }
    25 
    26         LinkedList<String> linkedList = new LinkedList<String>();
    27         linkedList.addAll(arrayList);
    28         // 获取指定元素
    29         System.out.println(linkedList.get(4));
    30         // 获取第一个元素
    31         System.out.println(linkedList.getFirst());
    32         // 获取最后一个元素
    33         System.out.println(linkedList.getLast());
    34         // 获取并删除第一个元素
    35         System.out.println(linkedList.pollFirst());
    36         // 获取,但不移除第一个元素
    37         System.out.println(linkedList.peekFirst());
    复制代码
    复制代码

        ArrayList和LinkedList的效率比较

    复制代码
    ArrayList添加元素的效率
    复制代码
     1 ArrayList<String> arrList = new ArrayList<String>();
     2         long startTimeMillis, endTimeMillis;
     3         startTimeMillis = System.currentTimeMillis();
     4         for (int i = 0; i < 10000; i++) {
     5             arrList.add(0, "addString");
     6         }
     7         endTimeMillis = System.currentTimeMillis();
     8         System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)
     9                 + "ms");
    10 
    11         arrList.clear();
    12 
    13         startTimeMillis = System.currentTimeMillis();
    14         for (int i = 0; i < 20000; i++) {
    15             arrList.add(0, "addString");
    16         }
    17         endTimeMillis = System.currentTimeMillis();
    18         System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)
    19                 + "ms");
    20 
    21         arrList.clear();
    22 
    23         startTimeMillis = System.currentTimeMillis();
    24         for (int i = 0; i < 40000; i++) {
    25             arrList.add(0, "addString");
    26         }
    27         endTimeMillis = System.currentTimeMillis();
    28         System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)
    29                 + "ms");
    30 
    31         arrList.clear();
    32 
    33         startTimeMillis = System.currentTimeMillis();
    34         for (int i = 0; i < 80000; i++) {
    35             arrList.add(0, "addString");
    36         }
    37         endTimeMillis = System.currentTimeMillis();
    38         System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)
    39                 + "ms");
    40 
    41         arrList.clear();
    42 
    43         startTimeMillis = System.currentTimeMillis();
    44         for (int i = 0; i < 160000; i++) {
    45             arrList.add(0, "addString");
    46         }
    47         endTimeMillis = System.currentTimeMillis();
    48         System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)
    49                 + "ms");
    50 
    51         arrList.clear();
    52 
    53         startTimeMillis = System.currentTimeMillis();
    54         for (int i = 0; i < 320000; i++) {
    55             arrList.add(0, "addString");
    56         }
    57         endTimeMillis = System.currentTimeMillis();
    58         System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)
    59                 + "ms");
    复制代码
    复制代码

     

        执行时间比较

    执行次数(在0号位置插入)

    ArrayList所用时间(ms)

    LinkedList所用时间(ms)

    10000

    31

    0

    20000

    141

    0

    40000

    484

    16

    80000

    1985

    0

    160000

    7906

    0

    320000

    31719

    16

    执行次数(在尾部插入)

    ArrayList所用时间(ms)

    LinkedList所用时间(ms)

    10000

    0

    0

    20000

    15

    0

    40000

    0

    0

    80000

    0

    0

    160000

    0

    15

    320000

    0

    16

    循环输出次数(get(index)方法)

    ArrayList所用时间(ms)

    LinkedList所用时间(ms)

    10000

    93

    204

    20000

    188

    797

    40000

    328

    2734

    80000

    688

    13328

    160000

    1594

    62313

    320000

    2765

    太久了……

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

        

       

     

     

     

        因为ArrayList底层由数组实现,在0号位置插入时将移动list的所有元素,在末尾插入元素时不需要移动。LinkedList是双向链表,在任意位置插入元素所需时间均相同。所以在List中有较多插入和删除操作的情况下应使用LinkedList来提高效率,而有较多索引查询的时候使用ArrayList(使用增强型的for循环或Iterator遍历LinkedList效率将提高很多)。

        Map

    复制代码
    Map基本操作
    复制代码
     1 HashMap<String, Integer> map = new HashMap<String, Integer>();
     2         // 向Map中添加元素
     3         map.put("Tom", 26);
     4         map.put("Jack", 18);
     5         map.put("Micky", 17);
     6         map.put("Kate", 15);
     7         // 根据Key获取Value
     8         System.out.println("Jack is " + map.get("Jack") + " years old");
     9         // 移除
    10         map.remove("Micky");
    11         // 遍历Map
    12         for (Entry<String, Integer> entry : map.entrySet()) {
    13             System.out.println("name:" + entry.getKey() + " age:"
    14                     + entry.getValue());
    15         }
    16         // Key相同的元素将被覆盖
    17         map.put("Jack", 19);
    18         // 根据Key获取Value
    19         System.out.println("Jack is " + map.get("Jack") + " years old");
    20         // 判断是否包含某个Key
    21         if (map.containsKey("Tom")) {
    22             System.out.println(map.get("Tom"));
    23         }
    24         // 判断是否包含某个Value
    25         if (map.containsValue(26)) {
    26             System.out.println("The map include the value 26");
    27         }
    28         // 判断map是否为空
    29         if (!map.isEmpty()) {
    30             // 获取map大小
    31             System.out.println("The map's size=" + map.size());
    32         }
    33         // 获取Key的集合
    34         for (String str : map.keySet()) {
    35             System.out.println(str);
    36         }
    37 
    38         TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>();
    39         treeMap.putAll(map);
    40         // 输出内容按照key值排序
    41         for (Entry<String, Integer> entry : treeMap.entrySet()) {
    42             System.out.println("name:" + entry.getKey() + " age:"
    43                     + entry.getValue());
    44             // name:Jack age:19
    45             // name:Kate age:15
    46             // name:Tom age:26
    47         }
    48 
    49         LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<String, Integer>();
    50         // 向Map中添加元素
    51         linkedHashMap.put("Tom", 26);
    52         linkedHashMap.put("Jack", 18);
    53         linkedHashMap.put("Micky", 17);
    54         linkedHashMap.put("Kate", 15);
    55         // 保持了插入的顺序
    56         for (Entry<String, Integer> entry : linkedHashMap.entrySet()) {
    57             System.out.println("name:" + entry.getKey() + " age:"
    58                     + entry.getValue());
    59             // name:Tom age:26
    60             // name:Jack age:18
    61             // name:Micky age:17
    62             // name:Kate age:15
    63         }
    复制代码
    复制代码

        Set

    复制代码
    复制代码
     1            List<Integer> list = new ArrayList<Integer>();
     2            list.add(3);
     3            list.add(4);
     4            HashSet<Integer> hashSet = new HashSet<Integer>();
     5            hashSet.add(1);
     6            hashSet.add(3);
     7            hashSet.add(2);
     8            hashSet.add(6);
     9            // 重复元素将不能被添加
    10            hashSet.add(3);
    11            // 只要有元素被添加就返回true
    12            if (hashSet.addAll(list)) {
    13                System.out.println("Add success");
    14            }
    15            // 判断是否存在某个集合
    16            if (hashSet.containsAll(list)) {
    17                System.out.println("The hashSet is contain 3 and 4");
    18            }
    19            Iterator<Integer> it = hashSet.iterator();
    20            while (it.hasNext()) {
    21                System.out.print(it.next() + " ");
    22                // 1 2 3 4 6
    23                // 看结果是被排序了,HashSet按照Hash函数排序,Integer值的HashCode就是其int值
    24            }
    25            // 换转成数组
    26            Object[] integers = hashSet.toArray();
    27            for (int i = 0; i < integers.length; i++) {
    28                System.out.print((Integer) integers[i]);
    29            }
    30            //移除元素
    31            hashSet.remove(3);
    32            
    33            TreeSet<String> treeSet = new TreeSet<String>();
    34            treeSet.add("C");
    35            treeSet.add("A");
    36            treeSet.add("D");
    37            treeSet.add("B");
    38            for (Iterator<String> strIt = treeSet.iterator(); strIt.hasNext();) {
    39                System.out.print(strIt.next());
    40                // ABCD 按照字母顺序
    41            }
    42            LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
    43            linkedHashSet.add("C");
    44            linkedHashSet.add("A");
    45            linkedHashSet.add("D");
    46            linkedHashSet.add("B");
    47            for (Iterator<String> linkedIt = linkedHashSet.iterator(); linkedIt
    48                    .hasNext();) {
    49                System.out.print(linkedIt.next());
    50                // CADB 按照插入顺序
    51            }    
    复制代码
    复制代码

     

     

     

     

        本文没有对ArrayList及HashMap进行深入的分析,这两个类是集合类中最常用的类,将另开文章进行深入剖析。

         ArrayList深入分析:《ArrayList源码分析》

  • 相关阅读:
    STL(1) 指针迭代器
    不错我博主
    C++ 学习书目
    写给VC++ Windows开发的初学者 一片不错的博文
    算法:C语言实现 (4)队列的数组实现
    算法:C语言实现 (4)下推栈的数组实现
    算法:C语言实现 (4)下推栈的链表实现
    vs 使用笔记
    自定义组合控件,适配器原理-Day31
    Android30-Fragment-理解
  • 原文地址:https://www.cnblogs.com/daichangya/p/12959394.html
Copyright © 2011-2022 走看看