zoukankan      html  css  js  c++  java
  • [Java] 集合类(List、Set、Map的基本使用)

    数组是一种很常见的数据结构,开始接触编程的时候多数程序都和数组相关。刚开始接触Java时也是一直使用数组写一些程序,后来越来越觉得...

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

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

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

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

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

    集合类的分类

    20121220051043731

    被水印遮住的单词是Comparator

    上图中不包含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基本操作

            ArrayList<String> arrayList = new ArrayList<String>();  
            arrayList.add("Tom");  
            arrayList.add("Jerry");  
            arrayList.add("Micky");  
            // 使用Iterator遍历元素  
            Iterator<String> it = arrayList.iterator();  
            while (it.hasNext()) {  
                String str = it.next();  
                System.out.println(str);  
            }  
            // 在指定位置插入元素  
            arrayList.add(2, "Kate");  
            // 通过索引直接访问元素  
            for (int i = 0; i < arrayList.size(); i++) {  
                System.out.println(arrayList.get(i));  
            }  
            List<String> subList = new ArrayList<String>();  
            subList.add("Mike");  
            // addAll(Collection<? extends String> c)添加所给集合中的所有元素  
            arrayList.addAll(subList);  
            // 判断是否包含某个元素  
            if (arrayList.contains("Mike")) {  
                System.out.println("Mike is include in the list");  
            }  
     
            LinkedList<String> linkedList = new LinkedList<String>();  
            linkedList.addAll(arrayList);  
            // 获取指定元素  
            System.out.println(linkedList.get(4));  
            // 获取第一个元素  
            System.out.println(linkedList.getFirst());  
            // 获取最后一个元素  
            System.out.println(linkedList.getLast());  
            // 获取并删除第一个元素  
            System.out.println(linkedList.pollFirst());  
            // 获取,但不移除第一个元素  
            System.out.println(linkedList.peekFirst());

    ArrayList和LinkedList的效率比较

    // ArrayList添加元素的效率   
             ArrayList<String> arrList = new ArrayList<String>();  
                     long startTimeMillis, endTimeMillis;  
                     startTimeMillis = System.currentTimeMillis();  
                     for (int i = 0; i < 10000; i++) {  
                         arrList.add(0, "addString");  
                     }  
                     endTimeMillis = System.currentTimeMillis();  
                     System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)  
                             + "ms");  
               
                     arrList.clear();  
               
                     startTimeMillis = System.currentTimeMillis();  
                     for (int i = 0; i < 20000; i++) {  
                         arrList.add(0, "addString");  
                     }  
                     endTimeMillis = System.currentTimeMillis();  
                     System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)  
                             + "ms");  
               
                     arrList.clear();  
               
                     startTimeMillis = System.currentTimeMillis();  
                     for (int i = 0; i < 40000; i++) {  
                         arrList.add(0, "addString");  
                     }  
                     endTimeMillis = System.currentTimeMillis();  
                     System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)  
                             + "ms");  
               
                     arrList.clear();  
               
                     startTimeMillis = System.currentTimeMillis();  
                     for (int i = 0; i < 80000; i++) {  
                         arrList.add(0, "addString");  
                     }  
                     endTimeMillis = System.currentTimeMillis();  
                     System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)  
                             + "ms");  
               
                     arrList.clear();  
               
                     startTimeMillis = System.currentTimeMillis();  
                     for (int i = 0; i < 160000; i++) {  
                         arrList.add(0, "addString");  
                     }  
                     endTimeMillis = System.currentTimeMillis();  
                     System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)  
                             + "ms");  
               
                     arrList.clear();  
               
                     startTimeMillis = System.currentTimeMillis();  
                     for (int i = 0; i < 320000; i++) {  
                         arrList.add(0, "addString");  
                     }  
                     endTimeMillis = System.currentTimeMillis();  
                     System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis)  
                             + "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基本操作

    HashMap<String, Integer> map = new HashMap<String, Integer>();  
                     // 向Map中添加元素  
                     map.put("Tom", 26);  
                     map.put("Jack", 18);  
                     map.put("Micky", 17);  
                     map.put("Kate", 15);  
                     // 根据Key获取Value  
                     System.out.println("Jack is " + map.get("Jack") + " years old");  
                     // 移除  
                     map.remove("Micky");  
                     // 遍历Map  
                     for (Entry<String, Integer> entry : map.entrySet()) {  
                         System.out.println("name:" + entry.getKey() + " age:" 
                                 + entry.getValue());  
                     }  
                     // Key相同的元素将被覆盖  
                     map.put("Jack", 19);  
                     // 根据Key获取Value  
                     System.out.println("Jack is " + map.get("Jack") + " years old");  
                     // 判断是否包含某个Key  
                     if (map.containsKey("Tom")) {  
                         System.out.println(map.get("Tom"));  
                     }  
                     // 判断是否包含某个Value  
                     if (map.containsValue(26)) {  
                         System.out.println("The map include the value 26");  
                     }  
                     // 判断map是否为空  
                     if (!map.isEmpty()) {  
                         // 获取map大小  
                         System.out.println("The map's size=" + map.size());  
                     }  
                     // 获取Key的集合  
                     for (String str : map.keySet()) {  
                         System.out.println(str);  
                     }  
               
                     TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>();  
                     treeMap.putAll(map);  
                     // 输出内容按照key值排序  
                     for (Entry<String, Integer> entry : treeMap.entrySet()) {  
                         System.out.println("name:" + entry.getKey() + " age:" 
                                 + entry.getValue());  
                         // name:Jack age:19  
                         // name:Kate age:15  
                         // name:Tom age:26  
                     }  
               
                     LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<String, Integer>();  
                     // 向Map中添加元素  
                     linkedHashMap.put("Tom", 26);  
                     linkedHashMap.put("Jack", 18);  
                     linkedHashMap.put("Micky", 17);  
                     linkedHashMap.put("Kate", 15);  
                     // 保持了插入的顺序  
                     for (Entry<String, Integer> entry : linkedHashMap.entrySet()) {  
                         System.out.println("name:" + entry.getKey() + " age:" 
                                 + entry.getValue());  
                         // name:Tom age:26  
                         // name:Jack age:18  
                         // name:Micky age:17  
                         // name:Kate age:15  
                     }

    Set
    Set基础操作

    List<Integer> list = new ArrayList<Integer>();  
          list.add(3);  
          list.add(4);  
          HashSet<Integer> hashSet = new HashSet<Integer>();  
          hashSet.add(1);  
          hashSet.add(3);  
          hashSet.add(2);  
          hashSet.add(6);  
          // 重复元素将不能被添加  
          hashSet.add(3);  
          // 只要有元素被添加就返回true  
          if (hashSet.addAll(list)) {  
              System.out.println("Add success");  
          }  
          // 判断是否存在某个集合  
          if (hashSet.containsAll(list)) {  
              System.out.println("The hashSet is contain 3 and 4");  
          }  
          Iterator<Integer> it = hashSet.iterator();  
          while (it.hasNext()) {  
              System.out.print(it.next() + " ");  
              // 1 2 3 4 6  
              // 看结果是被排序了,HashSet按照Hash函数排序,Integer值的HashCode就是其int值  
          }  
          // 换转成数组  
          Object[] integers = hashSet.toArray();  
          for (int i = 0; i < integers.length; i++) {  
              System.out.print((Integer) integers[i]);  
          }  
          //移除元素  
          hashSet.remove(3);  
            
          TreeSet<String> treeSet = new TreeSet<String>();  
          treeSet.add("C");  
          treeSet.add("A");  
          treeSet.add("D");  
          treeSet.add("B");  
          for (Iterator<String> strIt = treeSet.iterator(); strIt.hasNext();) {  
              System.out.print(strIt.next());  
              // ABCD 按照字母顺序  
          }  
          LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();  
          linkedHashSet.add("C");  
          linkedHashSet.add("A");  
          linkedHashSet.add("D");  
          linkedHashSet.add("B");  
          for (Iterator<String> linkedIt = linkedHashSet.iterator(); linkedIt  
                  .hasNext();) {  
              System.out.print(linkedIt.next());  
              // CADB 按照插入顺序  
          }

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

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

    --------------------------------------

    欢迎您,进入 我系程序猿 的cnBlog博客。

    你不能改变你的过去,但你可以让你的未来变得更美好。一旦时间浪费了,生命就浪费了。

    You cannot improve your past, but you can improve your future. Once time is wasted, life is wasted.

    --------------------------------------

    分享到QQ空间  

  • 相关阅读:
    Genealogical tree(拓扑结构+邻接表+优先队列)
    确定比赛名次(map+邻接表 邻接表 拓扑结构 队列+邻接表)
    Agri-Net
    Network()
    Conscription
    Matrix(类似kruskal)
    Highways(求最小生成树的最大边)
    Shell学习之Shell特性(一)
    Linux学习之用户管理命令与用户组管理命令(十五)
    Linux学习之用户配置文件详解(十四)
  • 原文地址:https://www.cnblogs.com/jqmtony/p/3730297.html
Copyright © 2011-2022 走看看