JAVA葵花宝典

---------------java基础-----------------

你都知道哪些常用的Map集合?

  1. HashMap
    底层数组+链表实现,可以存储null键和null值,线程不安全
    初始size为16,扩容:newsize = oldsize*2,size一定为2的n次幂
    扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入
    插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)
    当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀
    计算index方法:index = hash & (tab.length – 1)
  2. HashTable
    底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化
    初始size为11,扩容:newsize = olesize*2+1
    计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length
  3. ConcurrentHashMap
    底层采用分段的数组+链表实现,线程安全
    通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是
    volatile的,也能保证读取到最新的值。)
    Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
    有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁
    扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

HashMap的get过程

①、调用 hash(K) 方法(计算 K 的 hash 值)从而获取该键值所在链表的数组下标;②、顺序遍历链表,equals()方法查找相同 Node 链表中 K 值对应的 V 值

HashMap的put过程

①、调用 hash(K) 方法计算 K 的 hash 值,然后结合数组长度,计算得数组下标;②、调整数组大小(当容器中的元素个数大于 capacity * loadfactor 时,容器会进行扩容resize 为 2n);
③、i.如果 K 的 hash 值在 HashMap 中不存在,则执行插入,若存在,则发生碰撞;
ii.如果 K 的 hash 值在 HashMap 中存在,且它们两者 equals 返回 true,则更新键值对;
iii. 如果 K 的 hash 值在 HashMap 中存在,且它们两者 equals 返回 false,则插入链表的尾部(尾插法)或者红黑树中(树的添加方式)

HashMap初始化容量、扩容机制

默认大小为16。初始化容量是比传入容量参数值大的最小的2的n次方,比如传入6,实际分配8。
当hashmap中的元素个数超过数组大小*loadFactor(默认值为0.75)时就会把数组的大小扩展为原来的两倍大小,然后重新计算每个元素在数组中的位置

怎么按添加顺序存储元素

按添加顺序使用LinkedHashMap,
按自然顺序使用TreeMap,
自定义排序TreeMap(Comparetor c)

HashMap 的遍历方

  1. for-each map.keySet() – 只需要K值的时候,推荐使用 for (String key :
    map.keySet()) {
    map.get(key); }
  2. for-each map.entrySet() – 当需要V值的时候,推荐使用 for (Map.Entry String> entry : map.entrySet()) {
    entry.getKey();
    entry.getValue(); }
  3. for-each map.entrySet().iterator() Iterator String>> iterator = map.entrySet().iterator();
    while (iterator.hasNext()) {
    Map.Entry entry = iterator.next();
    entry.getKey();
    entry.getValue(); }

List

List,Set都是继承自Collection接口。都是用来存储一组相同类型的元素的。
List特点:元素有放入顺序,元素可重复 。有顺序,即先放入的元素排在前面。
Set特点:元素无放入顺序,元素不可重复。无顺序,即先放入的元素不一定排在前面。不可重复,相同元素在set中只会保留一份。所以,有些场景下,set可以用来去重。
List主要有ArrayList、LinkedList与Vector几种实现
ArrayList:底层的数据结构使用的是数组结构(数组长度是可变的百分之五十延长)(特点是查询很快,但增删较慢)线程不同步
LinkedList:底层的数据结构是链表结构(特点是查询较慢,增删较快)
Vector:底层是数组数据结构 线程同步(数组长度是可变的百分之百延长)(无论查询还是增删都很慢,被ArrayList替代了)。其他要实现线程安全使用工具类Collections.synchronizedList(new ArrayList())方法

Array.asList获得的List有何特点

  1. asList 得到的只是一个 Arrays 的内部类,一个原来数组的视图 List,因此如果对它进行增删操作会报错
  2. 用 ArrayList 的构造器可以将其转变成真正的 ArrayList

Set

Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set具有与Collection完全一样的接口,实际上Set就是Collection,只 是行为不同。
Set接口主要实现了两个实现类
HashSet类按照哈希算法来存取集合中的对象,存取速度比较快
TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。

“==” 和 equals()的区别

基本数据类型比较的是值;
引用类型比较的是地址值。

你可能感兴趣的:(java)