1. 集合框架体系介绍
1. 集合框架包含接口,实现(类),算法,迭代器
- 接口,集合的抽象数据类型。接口提供统一标准的集合操作方法。
- 实现(类),集合接口的具体实现,它们是可重复使用的数据结构。
- 算法,实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。
- 迭代器,能够遍历集合中的元素
2. 按类的继承结构分为两大类 继承自Collection接口,这类集合包含List、Set和Queue等集合类。 继承自Map接口,这主要包含了哈希表相关的集合类。
2. Collection继承结构体系
图中的绿色的虚线代表实现,绿色实线代表接口之间的继承,蓝色实线代表类之间的继承。Collection接口继承于Iterable接口,Iterable接口定义了迭代器的功能,该接口的iterator()方法返回一个标准的Iterator实现。Collection接口的子接口有:List、Set、Queue接口和一个实现Collection接口的抽象类AbstractCollection。
- List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 常用实现类有<ArrayList,LinkedList,Vector> 。
- Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。 Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 常用实现类有<HashSet,TreeSet>。
- Queue用来模拟队列数据结构,常用实现类<PriorityQueue, ArrayDeque, LinkedList>
2.1 List接口
- List接口是一个有序的 Collection子接口
- 使用此接口能够精确的控制每个元素插入的位置 能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素 第一个元素的索引为 0,允许有相同的元素。
- 两种数据结构的实现:数组和链表 ,List接口使用比较多的标准实现是ArrayList和LinkedList, Vector,Stack
- ArrayList,Vector,Stack:数组实现。
- 数组实现的特点: 查询快 增删慢(参照于LinkedList)
- 查询: 直接使用角标(索引)查询
- 增删: 需要把要增删元素的位置 后面的元素 全部移动一位
- Vector是实现List接口的矢量队列。Stack继承Vector,Stack模拟栈操作,特点是:先进后出(FILO, First In Last Out)
- LinkedList:链表实现
- 链表实现的特点: 查询慢 增删快
- 查询: 判断查询的元素离头近还是离尾近,然后从头/尾 一个一个查找 找到为止
- 增删: 将要插入的元素的地址保存 后面的元素 不进行任何的改动
- LinkedList作为数组使用时与ArrayList使用方法相同,此外LinkedList实现了的队列(Queue)功能
- 使用场景:集合查询较多使用ArrayList,Vector的操作是线程安全的。 集合增删多使用LinkedList
2.2 Set接口
- Set接口是Collection的子接口,HashSet,LinkedHashSet 实现Set接口
- SortedSet接口是Set接口的子接口,SortedSet接口对集合元素排序 ,TreeSet实现SortedSet接口
HashSet,LinkedHashSet,TreeSet比较
- 相同点
- 保存不重复数据
- 可以存放一个null元素
- 唯一性添加功能底层依赖元素对象的:boolean equals(Object obj)
- 区别
- HashSet,LinkedHashSet实现了接口Set。
- HashSet不保证集合中元素的顺序,顺序有可能发生变化。
- LinkedHashSet按照元素插入的顺序进行迭代,即迭代输出的顺序与插入的顺序保持一致。
- TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序
- TreeSet自然排序,自然排序,集合中的元素需要是实现Comparable接口的对象,Comparable接口中定义了CompareTo函数,使用对象元素的CompareTo(Object obj)方法来比较对象元素之间的大小关系,然后将对象元素按照升序排列。
- TreeSet定制排序,自然排序是根据集合元素的大小,以升序排列,如果要定制排序,可以为集合指定比较器实现Comparator接口,可以自己实现 int compare(T o1,T o2)方法来实现定制排序
2.3 Queue接口
- Queue接口是Collection接口中的子接口,是单向队列
- Deque接口是Queue接口的子接口,是双端队列
- LinkedList ,ArrayDeque实现了Deque接口
- LinkedList ,ArrayDeque特点
- ArrayDeque不允许插入null元素
- ArrayDeque非线程安全
- 当ArrayDeque 作为一个栈来使用的时候比Stack快
- 当ArrayDeque 作为 队列使用的时候比 LinkedList 速度要快
- PriorityQueue继承父类AbstractQueue实现Queue接口
- PriorityQueue特点
- 优先队列不允许空值
- 不支持non-comparable(不可比较)的对象 ,PriorityQueue集合中的对象需要都是可比较的,集合元素需要实现Comparable接口
- 根据提供的比较器或者元素的自然顺序排序
- PriorityQueue是非线程安全的
3.Map继承结构体系
图中的绿色的虚线代表实现,绿色实线代表接口之间的继承,蓝色实线代表类之间的继承。Map接口是键值对的集合接口 SortedMap是Map的子接口。AbstractMap是Map接口的抽象实现类,从图中看出我们常用的Map接口体系的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等
HashMap,LinkedHashMap,TreeMap,HashTable特点
- HashMap
- HashMap不能保证元素存放的顺序,根据键的HashCode 值存储数据,根据键可以直接获取它的值
- 最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null
- 非线程同步
- LinkedHashMap
- LinkedHashMap继承HashMap,HashMap是无序的,LinkedHashMap 能够保证插入集合的元素顺序与输出顺序一致
- 最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null
- 非线程同步
- LinkedHashMap在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
- TreeMap
- TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
- 非线程同步
- TreeMap不允许key的值为null。
- 一 般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.
- HashTable
- HashTable它不允许记录的键或者值为null;
- 支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
- HashTable现在已经很少使用了,与HashMap的主要区别是HashTable是线程安全的,不过由于其效率比较低,所以通常使用HashMap,在多线程环境下,通常用CurrentHashMap来代替。
4.集合中的工具类
4.1 Collections介绍
- Collections是集合框架的一个工具类。它里边的方法都是静态的,不需要创建对象。
- 在Collections工具类中大部分方法是用于对List集合进行操作的,如比较,二分查找,随机排序等。
- T max(Collection<? extends T> coll);//根据集合的自然顺序,获取coll集合中的最大元素
- T max(Collection<? extends T> coll,Comparator<? super T> comp);//根据指定比较器comp的顺序,获取coll集合中的最大元素
- int binarySearch(List<? extends Comparable<? super T>> list,T key);//二分法搜索list集合中的指定对象,返回索引值
- void fill(List<? super T> list, T obj);//将list集合中的全部元素替换成指定对象obj
- boolean replaceAll(List<T> list,T oldVal,T newVal);//用newVal替换集合中的oldVal值
- void swap(List list,int i,int j);//在指定列表的指定位置处交换元素
- void shuffle(List<?> list);//使用默认随机源对list集合中的元素进行随机排序
- void sort(Lsit<T> list);//根据自然顺序对list集合中的元素进行排序
- void sort(List<T> list,Comparator<? super T> c);//根据指定比较器c的排序方式对list集合进行排序
- reverse(List<?> list);//反转list集合中元素的顺序
- Comparator reverseOrder();//返回一个比较器,强行逆转了实现Comparable接口的对象的自然顺序
- Comparator reverseOrder(Comparator<T> cmp);//返回一个比较器,强行逆转了指定比较器的顺序
- 通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
- Collection<T> synchronizedCollection(Collection<T>c);
- List<T>synchronizedList(List<T> list)
- Map<K,V> synchronizedMap(Map<K,V> m)
- Set<T>synchronizedSet (Set<T> s)
- SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V>m)
- SortedSet<T> synchronizedSortedSet(SortedSet<T>s)
4.2 Arrays工具
- Arrays是用于操作数组的工具类。里边的方法也全是静态的。不需要创建对象。
- Arrays可以把数组变成List集合 Lsit<T> asList(T... a);//将数组转换为集合,使用集合的思想和方法来操作数组中的元素。如:contains,get,indexOf,subList等方法。
- 集合变数组,Collection接口中的toArray方法。
- Object[] toArray(); 将集合变为数组
- Object[] toArray(Object[] a);将集合变为指定类型的数组。
- 可以对元素进行查找排序
- binarySearch 二分查找方法
- sort 排序方法
4.3 Comparable,Comparator
- Comparable接口对实现它的每个类的对象进行整体排序。这个接口需要类本身去实现,若一个类实现了Comparable 接口,实现 Comparable 接口的类的对象的 List 列表 ( 或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。此外,实现 Comparable 接口的类的对象 可以用作 “有序映射 ( 如 TreeMap)” 中的键或 “有序集合 (TreeSet)” 中的元素,而不需要指定比较器。
- 如果我们的这个类无法修改,可以在类的外部使用Comparator
- Comparable 排序接口;若一个类实现了 Comparable 接口,就意味着 “该类支持排序”。实现public int compareTo(Object o) 确定排序规则。
- Comparator 是比较器;我们若需要控制某个类的次序,可以建立一个 “该类的比较器” 来进行排序。 前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用。可以说前者属于 “静态绑定”,而后者可以 “动态绑定”。 实现public int compare(Object o1, Object o2) 确定排序规则。
- 我们不难发现:Comparable 相当于 “内部比较器”,而 Comparator 相当于 “外部比较器”。