Skip to content

Commit 107e1fd

Browse files
committed
初步整理阿里面经
1 parent ae8c29e commit 107e1fd

12 files changed

Lines changed: 1393 additions & 14 deletions

notes/JavaArchitecture/01 Java 基础.md

Lines changed: 684 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
##### 6. 集合框架(Java Collections Framework Internals)
2+
3+
​ Java集合框架提供了数据持有对象的方式,提供了对数据集合的操作。Java集合框架位于`java.util`包下,主要有三个大类:`Collection``Map`接口以及对集合进行操作的工具类。
4+
5+
6+
7+
Java集合类的整体框架如下:
8+
9+
![](D:/gitdoc/2019_campus_appy/notes/pics/java_set_framework.jpg)
10+
11+
12+
13+
14+
15+
Collection
16+
17+
![]()
18+
19+
- `ArrayList`:线程不同步。默认初始容量为10,当数组大小不足时增长率为当前长度的`50%`
20+
- `Vector`**线程同步**。默认初始容量为10,当数组大小不足时增长率为当前长度的`100%`。它的同步是通过`Iterator`方法加`synchronized`实现的。
21+
- `LinkedList`:线程不同步。**双端队列形式**
22+
- `Stack`**线程同步**。继承自`Vector`,添加了几个方法来完成栈的功能。
23+
- `Set`:Set是一种不包含重复元素的Collection,Set最多只有一个null元素。
24+
- `HashSet`:线程不同步,内部使用`HashMap`进行数据存储,提供的方法基本都是调用`HashMap`的方法,所以两者本质是一样的。**集合元素可以为**`NULL`
25+
- `NavigableSet`:添加了搜索功能,可以对给定元素进行搜索:小于、小于等于、大于、大于等于,放回一个符合条件的最接近给定元素的 key。
26+
- `TreeSet`:线程不同步,内部使用`NavigableMap`操作。默认元素“自然顺序”排列,可以通过`Comparator`改变排序。
27+
- `EnumSet`:线程不同步。内部使用Enum数组实现,速度比`HashSet`快。**只能存储在构造函数传入的枚举类的枚举值**
28+
29+
30+
31+
Map
32+
33+
![]()
34+
35+
- `HashMap`:线程不同步。根据`key``hashcode`进行存储,内部使用静态内部类`Node`的数组进行存储,默认初始大小为16,每次扩大一倍。当发生Hash冲突时,采用拉链法(链表)。**可以接受为null的键值\(key\)和值\(value\)**。JDK 1.8中:当单个桶中元素个数大于等于8时,链表实现改为红黑树实现;当元素个数小于6时,变回链表实现。由此来防止hashCode攻击。
36+
- `LinkedHashMap`**保存了记录的插入顺序**,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的. 也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
37+
- `TreeMap`:线程不同步,基于 **红黑树** (Red-Black tree)的NavigableMap 实现,**能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。**
38+
- `HashTable`:线程安全,HashMap的迭代器\(Iterator\)`fail-fast`迭代器。**HashTable不能存储NULL的key和value。**
39+
40+
41+
42+
工具类
43+
44+
- `Collections``Arrays`:集合类的一个工具类\/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
45+
46+
- `Comparable``Comparator`:一般是用于对象的比较来实现排序,两者略有区别。
47+
48+
> - 类设计者没有考虑到比较问题而没有实现Comparable接口。这是我们就可以通过使用Comparator,这种情况下,我们是不需要改变对象的。
49+
> - 一个集合中,我们可能需要有多重的排序标准,这时候如果使用Comparable就有些捉襟见肘了,可以自己继承Comparator提供多种标准的比较器进行排序。
50+
51+
52+
53+
54+
55+
​ 深入理解JCF: [CarpenterLee/JCFInternals:深入理解Java集合框架](https://github.com/CarpenterLee/JCFInternals)
56+
57+
- 具体内容安排如下:
58+
- [Overview](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/1-Overview.md) 对Java Collections Framework,以及Java语言特性做出基本介绍。
59+
- [ArrayList](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/2-ArrayList.md) 结合源码对*ArrayList*进行讲解。
60+
- [LinkedList](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/3-LinkedList.md) 结合源码对*LinkedList*进行讲解。
61+
- [Stack and Queue](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/4-Stack%20and%20Queue.md)*AarryDeque*为例讲解*Stack**Queue*
62+
- [TreeSet and TreeMap](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/5-TreeSet%20and%20TreeMap.md) 结合源码对*TreeSet**TreeMap*进行讲解。
63+
- [HashSet and HashMap](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/6-HashSet%20and%20HashMap.md) 结合源码对*HashSet**HashMap*进行讲解。
64+
- [LinkedHashSet and LinkedHashMap](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/7-LinkedHashSet%20and%20LinkedHashMap.md) 结合源码对*LinkedHashSet**LinkedHashMap*进行讲解。
65+
- [PriorityQueue](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/8-PriorityQueue.md) 结合源码对*PriorityQueue*进行讲解。
66+
- [WeakHashMap](https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/9-WeakHashMap.md)*WeakHashMap*做出基本介绍。
67+
68+
69+
70+
##### 5.Hash Map和Hash Table的区别,Hash Map中的key可以是任何对象或数据类型吗?HashTable是线程安全的么?
71+
72+
- Hash Map和Hash Table的区别
73+
74+
- Hashtable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。
75+
- Hashtable不允许 null 值(key 和 value 都不可以),HashMap允许 null 值(key和value都可以)。
76+
- 两者的遍历方式大同小异,Hashtable仅仅比HashMap多一个elements方法。
77+
78+
Hashtable 和 HashMap 都能通过values()方法返回一个 Collection ,然后进行遍历处理。
79+
80+
两者也都可以通过 entrySet() 方法返回一个 Set , 然后进行遍历处理。
81+
82+
- HashTable使用Enumeration,HashMap使用Iterator。
83+
- 哈希值的使用不同,Hashtable直接使用对象的hashCode。而HashMap重新计算hash值,而且用于代替求模。
84+
- Hashtable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
85+
- HashTable基于Dictionary类,而HashMap基于AbstractMap类
86+
87+
- Hash Map中的key可以是任何对象或数据类型吗
88+
89+
- 可以为null,但不能是可变对象,如果是可变对象的话,对象中的属性改变,则对象HashCode也进行相应的改变,导致下次无法查找到已存在Map中的数据。
90+
- 如果可变对象在HashMap中被用作键,那就要小心在改变对象状态的时候,不要改变它的哈希值了。我们只需要保证成员变量的改变能保证该对象的哈希值不变即可。
91+
92+
- HashTable是线程安全的么
93+
94+
- HashTable是线程安全的,其实现是在对应的方法上添加了synchronized关键字进行修饰,由于在执行此方法的时候需要获得对象锁,则执行起来比较慢。所以现在如果为了保证线程安全的话,使用CurrentHashMap。
95+
96+
97+
98+
##### 6. HashMap和Concurrent HashMap区别, Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全?
99+
100+
- HashMap和Concurrent HashMap区别?
101+
- HashMap是非线程安全的,CurrentHashMap是线程安全的。
102+
- ConcurrentHashMap将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁。
103+
- ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。
104+
- Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全?
105+
- HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
106+
- get操作的高效之处在于整个get过程不需要加锁,除非读到的值是空的才会加锁重读。get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。
107+
- Put方法首先定位到Segment,然后在Segment里进行插入操作。插入操作需要经历两个步骤,第一步判断是否需要对Segment里的HashEntry数组进行扩容,第二步定位添加元素的位置然后放在HashEntry数组里。
108+
109+
##### 7. 因为别人知道源码怎么实现的,故意构造相同的hash的字符串进行攻击,怎么处理?那jdk7怎么办?
110+
111+
- 怎么处理构造相同hash的字符串进行攻击?
112+
113+
- 当客户端提交一个请求并附带参数的时候,web应用服务器会把我们的参数转化成一个HashMap存储,这个HashMap的逻辑结构如下:key1-->value1;
114+
- 但是物理存储结构是不同的,key值会被转化成Hashcode,这个hashcode有会被转成数组的下标:0-->value1;
115+
- 不同的string就会产生相同hashcode而导致碰撞,碰撞后的物理存储结构可能如下:0-->value1-->value2;
116+
- 1、限制post和get的参数个数,越少越好
117+
118+
2、限制post数据包的大小
119+
120+
3、WAF
121+
122+
- Jdk7 如何处理hashcode字符串攻击
123+
124+
- HashMap会动态的使用一个专门的treemap实现来替换掉它。
125+
126+
127+
128+
129+
130+
##### 7.ArrayList和LinkedList是常用的两种存储结构,有哪些区别呢?
131+
132+
- 1、ArrayList和LinkedList可想从名字分析,它们一个是Array(动态数组)的数据结构,一个是Link(链表)的数据结构,此外,它们两个都是对List接口的实现。前者是数组队列,相当于动态数组;后者为双向链表结构,也可当作堆栈、队列、双端队列
133+
- 2、当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
134+
- 3、当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。
135+
- 4、从利用效率来看,ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。
136+
- 5、ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。
137+
138+
139+
140+
141+
142+
143+

0 commit comments

Comments
 (0)