集合 详解

简介: 集合 详解

1.List:是有序的Collection。使用此接口能够精确地控制每一个元素插入的位置。用户能够使用索引(元素在list中的位置,类似于数组下标)来访问list中的元素。和Set不同,List允许有相同的元素。常见的List的实现类:

①.LinkedList:是以元素列表的形式存储它的数据,每一个元素都和它的前一个元素和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(N)。提供了额外的get、remove、insert方法在linkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack)、队列(queue)或双向队列(deque).此方法非同步。

②.ArrayList:它的底层是数组,实现了可变大小的数组,它可以以O(1)时间复杂度对元素进行随机访问。每个ArrayList实例都有一个容量,表示存储元素的数组大小,这个容量可随着不断添加新元素而自动增加。此方法非同步。

对比:相对于LinkedList,  ArrayList的插入,添加,删除操作速度慢一些,因为当元素被添加到集合任意位置的时候,需要像数组那样重新计算大小或者是更新索引。

但LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向后一个元素。

2.Set:它具有和Collection完全一样的接口,没有任何额外的功能。它是一种不包含重复元素的Collection。Set最多有一个null元素。public interface Set extends Collection,  常用的Set的实现类有:

①.HashSet:内部使用Map保存数据,即将HashSet的数据作为Map的数据作为Map的key值保存,这也是HashSet中元素不能重复的原因。而Map中保存key值前,会先判断当前Map对象,内部是通过key的hashcodes确定有相同的hashcode之后,再通过equal方法判断是否相同。此实现不是同步的。(无序) 时间复杂度是 O(1).

public class HashSet
    extends AbstractSet
    implements Set, Cloneable, java.io.Serializable
{....}

②.LinkedHashSet:基于可预知迭代顺序的set接口的哈希表和链接列表实现。与HashSet的不同点:LinkedHashSet它维护着一个运动于所有条目的双重链接列表。

③.TreeSet是由一个树形的结构来实现的,底层是红黑树。它里面的元素是有序的。因此add(),remove(),contain()方法的时间复杂度是O(logn);

public class HashSet
    extends AbstractSet
    implements Set, Cloneable, java.io.Serializable
{...}

3.Map:没有继承Collection接口,他提供key到value的映射。一个map中不能包含相同的key.map接口提供了3种集合的试图,map的内容可以被当作一组key集合、一组value集合,或者一组key-value映射。常用的map的实现类:

①.HashMap:底层是数组加链表实现的哈希表。允许null作为键,null作为值。线程不安全。(查找快,插入,删除也快),为什么用数组+链表实现吗?

        i>利用拉链法解决冲突:把所有的同义词用单链表连接起来。该方法下,哈希表每一个单元中存放的不再是元素本身,而是相应同义词单链表的头指针。

       ii>HashMap维护了一个Entry数组,Entry内部类有key,value,hash,next四个字段,其中next也是一个Entry类型,可以将Entry数组理解为一个个的散列桶。每一个桶实际上是一个单链表。当执行put操作时,会根据key的HashCode定位到相应的桶。

      iii>遍历单链表检查该key是否已经存在,如果存在,覆盖该value,反之,新建一个新的Entry,并放在单链表的头部。

当通过传递key调用get方法时,它再次使用key.hashCode()来查找相应的散列桶,然后再使用key.equal()方法找出单链表中正确的Entry,然后返回它的值。

②.HashMap和HashTable的区别:(都实现了Map接口)

i> HashMap是非线程安全的,HashTable是线程安全的。(Hasptable的方法是synchronize的,而HashMap不是,在多个线程访问HashTable时,不需要自己为他的方法实现同步,而HashMap就必须为之提供外同步)。

ii>HashTable不允许键和值出现null值。

HashMap的键和值都允许有null值存在,null可以作为键,但是这样的键只有一个,可以有一个键或多个键的值为null,当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键而应该用containsKey()方法来判断。

iii>因为线程安全问题,HashMap效率比HashTable高。

iv>两个遍历方式的内部实现上不同。(Hashtable、HashMap都使用了Iterator.而由于历史原因,Hashtable还使用了Enumeration的方式)。

v>哈希值的使用不同,HashTable直接使用对象的hashCode.而HashMap重新计算hash值。

vi>Hashtable和HashMap他们两个内部实现方式的数组的初始大小和扩容方式。HashTable中hash数组默认大小是11,增加的方式是old*2+1.HashMap中hash数组的默认大小为16,而且一定是2的指数。

vii>HashTable继承自Dictionary类,而HashMap是继承了AbstractMap类。下面是源码:

public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

........

}

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

.......

}

相关文章
|
4天前
|
存储 Java 索引
JAVASet集合
JAVASet集合
28 0
|
4天前
集合
数组的长度不可以发生改变。 但是ArrayList集合的长度是可以随意变化的。 对于ArrayList来说,有一个尖括号代表泛型。 泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。 注意:泛型只能是引用类型,不能是基本类型。 注意事项: 对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。如果内 容是空,得到的是空的中括号:[]
30 0
|
7月前
|
存储 Java 索引
1.9 集合
1.9 集合
28 1
|
11月前
|
索引
集合理解
集合的个人理解笔记 与二叉查找树规律
51 0
|
存储 JavaScript 前端开发
集合的实现
集合的实现
集合的实现
|
存储 算法 安全
|
存储 算法 安全
集合总结
集合总结
74 0
|
存储 安全 Java
第9章 集合
集合体系、集合的数据结构以及操作。
91 0
GoogleGuava - 第 2 章 集合——不可变集合
GoogleGuava - 第 2 章 集合——不可变集合
101 0
GoogleGuava - 第 2 章 集合——不可变集合