java基础——Map、Set、List实现类(随笔)

Set接口

Set接口直接继承Collection接口,并且方法接口上也一模一样。Set对添加的元素有一些要求,不允许出现重复的元素,元素之间无序。所以,添加进Set的元素类型需要定义equals方法。若是使用自定义的类,则应该重写equals方法来确保实现自己需要的功能。

Set接口主要有两个实现类:HashSet,TreeSet

HashSet是按照哈希值来存取元素的,因此速度比较快。HashSet继承自抽象类AbstractSet,然后实现了Set,Cloneable,Serializable接口.

TreeSet也是继承自AbstractSet,不过不同的是其实现的是NavigableSet接口。而NavigableSet继承自SortedSet。SortedSet是一个有序的集合。其添加的元素必须实现了Comparable接口,因为其再添加一个元素的时候需要进行排序。NavigableSet则提供了更多的有关元素次序的方法,比如:E lower(E e);//找出小于e的元素 E floor(E e);//找出小于等于e的元素 E ceilling(E e);//找出大于等于e的元素 E higher(E e);//找出大于e的元素 E pollFirst();//弹出第一个(最小)元素,如果集合为空则返回null E pollLast();//弹出最后一个(最大)元素,如果集合为空则返回null

LinkedHashSet也是Set的一个实现。和HashSet类似,只不过内部用链表来维护,按照元素插入次序来保存。

List接口

list接口也是继承自Cllection。与Set不同的是,List可以存储重复的元素。主要有两种实现:ArryList和LinkedList。

ArryList就像传统数组一样,有着很快的随机存取速度,但是插入删除的速度就很慢。

LinkedList则与ArrayList恰恰相反,因为用链表来保存数据,所以插入删除元素的速度很快,但是访问数据的速度就不如ArrayList了。

ArrayList、LinkedList、Vector比较

1、同步性:ArrayList,LinkedList不具有同步性,而Vector是同步的。所以如果对线程安全没有要求的话,可以使用ArrayList或LinkedList,可以节省为同步而耗费的开销。但是在多线程的情况下,有时候就必须使用Vector。但是ArrayList和LinkedList可以通过包装类来让他们达到同步的效果,但是效率大大下降了。如:List<Map<String,Object>> data=Collections.synchronizedList(new ArrayList<Map<String,Object>>())或者使用synchronized关键字。

2、数据增长:从内部实现机制来讲ArrayList和Vector都是使用Object的数组形式来存储的,当你想着两种类型中增加元素的时候,如果元素的数目超过了内部数组目前的长度,他们需要扩容。Vector默认的情况下自动增长到原来的一倍数组胀肚,ArrayList是:L=l*(3/2)+1;所以你获得的这个集合所占的空间总是比你实际需要的更大。所以如果你要在集合中保存大量的数据那么使用Vector有一些又是,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。而LinkedList在每一个数据节点占用空间更多,因为LinkedList是使用链表的形式来完成的。

3、检索、插入、删除对象的效率:ArrayList和Vector中,从指定的位置(用index)检索一个对象,或者在集合的末位插入、删除一个对象的时间是一样的,可表示为O(1)。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线性增长:O(n-i),其中n代表集合中元素的个数,i代表增加或移除元素的索引位置。因为在执行上述操作之后,集合中的第i和第i之后的元素都要执行(n-i)个对象的位移操作。LinkedList中,在插入、删除集合中任何一个位置所花费的时间都是O(1),但是她在索引一个元素的时候比较慢,为o(i),其中i是索引的位置.

总结:1、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。2、对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。3、对于新增和删除操作add和remove。LinkedList比较占优势,因为ArrayList要移动数据。4、ArrayList的空间浪费主要体现在list列表的结尾预留一定的容量空间而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当空间。

Map接口

Map(映射)是一个存储键值对的容器接口。每个元素包含一个key对象和value对象,且元素不允许重复。

Map接口的实现主要有:HashMap是最常用的一个实现。HashMap使用hash映射来存取数据,这个速度是相当快,是o(1)其容量capacity和负载因子load factor可以在一开始设定。默认为16和0.75。当元素个数达到capacity*load factor的时候,就会进行扩容。

LinkedHashMap和HashMap类似和HashMap类似,只不过内部用链表来维护次序。因此遍历时候的顺序时其插入顺序。

TreeMap是基于红黑树的Map,插入的数据有次序保存,并且有很高的效率。因此在遍历输出的时候可以得到排序的数据,但是这要求插入的数据实现了comparable接口。

HashMap和HashTable的区别

HashSet内部也是使用的HashMap来存储。

HashMap的key值和value值均可以为null值。HashTable(put和get方法都加上了synchronized关键字)的key值和value值均不可为null值,且key值不能重复,一旦重复不会报错,但是会覆盖原来的值。

HashMap效率高,因为他不是线程安全的,而HashTable是线程安全的;HashMap可以存储null的key值,HashTable不行;迭代算法不同,HashMap使用fail-fast,所以在有其他线程更改了结构会抛出异常。HashTable是线程安全的,所以在单线程操作中效率比HashMap慢;HashMap不能保证元素次序是一直不变的(再添加过程中,超过容积,就会像ArrayList那样增加到原有的两倍,然后会倒序的方式装进去,顺序就变了)

HashMap和ConcurrentHashMap的区别


在HashMap的基础上,ConcurrentHashMap(value是volatile的;next是final的,保证了一旦HashEntry取出来,整个链表就是正确的)将数据分为多个segment,默认16个(concurrency level),然后每次操作对一个segment加锁,避免多线程锁得几率,较HashTable提高并发效率。

list、set、map遍历

一、map遍历

1、取两次值

for (String key : map.keySet()) { 
    System.out.println(key + map.get(key)); 

2、通过Map.entrySet使用iterator遍历key和value

Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); 
while (iterator.hasNext()) { 
    Map.Entry<String, String> entry = iterator.next(); 
    System.out.println(entry.getKey() + entry.getValue()); 

3、通过Map.entrySet遍历key和value(推荐容量大时使用)

for (Map.Entry<String, String> entry : map.entrySet()) { 
    System.out.println(entry.getKey() + entry.getValue()); 

4、通过Map.values()遍历所有的value,但不能遍历key

for (String value : map.values()) { 
    System.out.println(value); 

二、List的遍历

1、普遍使用,效率最高

for (int i = 0; i < list.size(); i++) { 
    System.out.println(list.get(i)); 

2、迭代遍历

Iterator<String> iterator = list.iterator(); 
while(iterator.hasNext()){ 
    System.out.println(iterator.next()); 

3、for循环遍历

for(String data : list){ 
    System.out.println(data); 

三、Set的遍历

1、迭代遍历

Iterator<String> iterator = set.iterator(); 
while (iterator.hasNext()) { 
    System.out.println(iterator.next()); 

2、for循环遍历

for (String data : set) { 
    System.out.println(data); 

阅读更多

没有更多推荐了,返回首页