静态 shuffle()方法
//使用默认随机源对列表进行置换,所有置换发生的可能性都是大致相等的
static void shuffle(List<?> list)
//使用指定的随机源对指定列表进行置换,所有置换发生的可能性都是大致相等的,假定随机源是公平的
static void shuffle(List<?> list, Random rand)
Map
Map 是先根据Key值的hashcode分配和获取对象保存数组下标的,然后再根据equals区分唯一值
HashMap
https://crossoverjie.top/2018/07/23/java-senior/ConcurrentHashMap/
HashMap 底层是基于 数组 + 链表
组成的
HashMap 中比较核心的几个成员变量:
- 初始化桶大小,因为底层是数组,所以这是数组默认的大小。
- 给定的 HashMap 的容量大小是固定,给定的默认容量为 16
- 桶最大值。
- 默认的负载因子(0.75)
table
真正存放数据的数组。Map
存放数量的大小。- 桶大小,可在初始化时显式指定。
- 负载因子,可在初始化时显式指定。
Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12
就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作,所以非常消耗性能。
- 因此通常建议能提前预估 HashMap 的大小最好,尽量的减少扩容带来的性能损耗
put()
存值规则:把Key的hashCode 与HashMap的容量 取余得出该Key存储在数组所在位置的下标
- hashCode & (HashMap容量-1)
HashMap不是线程安全的
在多线程环境下,操作HashMap会导致各种各样的线程安全问题,比如
- 在HashMap扩容重哈希时出现的死循环问题,脏读问题等
HashMap的这一缺点往往会造成诸多不便,虽然在并发场景下HashTable和由同步包装器包装的HashMap(Collections.synchronizedMap(Map<K,V> m) )可以代替HashMap,但是它们都是通过使用一个全局的锁来同步不同线程间的并发访问,因此会带来不可忽视的性能问题
ConcurrentHashMap
https://blog.csdn.net/justloveyou_/article/details/72783008
ConcurrentHashMap是J.U.C(java.util.concurrent包)的重要成员
是HashMap的一个线程安全的、支持高效并发的版本,无论是读操作还是写操作都能保证很高的性能:
进行读操作时(几乎)不需要加锁,在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问
特别地,在理想状态下,ConcurrentHashMap 可以支持 16 个线程执行并发写操作(如果并发级别设为16),及任意数量线程的读操作。
List
不带参数的toArray方法,是构造的一个Object数组,然后进行数据拷贝
- 如果要把一个List直接转化为Object数组,则可以直接使用Object[] o = list.toArray();
根据参数数组的类型,构造了一个对应类型的,长度跟ArrayList的size一致的空数组
- 如果要转化为String数组,则有以下两种方式:
方法一、String[] arr = new String[list.size]; list.toArray(arr);//此时arr就有了list中的值了
方法二、String[] arr = (String[])list.toArray(new String[0]);
set
Set区别对象是不是唯一的标准是,两个对象hashcode是不是一样,再判定两个对象是否equals;