集合概述
- 概念和种类
- 集合:
集合类存放于java.util包中。
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用。
通俗的讲集合就是一个放数据的容器,准确的说是放数据对象引用的容器。 - 种类:
集合类型主要有3种:set(集)、list(列表)和map(映射)。
集合接口分为:Collection和Map,list、set实现了Collection接口 - 概述:
Set下有HashSet,LinkedHashSet,TreeSet
List下有ArrayList,Vector,LinkedList
Map下有Hashtable,LinkedHashMap,HashMap,TreeMap
Collection接口下还有个Queue接口,有PriorityQueue类 - 集合的构成分类图
集合类型
(1)List集合
List 接口实现了 Collection 接口,它主要实现类有:ArrayList , LinkedList 和Vector类。在 List 集合中允许出现重复元素。与 Set 集合不同的是,在 List 集合中的元素是有序的,可以根据索引位置来检索 List 集合中的元素,第一个添加到 List 集合中的元素的索引为 0,第二个为 11依此类推。
1. 常用实现类
- ArrayList :
ArrayList实现了java.io.Serializable接口,底层使用Object数组来存储元素数据。所有的方法都围绕这个核心的Object数组来开展。
ArrayList是可以存放任意数量的对象,数组长度是有限的,本质上就是通过定义新的更大的数组,将旧数组内容拷贝到新数组,来实现扩容。
ArrayList的Object数组初始化长度为10,如果我们存储满了这个数组,需要存储第11个对象,就会定义新的数组长度长度更大的数组,并将将原数组内容和新的元素一起加入到新数组中。
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续,ArrayList要移动数据,所以插入和删除操作效率比较低。 - LinkedList :
它是非同步的,继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。实现List接口,能对它进行队列操作。实现Deque接口,即能将LinkedList当作双端队列使。LinkedList实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。 - Vector :
Vector基于数组实现的线程安全的集合。线程同步(方法被synchronized修饰)。
Vector和ArrayList在用法上几乎完全相同。区别是Vector线程安全,性能低,ArrayList性能高,保证不了安全性。而且ArrayList扩容时:增长0.5倍,Vector扩容时增长1倍。
特点:是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。
2. 区别与比较
- ArrayList和LinkedList
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
注意:若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数 据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。 - Vector和ArrayList
1,vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。
2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。
3. list常用方法
add():在列表的最后添加元素;
add(index,obj):在列表的指定位置添加元素;
size():返回当前列表的元素个数
get(int index):返回下标为index的元素;
clear():清除列表中所有元素;
isEmpty():检测列表是否为空;返回true/false;
contains():传入一个对象,检测列表中是否含有该对象;
indexOf():传入一个对象,返回该对象在列表中首次出现的地址;
lastInsevOf():传入一个对象,返回该对象在列表中最后一次出现的地址;
remove():传入一个下标,或者一个对象,删除指定元素;如果删除指定对象,需要重写equals()方法,比对传入的对象是不是属于原列表,如果属于,结果返回true;
set(index,obj):用新传入的对象,将指定位置的元素替换掉,返回被替换前的元素对象;
subList():截取一个子列表返回List类型;
toArray():将列表转为数组,返回一个Object[]类型;
iterator():使用迭代器遍历。
(2)Set集合
集合是无序不可重复的,取出也是随机的(方式:迭代器,增强for循环) ,Set接口已知的常用实现类有:HashSet、LinkedHashSet、TreeSet。
1. 常用实现类
- HashSet类:
HashSet类实现Java.util.Set接口。 它不允许出现重复元素,不保证集合中的元素的顺序,允许包含值为null的元素,但最多只能有null元素。
当我们用到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。
HashSet的底层其实是包装了一个HashMap去实现的。HashSet采用HashCode算法来存取集合中的元素,因此具有比较好的读取和查找功能。
exp:public class HashSetDemo { public static void main(String [] args) { HashSet h=new HashSet(); h.add("first"); h.add("second"); h.add(new Integer(3)); h.add(new Double(4.0)); h.add("second"); //重复元素,未被添加 h.add(new Integer(3)); //重复元素,未被添加 h.add(new Date()); System.out.println("开始:size="+h.size()); Iterator it=h.iterator(); while(it.hasNext()) { Object o=it.next(); System.out.println(o); } h.remove("second"); System.out.println("移除元素后:size="+h.size()); System.out.println(h); } }
- TreeSet
用TreeSet可以实现排序功能,它在将对象元素添加到集合中会自动按照某种比较规则将其插入到序的对象序列中,并保证该集合元素组成的读序列按照升序排列。
因为TreeSet实现了SortedSet接口,顾名思义是一种排序的Set集合,我们查看JDK源码会发现底层使用TreeMap实现的,本质上是一个红黑树原理。正因为它是排序了的,所以相对于HashSet来说,TreeSet提供了一些额外按排序位置访问元素的方法,例如first(),lower(),subSet(),headSet(),tailSet()。
TreeSet的排序分为两种类型,一种是自然排序,另一种是定制排序。
通过实现Comparable接口(compareTo(Object o)),和Comparator接口(compare(x,y))。 - LinkedHashSet
LinkedHashSet集合和HashSet一样也是根据元素的hashCode值来决定元素的存储位置,但和HashSet不同的是,它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。因为需要维护元素的插入顺序,LinkedHashSet性能略低于HashSet的性能。
2.set常用方法:
添加:add(添加元素);addAll(添加集合中所有元素)
删除:remove(删除元素);
查询集合长度:size
查询是否存在:contains
这里顺便比较一下HashSet与和HashMap的区别:
(3)Map集合
Map接口的特点是以键值对的形式存储数据,以键取值。键不能重复,值可以重复,
常用实现类有HashMap、HashTable、LinkedHashMap、TreeMap、ConcurrentHashMap。(ConcurrentHashMap后期单独拿出来说)
1. 常用实现类
-
HashMap
HashMap是线程不安全,但是效率高。可以允许键值对为null值,是基于哈希表的Map接口实现,哈希表的作用是用来保证键的唯一性的。
常用实例化方法:
new HashMap< Object, Object>(); -
HashTable
Hashtable和HashTable 都实现了 Map 接口,区别在于 HashTable不像前者那样允许空(null)键值(key),。最大的不同是, Hastable的方法是 synchronize的,所以是线程安全的,因此效率上来说也低于HashMap。在多个线程访问Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为之提供同步。 -
LinkedHashMap
LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,所以总结LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。 -
TreeMap
TreeMap是基于红黑树的Map,插入的数据被有次序保存,并且有很高的效率。因此在遍历输出的时候可以得到排序的数据。要求插入的数据实现了comparable接口。
2. map集合常用方法:
size() : int返回Map中元素的个数
isEmpty() : boolean 返回一个布尔值,表示这个Map是否为空
containsKey(Object) : boolean 返回一个布尔值,表示这个Map中是否存在一个为Object的key
containsValue(Object) : boolean 返回一个布尔值,表示这个Map中是否存在一个为Object的value
get(Object) : V 返回Object这个key所对应的Value
put(K, V) 添加一个元素到Map中
clear() 清除Map中的元素
keySet() : Set 返回一个Set对象,里面包含Map的所有key
values() : Collection 返回一个实现了Collection的类的对象,里面包含Map中的所有value
entrySet() : Set 返回一个Set,Set中的每个元素都为entry,每个entry中包含Map的一个Key和对应的Value
equals() : boolean 用于比较两个Map是否相等
总结:本文只是简单的介绍的这些常见集合的特点及用法,像更深入的底层原理和代码案例后期会单独详谈或后期补充。