Ozpin
发表于 2021-3-2 21:28
RE: 股票实战:转债期权·小灶营分队 [修改]
shoupelai
发表于 2021-3-2 21:50
资源收藏了
bashen
发表于 2021-3-2 22:10
股票实战:转债期权·小灶营分队
qiqi
发表于 2021-3-2 22:17
股票实战:转债期权·小灶营分队 [修改]
呆萌钟
发表于 2021-3-2 22:18
1. linkedList与arrayList区别 适用场景
• 区别:
a. 数据结构不同,ArrayList是基于数组实现的,LinkedList是基于双向链表实现的;
b. LinkedList不仅是List接口的实现类,可以根据索引来随机访问集合中的元素,另外,LinkedList还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双向队列,因此LinkList可以作为双向队列、栈和List集合使用;
c. 因为ArrayList是基于索引的数据结构,它使用索引在数组中搜索和读取数据是很快的,可以直接返回数组中索引位置的元素,因此在随机访问集合元素上有较好的性能。ArrayList获取数据的时间复杂度是O(1),但是要插入、删除数据却是开销很大,因为这需要移动数组中插入位置之后的所有元素;
d. 相比于ArrayList,LinkedList的随机访问集合元素时性能较差,因为需要对双向链表进行遍历;但在插入,删除操作是更快的,因为LinkedList不像ArrayList,不需要改变数组的大小,也不需要在数组装满的时候将所有的数组重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。
e. LinkedList需要更多的内存,因为ArrayList的每个索引的位置存储的是实际的数据,而LinkedList的每个节点中存储的是实际的数据和前后节点的地址。
• 使用场景:
a. 如果应用程序对数据有较多的随机访问,ArrayList对象要优于LinkedList;
b. 如果应用程序有更多的插入或者删除操作,较少的数据读取,LinkedList对象要优于ArrayList对象;
c. 不过,ArrayList的插入,删除操作也不一定比LinkedList慢,如果在ArrayList靠近末尾的地方插入,那么ArrayList只需要移动较少的数据,而LinkedList则需要一直查找到列表尾部,反而耗费较多时间,这时ArrayList要比LinkedList要快。
2. ArrayList和LinkedList的插入和访问的时间复杂度?
• ArrayList 是线性表(数组)
○ get() 直接读取第几个下标,复杂度 O(1)
○ add(E) 添加元素,直接在后面添加,复杂度O(1)
○ add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)
○ remove()删除元素,后面的元素需要逐个移动,复杂度O(n)
•LinkedList 是链表的操作
○ get() 获取第几个元素,依次遍历,复杂度O(n)
○ add(E) 添加到末尾,复杂度O(1)
○ add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n)
○ remove()删除元素,直接指针指向操作,复杂度O(1)
• 当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
3. ArrayList是如何扩容的
扩容原来数组的1.5倍,并把老数组copy到新数。
4. ArrayList是否会越界?
会。
○ 调用空参构造函数创建对象后,直接调用add(index,element)方法时会引发数据越界异常;
○ 多线程并发情况下也有可能出现越界异常;
5. hashset存的数是有序的么?
HashSet的元素无序不可重复。
6. ArrayList和hashset有何区别?
○ ArrayList实现的是List接口,HashSet实现的是Set接口
○ ArrayList存储的元素有序可重复,HashSet存储的元素无序不可重复
○ ArrayList底层实现是基于数组,HashSet底层实现是基于哈希表
7. 说说HaspMap底层原理?
HashMap基于Hash算法,我们通过put(key,value)存储,get(key)来获取。当传入key时,HashMap会根据key.hashCode()计算出hash值,根据hash值将value保存在bucket里。当计算出的hash值相同时,我们称之为Hash冲突,HashMap的做法是用链表和红黑树存储相同hash值的value。当Hash冲突的个数比较少时,使用链表,否则使用红黑树。
8. Java8中的HashMap有什么变化?
○ 底层数据结构不同:1.7是数组+链表,1.8是数组+链表+红黑树
○ 插入键值对的方式不同:1.7中采用头插法,1.8中采用尾插法
○ 哈希表初始化方式不同:1.7中会先初始化一个数组,而1.8中是在首次put时候才会调用resize方法进行扩容
○ hash函数对哈希值的计算方式不同:1.7中直接计算key的hashCode值,1.8中则采用key的hashCode异或上key的hashCode进行无符号右移16位的结果,避免了只靠低位数据来计算哈希时导致的冲突,计算结果由高低位结合决定,使元素分配更均匀
○ 扩容策略不同:1.7中是只要不小于阈值就直接扩容2倍;而1.8的扩容策略会更优化,当数组容量未达到64时,以2倍进行扩容,超过64之后若桶中元素个数不小于7就将链表转换为红黑树,但如果红黑树中的元素个数小于6就会还原为链表
9. HashMap的底层数据结构
○ 1.7是数组+链表
○ 1.8是数组+链表+红黑树
10.1.8还采用了红黑树,讲讲红黑树的特性
1,每个节点要么是红色,要么是黑色。
2,根节点必须是黑色。叶子节点必须是黑色NULL节点。
3,红色节点不能连续。
4,对于每个节点,从该点至叶子节点的任何路径,都含有相同个数的黑色节点。
5,能够以O(log2(N))的时间复杂度进行搜索、插入、删除操作。此外,任何不平衡都会在3次旋转之内解决。
11. 为什么HashMap要用红黑树而不是AVL树?
红黑树的查询性能略微逊色于AVL树,因为其比AVL树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的AVL树最多多一次比较,但是,红黑树在插入和删除上优于AVL树,AVL树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于AVL树为了维持平衡的开销要小得多
12. 红黑树需要比较大小才能进行插入,是依据什么进行比较的?
是根据插入节点的hash值进行比较的
13. HashMap的时间复杂度?
• 不管插入还是查找,由key获取hash值然后定位到桶的时间复杂度都是O(1)
• 真正决定时间复杂度的实际上是桶里面链表/红黑树的情况:
○如果桶里面没有元素,那么直接将元素插入/或者直接返回未查找到,时间复杂度就是O(1)
○ 如果里面有元素,那么就沿着链表进行遍历,时间复杂度就是O(n),链表越短时间复杂度越低
○ 如果是红黑树的话那就是O(logn)
14. HashMap如何解决Hash冲突?
采用的是链表法,将相同hash值的对象组织成一个链表放在hash值对应的槽位,JDK18时,会在链表长度超过8时,把链表转化成红黑树,后续的节点插入到红黑树中
15. HashMap检测到hash冲突后,将元素插入在链表的末尾还是开头?
1.7中采用头插法,1.8中采用尾插法
16. HashMap哈希函数的认识,JDK1.8采用的hash函数
1.7中直接计算key的hashCode值,1.8中则采用key的hashCode异或上key的hashCode进行无符号右移16位的结果,避免了只靠低位数据来计算哈希时导致的冲突,计算结果由高低位结合决定,使元素分配更均匀
17. HashMap怎么从链表转换为红黑树?
当数组长度大于64,且当链表已经有8个节点了,此时再新链上第9个节点,在成功添加了这个新节点之后,立马做链表转红黑树
18. HashMap如果存入的是null键,放在桶的哪个位置?
存在数组的第一个位置。
19. HashMap的put操作讲一下
a. 取key的hashCode进行高位运算,返回hash值
b. 如果数组为空,直接调用resize方法进行扩容
c. 如果数组不为空,对hash进行取模运算,得到数组的下标位置
d. 判断对应数组下标位置是否为空,为空则直接插入Node节点
e. 不为则判断是否为红黑树
f. 如果是红黑树,则判断TreeNode节点是否已经存在,如果存在,则直接返回原节点数据,并更新;不存在,则直接插入红黑树,超出负载容量就扩容
g. 如果是链表,则判断Node节点是否已经存在,如果存在,则直接返回原节点数据,并更新;不存在则直接插入链表尾部,然后判断链表长度,如果大于8则转为红黑树存储,超出负载容量就扩容
20. HashMap中的get()方法是如何实现的?
a. 对key进行哈希计算
b. 通过数组长度减一与hash值进行取模运算获取该key在数组的位置
c. 判断数组中的首节点是否为空,为空则直接返回空
d. 如果不为空,再判断节点key是否和目标值相同,相同则直接返回,不相同则判断节点的next引用是否为空,为空则直接返回空
e. 如果节点的next引用不为空,则判断是否为红黑树节点,如果是红黑树,则进入红黑树的取值流程,并返回结果
f. 如果是链表,则进入链表的取值流程,并返回结果
取值流程:key的哈希值相等并且key的值也相等
呆萌钟
发表于 2021-3-2 22:25
20. HashMap中的get()方法是如何实现的?
a. 对key进行哈希计算
b. 通过数组长度减一与hash值进行取模运算获取该key在数组的位置
c. 判断数组中的首节点是否为空,为空则直接返回空
d. 如果不为空,再判断节点key是否和目标值相同,相同则直接返回,不相同则判断节点的next引用是否为空,为空则直接返回空
e. 如果节点的next引用不为空,则判断是否为红黑树节点,如果是红黑树,则进入红黑树的取值流程,并返回结果
f. 如果是链表,则进入链表的取值流程,并返回结果
g. 取值流程:key的哈希值相等并且key的值也相等
21. HashMap在什么情况下会扩容,或者有哪些操作会导致扩容?
• 当向容器添加元素的时候,会判断当前容器的元素个数,如果大于等于阈值---即当前数组的长度乘以加载因子的值的时候,就要自动扩容;
• 当数组长度小于64时,链表长度如果达到8,不会进行树化,而会进行扩容操作
22. hashmap怎么扩容?
当向容器添加元素时,如果当前容量大于负载容量,则触发扩容,负载容量为数组长度*负载因子,默认负载因子是0.75,扩容时新建一个原数组两倍长的新数组,然后再把旧数组中的元素迁移到新数组。
23. hashmap扩容的时候怎么高效率的实现数据迁移?
旧数组元素迁移到新数组时,通过节点hash&(新数组长度-1)定位新数组中的位置,大大减少了之前已经散列好的老数组的数据位置重新调换,保证了数据分布的更加均匀。
24. hashmap每次扩容的容量为什么是2的幂次
因为Hashmap计算存储位置时,使用了(n - 1) & hash。只有当容量n为2的幂次方,n-1的二进制会全为1,位运算时可以充分散列,避免不必要的哈希冲突,所以扩容必须2倍就是为了维持容量始终为2的幂次方。
25. Hashmap增删的情况后端数据结构如何位移?
在JDK1.8中,增加元素的过程中,如果链表长度大于8会把链表转为红黑树;在删除元素的过程中,如果树中元素个数小于6,树会转为链表。
26. hashset和hashmap的区别?
• HashSet实现了Set接口
• HashMap实现了Map接口
• HashSet底层实现是基于HashMap
27. hashset底层实现
HashSet底层实现是基于HashMap
28. 并发容器了解哪些?
• ConcurrentHashMap
○ 对应的非并发容器:HashMap
○ 目标:代替Hashtable、synchronizedMap,支持复合操作
○ 原理:JDK6中采用一种更加细粒度的加锁机制Segment“分段锁”,JDK8中采用CAS无锁算法。
• CopyOnWriteArrayList
○ 对应的非并发容器:ArrayList
○ 目标:代替Vector、synchronizedList
○ 原理:利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用,并通过volatile 保证其可见性,当然写操作的锁是必不可少的了。
• CopyOnWriteArraySet
○ 对应的非并发容器:HashSet
○ 目标:代替synchronizedSet
○ 原理:基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。
• ConcurrentSkipListMap
○ 对应的非并发容器:TreeMap
○ 目标:代替synchronizedSortedMap(TreeMap)
○ 原理:Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。
• ConcurrentSkipListSet
○ 对应的非并发容器:TreeSet
○ 目标:代替synchronizedSortedSet
○ 原理:内部基于ConcurrentSkipListMap实现
• ConcurrentLinkedQueue
○ 不会阻塞的队列
○ 对应的非并发容器:Queue
○ 原理:基于链表实现的FIFO队列(LinkedList的并发版本)
• LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue
○ 对应的非并发容器:BlockingQueue
○ 特点:拓展了Queue,增加了可阻塞的插入和获取等操作
○ 原理:通过ReentrantLock实现线程安全,通过Condition实现阻塞和唤醒
○ 实现类:
§ LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列
§ ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列
§ PriorityBlockingQueue:按优先级排序的队列
29. 说说HashMap跟HaspTable和ConcurrentHashMap他们之间的区别?
• JDK1.7时,三者都是数组+链表,JDK1.8时,HashMap和ConcurrentHashMap改为数组+链表+红黑树
• HashMap的key和value都可以存储null值,Hashtable与ConcurrentHashMap的key和value都不能为null值
• HashMap是线程不安全的,Hashtable与ConcurrentHashMap都是线程安全的
• Hashtable默认初始化长度为11,HashMap与ConcurrentHashMap为16
30. ConcurrentHashMap如何解决线程安全,1.7版本以及1.8版本的不同?
• JDK1.7采用Segement分段锁+HashEntry的方式
• JDK1.8采用Node+CAS+Synchronized的方式
31. ConcurrenHashMap的put流程?
a. 如果没有初始化就先调用initTable()方法来进行初始化过程
b. 如果没有hash冲突就直接CAS插入
c. 如果还在进行扩容操作就先进行扩容
d. 如果存在hash冲突,就加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入
e. 最后一个如果该链表的数量大于阈值8,就要先转换成黑红树的结构,break再一次进入循环
f. 如果添加成功就调用addCount()方法统计size,并且检查是否需要扩容
32. Collections.sort底层排序方式?
Collections.sort方法底层就是调用的Arrays.sort方法,而Arrays.sort使用了两种排序方法,快速排序和优化的归并排序,快速排序主要是对那些基本类型数据(int,short,long等)排序, 而归并排序用于对Object类型进行排序。
小熊猫
发表于 2021-3-2 22:30
谢谢分享!!!!
kanpic
发表于 2021-3-2 23:17
实战:转债期权·小灶营分队 [复制链
zhaix
发表于 2021-3-2 23:29
学习一下,谢谢分享
delphijjk
发表于 2021-3-2 23:32