您的位置:首页 > 编程语言 > Java开发

牛客网刷题知识点总结(五)java容器

2017-08-14 15:22 253 查看
五、java容器

1.  关于HashMap的一些说法:

a)  HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。HashMap的底层结构是一个数组,数组中的每一项是一条链表。

b)  HashMap的实例有俩个参数影响其性能: “初始容量” 和 装填因子。

c)  HashMap实现不同步,线程不安全。  HashTable线程安全

d)  HashMap中的key-value都是存储在Entry中的。

e)  HashMap可以存null键和null值,不保证元素的顺序恒久不变,它的底层使用的是数组和链表,通过hashCode()方法和equals方法保证键的唯一性

f)  解决冲突主要有三种方法:定址法,拉链法,再散列法。HashMap是采用拉链法解决哈希冲突的。

注: 链表法是将相同hash值的对象组成一个链表放在hash值对应的槽位;

   用开放定址法解决冲突的做法是:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。 沿此序列逐个单元地查找,直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。

  拉链法解决冲突的做法是: 将所有关键字为同义词的结点链接在同一个单链表中 。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α可以大于1,但一般均取α≤1。拉链法适合未规定元素的大小。

   

2.  Hashtable和HashMap的区别:

a)   继承不同。

 public class Hashtable extends Dictionary implements Map

public class HashMap extends  AbstractMap implements Map

b)  Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

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

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

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

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

 

注:  HashSet子类依靠hashCode()和equal()方法来区分重复元素。

     HashSet内部使用Map保存数据,即将HashSet的数据作为Map的key值保存,这也是HashSet中元素不能重复的原因。而Map中保存key值的,会去判断当前Map中是否含有该Key对象,内部是先通过key的hashCode,确定有相同的hashCode之后,再通过equals方法判断是否相同。

3. 初始容量只是哈希表在创建时的容量。加载因子
是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,通过调用
rehash 方法将容量翻倍。
说的通俗一点啊 比如说你要装水 你首先找个一个桶
这个桶的容量就是加载容量,加载因子就是比如说你要控制在这个桶中的水要不超过水桶容量的多少,比如加载因子是0.75
那么在装水的时候这个桶最多能装到3/4 处, 这么已定义的话 你的桶就最多能装水 = 桶的容量 * 加载因子。
如果桶的容量是40 加载因子是0.75 那么你的桶最多能装40*0.75 = 30的水。
如果你要装的水比30 多 那么就该用大一点的桶 而rehash就是负责增加桶的容量的方法。

4.   ConcurrentHashMap引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的Segment,根据key.hashCode()来决定把key放到哪个Segment中。
(一个Segment可以看做一个HashTable) 
在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中。
举例,多个线程访问同一个ConcurrentHashMap,如果这些线程操作的是不同的Segment,那么不会发生阻塞。否则会发生阻塞。

 
  Hashtable是用synchronized实现并发控制的,synchronized是针对整张Hash表,即每次锁住整张表让线程独占。
 
  ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

5. ThreadLocal是一个线程局部变量,为每个使用该变量的线程分配一个独立的变量副本。所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
  因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步  。
详细参考
      http://blog.csdn.net/zhoudaxia/article/details/37397575
        实现原理  
      ThreadLocalMap,,,这个map的键是 当前对象 ,, 值是某变量。
 
      最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等 ( 典型的应用莫过于Spring,Hibernate等框架中对于多线程的处理了。比如Hibernate中Session的处理,Spring中数据库的连接。)

6.TreeSet的底层实现是TreeMap。 TreeMap的底层实现是红黑树,红黑树是一棵平衡排序二叉树,普通的排序二叉树可能会出现失衡的情况,所以下一步就是要进行调整。
 在TreeMap的put()的实现方法中主要分为两个步骤,第一:构建排序二叉树(可能会失衡),第二:平衡二叉树。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: