数组和集合的区别
- 数组可以存储基本数据类型和对象,集合中只能存储对象,(可以以包装类的形式存储基本数据类型)。
- 数组长度固定,集合长度可以动态改变。
- 定义数组必须指定数组的元素类型,集合默认的所有元素都是Object。
- 无法直接获取实际存储的元素个数,length用来获取数组长度,而集合框架中size()方法可以直接获取数组是急的元素个数。
- 数组采用分配连续空间的方式,集合有多种实现方式和不同的适用场合。
- 集合采用了接口和类的形式,具有继承、封装、多态的特性,考法效率较数组更高。
- 数组提供了Arrays类提供对数组的一系列操作,而集合提供了Collections类来操作集合。
由易到难,由浅入深,java集合框架需要学习的还有很多,随时补充。
java集合框架是一种统一的标准体系结构。
集合框架包含三大体系内容:
- 对外的接口
- 接口的实现
- 对集合运算的算法
接口:表示集合的抽象数据类型,例如:Collection、List、Set、Map、Iterator
实现:集合框架中对接口的具体实现:例如:ArrayList、LinkedList、HashSet、HashMap
算法:对某个集合完成有用的计算方法。JAVA提供了进行集合操作的工具类Collections。类似于Arrays类。
从框架图中不难看出,java集合框架有两大接口:Collection和Map
其中Collection又有两个子接口:List和Set
所以java集合框架共有三大接口:List、Set、Map
具体介绍:
Collection:允许重复、无序的对象
List:允许重复、有序(以元素插入的次序来放置元素)的对象
Set:不允许重复、无序的对象Map:存储成对的键 - 值 对象,提供key到value的映射
key无序,不可重复;value无序,可以重复
Collection接口方法:
size() - 集合内的对象数量
add(E)/addAll(Collection) - 向集合内添加单个/批量对象
remove(Object)/removeAll(Collection) - 从集合内删除单个/批量对象
contains(Object)/containsAll(Collection) - 判断集合中是否存在某个/某些对象
toArray()- 返回包含集合内所有对象的数组
List接口增加的方法:
get(int) - 返回指定index位置上的对象
add(E)/add(int, E) - 在List末尾/指定index位置上插入一个对象
set(int, E) - 替换置于List指定index位置上的对象
indexOf(Object) - 返回指定对象在List中的index位置
subList(int,int) -返回指定起始index到终止index的子List对象
常用类ArrayList:
ArrayList基于数组来实现集合的功能,其内部维护了一个可变长的对象数组,集合内所有对象存储于这个数组中,并实现该数组长度的动态伸缩
ArrayList使用数组拷贝来实现指定位置的插入和删除:
常用类LinkedList:
LinkedList基于链表来实现集合的功能,其实现了静态类Node,集合中的每个对象都由一个Node保存,每个Node都拥有到自己的前一个和后一个Node的引用
ArrayList的随机访问更高,基于数组实现的ArrayList可直接定位到目标对象, 而LinkedList需要从头Node或尾Node开始向后/向前遍历若干次才能定位到目标对象。
LinkedList在头/尾节点执行插入/删除操作的效率比ArrayList要高。
由于ArrayList每次扩容的容量是当前的1.5倍,所以LinkedList所占的内存空间要更小一些。
二者的遍历效率接近,但需要注意,遍历LinkedList时应用iterator方式,不要用get(int)方式,否则效率会很低
Arraylist:
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。
LinkedList:
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
适用场景分析:
当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。
http://mp.weixin.qq.com/s/nrfFY7A9__PJmc75Y_exZg
这篇文章也很清楚的及介绍了两者异同。
Set接口常用类HashSet:
特点:查找效率高
常用方法:
添加元素:
hashset.add(E e):返回boolean型,如果此 set 中尚未包含指定元素,则添加指定元素;如果此 set 已包含该元素,则该调用不更改 set 并返回 false。
删除元素:
hashset.clear():从此 set 中移除所有元素。
hashset.remove(Object o):如果指定元素存在于此 set 中,则将其移除。
hashset.isEmpty():如果此set 不包含任何元素,则返回true。
hashset.contains(Object o):如果此 set 包含指定元素,则返回 true。
hashset.size():返回此 set 中的元素的数量(set 的容量)。
Set接口还有TreeSet和LinkedHashSet需要了解:
TreeSet:
为快速查找设计的Set。底层为树结构,使用它可以从Set中提取有序的序列。
LinkedHashSet:
具有HashSet的查询速度,企且内部使用了链表维护维护元素的顺序(插入的次序)。于是在迭代器遍历Set时,结果会按元素的插入次序来排序显示。
HashSet与Treeset的适用场景
- TreeSet 是二叉树(红黑树的树据结构)实现的,Treeset中的数据是自动排好序的,不允许放入null值
- HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
- HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例。
适用场景分析:
HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。为快速查找而设计的Set,我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。
Map接口:
键值对的存储形式的优点是查询指定元素的效率高
Map接口在Collection的基础上,为其中的每个对象指定了一个key,并使用Entry保存每个key-value对,以实现通过key快速定位到对象(value)。Map接口的主要方法包括:
常用类HashMap增加了isEmpty()、clear()方法
isEmpty()若不存在键值对关系,则返回true
clear()清除所有映射关系
Map中还有许多类需要了解和知道:
LinkedHshMap:
类似于HashMap,但是迭代遍历时,取得的键值对的顺序是其插入的顺序,或者最近最少使用的次序,纸币HashMap慢一点,而在迭代遍历时发生更快,因为他是链表维护结构。
TreeMap
:基于红黑树数据结构的实现,查看键或者键值对时,他们会被排序。TreeMap的特点在于,得到的结果是经过排序后的,TreeMap是唯一带有subMap()方法的Map,他可以返回一个子树。
WeakHashMap:
弱键Map,Map中使用的对象被允许释放,这是为解决特殊问题而设计的。如果没有map之外的引用指向某一个键时,则此键会被GC回收。
IdentifyHashMap:
使用==代替equals对键做比较的hashmap。专为解决特殊问题设计。
常见面试题。
相同点:
HashMap类出现以前,JDK存在着一个和它同样采用哈希表存储方式,同样实现键值对的集合类HashTable。两者实现原理相同。都使用哈希表来存储键值对。
不同点:
Hashtable继承自Dictionary类,而HashMap实现了Map接口。
Hashtable是线程安全的,HashMap注重速度,但是是非线程安全的。
Hashtable的key和value不允许null值,HashMap都允许null值。
Hashtable是过时的类,开发中最好使用HashMap。
http://mp.weixin.qq.com/s/wnvpPOQvCgE5vgdnoMpGYw
上面的文章具体的说明了他们的异同。
HashMap与TreeMap、HashTable的区别及适用场景
HashMap 非线程安全
HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
适用场景分析:
HashMap和HashTable:HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。
HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。 HashMap允许空键值,而HashTable不允许。
HashMap:适用于Map中插入、删除和定位元素。
Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
List、Set、Map的区别以及使用场景
1. List,Set都是继承自Collection接口,Map则不是
2. List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
3. Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
4. Map适合储存键值对的数据
5. 线程安全集合类与非线程安全集合类 :
LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
HashMap是非线程安全的,HashTable是线程安全的;
StringBuilder是非线程安全的,StringBuffer是线程安全的。
迭代器iterator
iterator专门为集合框架而生
Collection接口的iterator()方法返回一个iterator,然后通过iterator的两个方法即可方便实现遍历
next()返回要访问的下一个元素。
遍历Map推荐方法:
for(Map.Entryentry:dogs.entrySet()){
System.out.println(entry.getKey()+" \t"+entry.getValue());
}
遍历List方法:
Iterator it=dogs.iterator();
while(it.hasNext()){
Dog dog= it.next();
System.out.println(dog.getName()+" \t"+dog.getStrain());
}
遍历Set方法:
Iterator dogit=dogs.iterator();
while(dogit.hasNext()){
Dog dog=dogit.next();
System.out.println(dog.getName()+" \t"+dog.getStrain());
}