深入理解java集合类及其运用总结及经验分享

忠所周知java集合类的运用非常之广泛,小到面试的时候面试官都会经常问到的hashMap与hashTable的区别,举例说明collection集合类的几种形式(set,map,list)并说明其各自的区别;大到平时运用到的各种集合类的选择以及不同运用场景下的使用,如:一般arraylist实现类的使用,map的使用等。下面我们将从list、set、map的介绍以及collection的iterator的介绍中进一步加大大家对集合类的印象。
list为一种有序可重复的集合接口,其常用的实现类包括,Vector、LinkedList和ArrayList等,list一个重要的特点是集合中的每个元素都有其对应的顺序,Vector与ArrayList的主要区别是Vector是线程安全的,而ArrayList则不是,在这里很多初学者可能就得懵逼了,线程安全到底是怎样的一个概念呢,说到线程安全,首先我们得来解释两个名词,一个叫做工作内存,另外一个叫做主内存,工作内存是指java虚拟机给我们所使用的list对象分配的内存,而主内存是程序运行主线程占用的内存,当我们对list进行操作时,Vector线程安全指的是list在工作内存中进行工作,同时java虚拟机为这个线程分配了一个线程锁,即当对象占用线程锁时其他线程想要去修改操作这个对象需要等占有锁的对象把锁主要释放或者锁超时。这里我们一般使用的list的实现类一般为ArrayList,因为是使用Vector时集合的效率要远远下降,当多个线程同时操作同一个list的时候会出现ConcurrentModificationException。下面再来讲讲我们的LinkedList,LinkedList是list的链表实现方式,当插入、删除元素的速度非常快,ArrayList在进行插入、删除元素的时间复杂度为O(n),而LinkedList为O(1),因为其本身就存有list的指针,而ArrayList在查找的速度上则要比LinkedList快得多。

set集合一个最大的特点是无需不可重复。set判断两个元素是否一致的方式是equals,当equals为false时,这两个元素则不允许同时存在。HashSet是set接口的重要实现,HashSet按set的hashcode()方法计算出set所对应的哈希码,因此具有很多的存储和查找性能。HashSet可以保存null元素。HashSet在初始化的时候具有16的初始容量和0.75的加载因子,当hashset的长度达到16*0.75时,java虚拟机会对其长度进行rehash,变成16*2即32,其容量大小必须为2的次幂,这种特性是由HashSet的底层实现hashMap决定的。值得一提的是,当加载因子小的时候查询的效率越大,但浪费的空间也很大,当加载因子大的时候,浪费的空间小,当查询效率差,容易出现数据冲突。下面我们来看看hashSet的部分源码:

public class HashSet extends AbstractSet implements Set, Cloneable,Serializable {
               private transient HashMap map;
               private static final Object PRESENT = new Object();

               public HashSet() {
                   map = new HashMap();
               }
               public Iterator iterator() {
                   return map.keySet().iterator();
               }
               public boolean add(E e) {
                   return map.put(e, PRESENT)==null;
               }
               public boolean remove(Object o) {
                   return map.remove(o)==PRESENT;
               }
           }

从HashSet的源码中我们不难看出其底层是HashMap构成,我们在往HashSet中存储数据的时候,存的都是HashMap的键值,它们的value都是一样的:private static filna Object PRESENT=new Object()。HashSet在Hash表中的存储包括存储其key、value和hashcode一共三列,我们在调用HashSet的add方法时,java虚拟机首先会计算value值的hashcode,再根据hashcode计算出来的索引进行遍历,调用key的equals方法,当vlaue已经存在时,则将原来的指进行替换,并返回之前的值,否则就返回null。这里,我们的HashSet也是线程不同步的。
下面我们再来讲一下map, map用于保存具有映射关系的数据。map接口有如下几个常用的实现类:HashMap、HashTable、TreeMap。TreeMap是基于红黑树对TreeMap中所有key进行排序,HashMap和HasTable的区别只要有两点,一是hashTable是线程安全的而HashMap不是,二是hashMap允许null作为key和value,这里有一点需要注意的是,HashMap只能有一个key为null,而允许有多个value为null。
前面讲述了collection集合类的一些特征,下面让我们来讲解以下这几个集合类的一些联系,Set与Map的关系,Map的key所有key集合结合起来就是Set集合,所以map中提供Set keySet()方法返回所有key组成的set集合。Map与List的关系,Map集合的key-value相当于List中的一个对象。

猜你喜欢

转载自blog.csdn.net/DanielAntony/article/details/52972581
今日推荐