【android 】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);
【参考链接】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
2022-02-23 【Nginx解决Host头注入& cors跨域请求伪造】
2020-02-23 【go】go国内镜像