zoukankan      html  css  js  c++  java
  • Android List、Set和Map的介绍和使用

    一、前言

    Android中常用的数据结构包括List、Set和Map这三大类的集合,其中List和Set属于Collection。List与Set的区别在于List可以存放重复的数据,但是Set不可以。 
    Map一般为key-value这样的对于关系,比如常用的HashMap。 
    Android中的集合类关系图

    Collection        接口的接口   对象的集合
    |-List            子接口      按进入的先后顺序进行保存,可重复
    |   |-LinkedList  接口实现类   链表,插入删除,非线程安全
    |   |-ArrayList   接口实现类   数组,随机访问,线程非安全
    |   |_Vector      接口实现类   数组,线程安全
    |_Set             子接口      仅接收一次,并做内部排序
    |   |-HashSet      接口实现类   HashSet使用Hash算法来存储集合中的元素,因此具有良好的存取和查找性能
    | 
    |   |-LinkedHashSet 接口实现类  LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但是和HashSet不同的是,它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。
    |—Queue           子接口      保持一个队列(先进先出)的顺序
       |-PriorityQueue 
    Map               接口        把键对象和值对象进行关联的容器,并且值对象可以是另一个Map
    |-HashMap         接口实现类     根据key算出一个hash值,确定一个存放index,期间需要解决hash冲突。非线程安全。
    |-LinkedHashMap   继承自HashMap  相比HashMap,其特点是内部存放数据是有顺序的,增加了记住元素插入或者访问顺序的功能。
    |-TreeMap         接口的实现类    使用大致与HashMap类似,只是内部实现是根据红黑树来实现的。
    |HashTable        接口实现类      Hashtable是线程安全的,内部实现与HashMap差不多。

    二、List、Set和Map的介绍和使用范例

    常用的List包括ArrayList、Linked List和Vector,下面将对他们进行一一介绍。 
    2.1 ArrayList 
    ArrayList非线程安全,底层由数组实现,它的构造主要从AbstractList实现,主要是判断下初始元素的容量,ArrayList最大的特点就是提供了Add、Get操作,当然可以通过迭代器来遍历,对于元素的存在可以通过contains方法判断。 
    ArrayList初始化和赋值

    //方式一:
      ArrayList<String> list = new ArrayList<String>();
      String str01 = String("test1");
      String str02 = String("test2");
      list.add(test1);
      list.add(test2);
    //方式二:
     ArrayList<String> list = new ArrayList<String>(){{add("test1"); add("test2");}};  

    ArrayList在使用过程中需要注意的一个问题便是在遍历的过程中删除Item元素,该问题的关键在于面试者使用的是ArrayList的remove还是Iterator的remove,如果操作不当,会出现删除的元素并没有完全被删除,或者出现ConcurrentModificationException异常。

    //采用For循环进行删除,该方法会造成某些对象没有被删除的情况
    public class Test1 {  
    
        public static void main(String[] args) {  
            ArrayList<String> aList = new ArrayList<String>();  
            aList.add("a");  
            aList.add("ab");  
            aList.add("abc");  
            aList.add("abc");  
            aList.add("abcr");  
            aList.add("abc");  
            aList.add("abcf");  
            aList.add("abc");  
            aList.add("abdc");  
    
            for(int i = 0;i < aList.size();i++){  
                if(aList.get(i).equals("abc")){  
                    aList.remove(i);   
                }  
            }            
            System.out.println(aList);  
        }  
    }
    //输出结果为:[a, ab, abc, abcr, abcf, abdc],其中有一个abc没有被删除
    //采用遍历器进行删除
    Iterator<String> iter = aList.iterator();  
            while(iter.hasNext()){  
                if(iter.next().equals("abc")){  
                    iter.remove();   
                }  
    //输出结果[a, ab, abcr, abcf, abdc]
    //采用遍历器进行删除
     for (String tar : aList) {
                if (tar.equals("abc")){
                    aList.remove(tar);
                }
            }
    //结果是出现异常

    综上所述,在对ArrayList进行遍历删除时,建议使用遍历器iterator进行遍历删除。

    2.2 LinkedList 
    Android中的LinkedList是通过双向列表实现的。链表元素除了含有自身的值以外,还含有上一个元素和下一个元素的引用。

    private static final class Link<T> {
            T data;//当前值
    
            Link<T> previous, next;//上一个,和下个链表对象的引用
    
            Link(T o, Link<T> p, Link<T> n) {
                data = o;
                previous = p;
                next = n;
            }
        }

    LinkedList的插入和删除操作就是双向链表的插入和删除操作,参加如下:

    //插入操作操作
    private boolean addLastImpl(E object) {
            Link<E> oldLast = voidLink.previous;
          //新元素的头指向上一个元素,尾指向链表的头部
            Link<E> newLink = new Link<E>(object, oldLast, voidLink);
          //头元素的头指向新元素
            voidLink.previous = newLink;
           //上一个结尾元素的尾 指向新元素
            oldLast.next = newLink;
            size++;
            modCount++;
            return true;
        }
    //删除操作
    @Override
        public E remove(int location) {
            if (location >= 0 && location < size) {
                Link<E> link = voidLink;
                if (location < (size / 2)) {
                    for (int i = 0; i <= location; i++) {
                        link = link.next;
                    }
                } else {
                    for (int i = size; i > location; i--) {
                        link = link.previous;
                    }
                }
                Link<E> previous = link.previous;
                Link<E> next = link.next;
                previous.next = next;
                next.previous = previous;
                size--;
                modCount++;
                return link.data;
            }
            throw new IndexOutOfBoundsException();
        }

    LinkedList在实现List的接口的同时也实现了Queue 的接口。

    2.3 Vector 
    Vector相当于具有同步操作的ArrayList,但是由于同步特性会造成一部分性能的损失。Vector基于数组和同步特性,支持包括添加、移除和替换元素在内的所有操作,允许包括NULL在内元素。 
    2.4 HashSet 
    Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。HashSet类按照哈希算法来存取集合中的对象,存取速度比较快。一般会用HashSet对List中相同的元素进行去重,参考如下:

    public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("a");
            list.add("f");
            list.add("b");
            list.add("c");
            list.add("a");
            list.add("d");
            System.out.println(list);
    
            list = removeSame(list);
            System.out.println(list);
    
        }
    
        private static List<String> removeSame(List<String> list) {
            Set<String> set = new HashSet<>();
            set.addAll(list);
            List<String> listSingle = new ArrayList<>();
            for(String s : set){
                listSingle.add(s);
            }
            return listSingle;
        }

    2.5 TreeSet和LinkedHashSet 
    TreeSet保存次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。 
    LinkedHashSet,具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结构会按元素插入的次序显示。 
    2.6 Queue 
    Queue用于模拟“队列”这种数据结构(先进先出)。Queue提供的操作函数如下:

    入队出队检索
    offer(E e) poll() peek()
    add(E e) remove() element()

    Queue的实现类主要分为三类 
    非线程安全:LinkedList,PriorityQueue等。 
    线程安全:非阻塞ConcurrentLinkedQueue 
    线程安全,阻塞:BlockingQueue实现类:ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue。 
    Queue在Android开发中很多场景都会用到,比如在线程池的任务队列就一般会用LinkedBlockingQueue来进行存放。

    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(
                    nThreads, nThreads,
                    0L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>() //任务队列采用LinkedBlockingQueue进行存放
            );

    2.7 Map 
    Map除去平常代码中用到的保存键值对的功能外,在此只总结一下Map在平常使用中的遍历操作,参见如下:

    
    // Map.values()遍历所有的value,不遍历key  
    for (String v : map.values()) {  
        System.out.println("value= " + v);  
    } 
    
    //取二次值,先取key再取value,建议只需要用key的时候使用,节省时间、空间  
    // keySet遍历key和value  
    for (String key : map.keySet()) {  
        System.out.println("key= "+ key + " and value= " + map.get(key));  
    }
    
    // 取一次值,一次把key和value全部取出  
    // entrySet使用iterator遍历key和value  
    Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();  
    while (it.hasNext()) {  
        Map.Entry<String, String> entry = it.next();  
        System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());  
    }
    
    // 推荐,尤其是容量大时,TreeMap尤其推荐  
    // entrySet遍历key和value  
    for (Map.Entry<String, String> entry : map.entrySet()) {  
        System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());  
    } 

    三、Android中常用类其它数据结构

    SparseArray类型,SparseArray有如下特性:

    1、SparseArray是android提供的一个工具类,它可以用来替代hashmap进行对象的存储
    2、SparseArray比HashMap更省内存,它对数据采取了矩阵压缩的方式来表示稀疏数组的数据,从而节约内存空间
    3、SparseArray只能存储key为整型的数据
    4、SparseArray在存储和读取数据时候,使用的是二分查找法,提高了查找的效率
    5、SparseArray有自己的垃圾回收机制。(当数量不是很多的时候,这个不必关心。)

    SparseArray的插取

    SparseArray<String> sparseArray = new android.util.SparseArray<String>(16);
    sparseArray.put(10, "value");
    sparseArray.get(10);

    四、参考博客

    从源码看Android常用的数据结构 ( SDK23版本 ) ( 三 , Queue篇) 
    Android List,Set,Map集合安全 集合区别 并发集合类性能分析 
    Android中List、Set、Map数据结构详解 
    List、Set、Map 和 Queue 之间的区别 
    Android之collection(集合) 
    java 利用HashSet去重并保持排序 
    Android中的HashMap,ArrayMap和SparseArray

    1. json = json.replace("\&", "&");
    2.  
      json = json.replace("&nbsp;", " ");
    3.  
      json = "[" + json + "]";
    4.  
       
    5.  
      //使用阿里的fastjson进行解析
    6.  
      List<KuWoInfo> list = JSON.parseArray(json,KuWoInfo.class);
    7.  
      Log.d(TAG,"--------------->"+list.get(0).getAbslist()[0].getSONGNAME());
       
       
  • 相关阅读:
    Spring AOP概念理解
    五分钟快速掌握RPC原理及实现
    Linux常用命令汇总
    一致性哈希算法原理
    RPC原理及实现
    IO设计模式:Reactor和Proactor对比
    到底什么时候该使用MQ?
    eclipse查看一个方法被谁引用(调用)的快捷键四种方式
    maven build pulgin
    VSCode 常用setiings.json设置
  • 原文地址:https://www.cnblogs.com/Alex80/p/13687871.html
Copyright © 2011-2022 走看看