Java数据结构
java因为其特殊性,对它的数据结构。可分为如下:
http://www.2cto.com/kf/201506/412305.html
Collection,List,Set,Map都是接口。
接下来按照顺序,依次对每一个集合接口进行说明。
ArrayList: 是线程不安全的。默认容量为20,每次扩容为当前容量的两倍,支持随机访问。一种遍历方式是采用迭代器。另一种是采用随机访问,也即采用数组下标访问。现在显示迭代器的代码如下:
List<String> list = new ArrayList();
Iterator<String> integer = list.Iterator();
while(integer.hasNext()){
int value = integer.next();
}
可以使用以下方法处理线程不安全情况:
一、使用synchronized关键词
二、使用Collections.synchronizedList();具体使用如下:
List<String> list = (Collections.synchronized)new ArrayList<>();
LinkedList: 是线程不安全的。不支持随机访问。在插入和删除元素方面,性能强于ArrayList。
Vector:
是线程安全的。操作比ArrayList慢。默认初始化10个数组,如果没有设置增长元素,则每次增长为当前容量的两倍。
HashSet: 基于HashMap来实现的,不能有重复元素。
(http://www.importnew.com/20386.html)这个地址讲解了JDK1.8中,HashMap的改进。值得一看。http://www.cnblogs.com/chenssy/p/3521565.html这一篇博客详细讲解了HashMap的源码以及内容等。
HashMap: HashMap 是线程不安全的。实现了Map接口。新建HashMap中,有基础容量,扩容因子。默认扩容因子为0.75。当HashMap中的元素大于基础容量 * 扩容因子,则会对其进行扩容。
在新建hash数组时,采用位运算,确保每次新建的数组长度为2的n次方。例如输入数组长度为5,则
length = 1;
while(length<5)
length << =1;
HashMap的实现是由数组和链表组成。在插入一个HashMap元素时,首先对元素进行hash值计算,计算完毕后,通过hash & (length - 1) ,即hash值对数组长度的位运算。在插入数据时,先判断数组上是否有数据,若无,则插入,若有,则比较两个的Key值是否相同,若相同,则用新值覆盖旧值,若不同,则将链表链接到新值上。
HashMap是线程不安全的,所以要保证安全,有两种方式:
一、使用Hashtable Map<String,String> llist = new Hash<String,String>();
Hashtable是使用synchronized来保证同步
二、使用ConcurrentHashMap
ConcurrentHashMap是使用锁分段技术来实现多线程访问。它将数据分为一段一段,对每一段加上锁。同一时刻,一个线程只能访问其中一段锁的数据,这就保证了其他的线程可以访问其他段锁的数据。每一段用Segment来标示。
为什么HashMap每次新建数组必须为2的n次方呢?
这是为了保证每次新进一个key,都能均匀的分布在数组中。我们接下来来看一个实验。假如n为5,则为16,那么length-1 = 15。则15标示为二进制位1111.
这样的格式,能够保证所有与它&操作,都是1或者0,而不会因为其中一个为0,另外的每一个操作都是0.例如如果是1110,那么最后一位,不管怎么&操作,都为0。
在JDK1.8中,HashMap当链表连接的数组超过8个时,则将其转换为红黑树进行保存。
TreeMap:
红黑树主要有以下特征,首先它是一颗二叉排序树,并且必须包含以下五个点:
1.每个点的 颜色不是红色就是黑色
2.根节点必须是黑色
3.如果一个节点是红色,则它的两个子节点必须是黑色
4.叶节点必须是黑色
5.从任一节点到每个叶子节点的路径,都必须包含相同数目的黑色节点。
红黑树里面的节点,均为排序好了的。
TreeMap底层是由红黑树来实现,是有序的。线程不安全的。