首页 > 编程 > Java > 正文

Java集合框架学习

2019-11-08 01:32:16
字体:
来源:转载
供稿:网友

今天看了一下集合框架,其实指的就是Collection接口和Map接口,其中Collection接口是Iterable接口的子接口。而Map接口上面已经没有父类接口了。 其中,Iterable接口包含三个方法

一、Collection接口 从Collection接口,就是我们的框架内容了,大致将一下,Collection接口下面有很多的子接口,其他的没用过,但是有三个我们经常碰见的,就是Set , List,Queue List:是一种底层是数组实现的, 元素可重复的有序集合,下面有很多实现,比如ArrayList,LinkedList , Vector等 Set:底层是hash表实现的,不可重复的无序集合,下面的实现有HashSet,TreeSet等 Queue:用于装载先进先出原则的数据 ,下面的实现有Dequeue,LinkedList等。 这里写图片描述

下面来介绍集中常用的实现 1、ArrayList,最常用的集合,底层是数组,源码中的定义如下,和父类List接口一直,是可以存放重复的元素 ,且存放的元素是有序的。

/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-PRivate to simplify nested class access

ArrayList与普通的数组有什么区别呢? 最大的区别就是数组的长度是固定的,不可变的,一旦超出数组的长度范围是会报错的,而ArrayList底层虽然也是数组,但是长度却是可变的,每次增加元素是,也就是add方法,都将会检查一遍上面定义的这个数组的长度是否足够,不够的话,将新建一个新的数组,并将老的数组复制到新的数组当中。

public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0)//如果下标大于数组长度,则需要新建一个数组 grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }

第二点就是,集合做到动态扩容牺牲的是自身的效率,因此,数组的效率是比集合要高的。 第三,集合定义了remove()方法删除自身元素,而数组没有。 第四点,集合存入对象时,抛弃类型信息,所有对象屏蔽为Object,编译时不检查类型,但是运行时会报错。而数组一旦定义好了,如果存放不同类型的数据,编译就会不通过。这个区别总结起来就是,数组只能存放单一类型,而集合可以存放任意类型,默认就是Object,所有对象。

当然了,集合和数组也可以转换,只限于集合存放单一类型 集合–>数组,List.toArray() 数组–>集合,Array.asList()

2、LinkedList

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable

看定义我们就知道,LinkedList是实现了List和Queue接口的。底层是链表实现的。LinkedList通过代价较低的在List中间进行插入和删除操作,提供了优化的顺序访问。也即是说,相比于ArrayList,LinkedList的插入删除速度是比ArrayList慢的,而查询的速度却更加的快。 源码中,unlinkLast()方法和unlinkFirst(),顾名思义,也就是pollLat()he pollFirst()的调用,里面是这么写的:

private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; } /** * Unlinks non-null last node l. */ private E unlinkLast(Node<E> l) { // assert l == last && l != null; final E element = l.item; final Node<E> prev = l.prev; l.item = null; l.prev = null; // help GC last = prev; if (prev == null) first = null; else prev.next = null; size--; modCount++; return element; }

里面的这句help GC很有意思,意思是让某个对象=null,就能被GC掉,否则这个对象永远不会被GC,为什么呢?翻翻JVM书可以找到答案。

3、Vector List的另一种实现,使用方法和ArrayList一样,但是,人家是线程安全的,所有操作元素的方法都加了synchronized关键字,这也是两者的最大的区别。 两者还有一个不同点,就是两者的扩容方式: ArrayList:初始容量*3/2+1 Vector:默认扩充两倍。

4、HashSet 说HashSet之前先看看下面的HashMap,因为HashSet是对HashMap的一层包装,内部就是一个HashMap,没什么区别。先看HashMap。

5、HashMap Map接口的实现类。以key/value键值对存放数据,key值不允许为空,value可以为空,且由于容器可能会对元素进行重新hash,HashMap无法保证元素是有序的。 重新Hash之后,有可能会产生冲突,HashSet处理冲突时候,采用的是冲突链表方式。 HashMap的性能问题,一般来说,put和get是可以在常数时间内完成,但是,如果要对HashMap进行迭代,就需要去遍历整个HashMap和冲突链表。因此,如果是迭代次数比较多的场景,HashMap的初始值不应该设置太大。 有两个参数可以影响HashMap的性能,一个是初始容量(inital capacity)和负载系数(load factor),负载系数指的是自动扩充容量的临界值。当entry的数量大于(初始容量*和负载系数)时,HashMap将进行扩容,且重新计算Hash。所以,对于插入操作较多的场景,将初始值设置稍大,可以减少重新Hash的次数。 另外,将对象放到HashMap中时,需要注意两个方法,hashCode()和equals(),当插入对象时,是通过hashCode计算Hash值判断对象应该插入到什么位置,当Hash值重复时,就要通过equals()方法去判断是不是同一个对象。所以说,如果要将自定义的对象放入到HashMap中,需要重写这两个方法。

6、HashTable 也是Map的实现类,与HashMap一样,唯一不同的就是,HashTable是同步的。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表