Skip to content

Commit 3774c15

Browse files
committed
auto commit
1 parent 0012f2a commit 3774c15

File tree

7 files changed

+42
-84
lines changed

7 files changed

+42
-84
lines changed

docs/notes/Java 容器.md

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public class ArrayList<E> extends AbstractList<E>
126126
private static final int DEFAULT_CAPACITY = 10;
127127
```
128128

129-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/52a7744f-5bce-4ff3-a6f0-8449334d9f3d.png" width="400px"> </div><br>
129+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208232221265.png"/> </div><br>
130130

131131
### 2. 扩容
132132

@@ -170,7 +170,7 @@ private void grow(int minCapacity) {
170170

171171
### 3. 删除元素
172172

173-
需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看出 ArrayList 删除元素的代价是非常高的。
173+
需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看到 ArrayList 删除元素的代价是非常高的。
174174

175175
```java
176176
public E remove(int index) {
@@ -185,34 +185,7 @@ public E remove(int index) {
185185
}
186186
```
187187

188-
### 4. Fail-Fast
189-
190-
modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。
191-
192-
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。
193-
194-
```java
195-
private void writeObject(java.io.ObjectOutputStream s)
196-
throws java.io.IOException{
197-
// Write out element count, and any hidden stuff
198-
int expectedModCount = modCount;
199-
s.defaultWriteObject();
200-
201-
// Write out size as capacity for behavioural compatibility with clone()
202-
s.writeInt(size);
203-
204-
// Write out all elements in the proper order.
205-
for (int i=0; i<size; i++) {
206-
s.writeObject(elementData[i]);
207-
}
208-
209-
if (modCount != expectedModCount) {
210-
throw new ConcurrentModificationException();
211-
}
212-
}
213-
```
214-
215-
### 5. 序列化
188+
### 4. 序列化
216189

217190
ArrayList 基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。
218191

@@ -277,6 +250,13 @@ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
277250
oos.writeObject(list);
278251
```
279252

253+
### 5. Fail-Fast
254+
255+
modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。
256+
257+
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。代码参考上节序列化中的 writeObject() 方法。
258+
259+
280260
## Vector
281261

282262
### 1. 同步
@@ -362,7 +342,7 @@ List<String> list = new CopyOnWriteArrayList<>();
362342

363343
## CopyOnWriteArrayList
364344

365-
### 读写分离
345+
### 1. 读写分离
366346

367347
写操作在一个复制的数组上进行,读操作还是在原始数组中进行,读写分离,互不影响。
368348

@@ -398,7 +378,7 @@ private E get(Object[] a, int index) {
398378
}
399379
```
400380

401-
### 适用场景
381+
### 2. 适用场景
402382

403383
CopyOnWriteArrayList 在写操作的同时允许读操作,大大提高了读操作的性能,因此很适合读多写少的应用场景。
404384

@@ -430,30 +410,29 @@ transient Node<E> first;
430410
transient Node<E> last;
431411
```
432412

433-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c8563120-cb00-4dd6-9213-9d9b337a7f7c.png" width="500px"> </div><br>
413+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208233940066.png"/> </div><br>
434414

435415
### 2. 与 ArrayList 的比较
436416

437-
- ArrayList 基于动态数组实现,LinkedList 基于双向链表实现;
438-
- ArrayList 支持随机访问,LinkedList 不支持;
439-
- LinkedList 在任意位置添加删除元素更快。
417+
ArrayList 基于动态数组实现,LinkedList 基于双向链表实现。ArrayList 和 LinkedList 的区别可以归结为数组和链表的区别:
418+
419+
- 数组支持随机访问,但插入删除的代价很高,需要移动大量元素;
420+
- 链表不支持随机访问,但插入删除只需要改变指针。
440421

441422
## HashMap
442423

443424
为了便于理解,以下源码分析以 JDK 1.7 为主。
444425

445426
### 1. 存储结构
446427

447-
内部包含了一个 Entry 类型的数组 table。
428+
内部包含了一个 Entry 类型的数组 table。Entry 存储着键值对。它包含了四个字段,从 next 字段我们可以看出 Entry 是一个链表。即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使用拉链法来解决冲突,同一个链表中存放哈希值和散列桶取模运算结果相同的 Entry。
429+
430+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208234948205.png"/> </div><br>
448431

449432
```java
450433
transient Entry[] table;
451434
```
452435

453-
Entry 存储着键值对。它包含了四个字段,从 next 字段我们可以看出 Entry 是一个链表。即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使用拉链法来解决冲突,同一个链表中存放哈希值和散列桶取模运算结果相同的 Entry。
454-
455-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9420a703-1f9d-42ce-808e-bcb82b56483d.png" width="550px"> </div><br>
456-
457436
```java
458437
static class Entry<K,V> implements Map.Entry<K,V> {
459438
final K key;
@@ -528,7 +507,7 @@ map.put("K3", "V3");
528507
- 计算键值对所在的桶;
529508
- 在链表上顺序查找,时间复杂度显然和链表的长度成正比。
530509

531-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e0870f80-b79e-4542-ae39-7420d4b0d8fe.png" width="550px"> </div><br>
510+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208235258643.png"/> </div><br>
532511

533512
### 3. put 操作
534513

notes/Java 容器.md

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public class ArrayList<E> extends AbstractList<E>
126126
private static final int DEFAULT_CAPACITY = 10;
127127
```
128128

129-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/52a7744f-5bce-4ff3-a6f0-8449334d9f3d.png" width="400px"> </div><br>
129+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208232221265.png"/> </div><br>
130130

131131
### 2. 扩容
132132

@@ -170,7 +170,7 @@ private void grow(int minCapacity) {
170170

171171
### 3. 删除元素
172172

173-
需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看出 ArrayList 删除元素的代价是非常高的。
173+
需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看到 ArrayList 删除元素的代价是非常高的。
174174

175175
```java
176176
public E remove(int index) {
@@ -185,34 +185,7 @@ public E remove(int index) {
185185
}
186186
```
187187

188-
### 4. Fail-Fast
189-
190-
modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。
191-
192-
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。
193-
194-
```java
195-
private void writeObject(java.io.ObjectOutputStream s)
196-
throws java.io.IOException{
197-
// Write out element count, and any hidden stuff
198-
int expectedModCount = modCount;
199-
s.defaultWriteObject();
200-
201-
// Write out size as capacity for behavioural compatibility with clone()
202-
s.writeInt(size);
203-
204-
// Write out all elements in the proper order.
205-
for (int i=0; i<size; i++) {
206-
s.writeObject(elementData[i]);
207-
}
208-
209-
if (modCount != expectedModCount) {
210-
throw new ConcurrentModificationException();
211-
}
212-
}
213-
```
214-
215-
### 5. 序列化
188+
### 4. 序列化
216189

217190
ArrayList 基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。
218191

@@ -277,6 +250,13 @@ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
277250
oos.writeObject(list);
278251
```
279252

253+
### 5. Fail-Fast
254+
255+
modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。
256+
257+
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。代码参考上节序列化中的 writeObject() 方法。
258+
259+
280260
## Vector
281261

282262
### 1. 同步
@@ -362,7 +342,7 @@ List<String> list = new CopyOnWriteArrayList<>();
362342

363343
## CopyOnWriteArrayList
364344

365-
### 读写分离
345+
### 1. 读写分离
366346

367347
写操作在一个复制的数组上进行,读操作还是在原始数组中进行,读写分离,互不影响。
368348

@@ -398,7 +378,7 @@ private E get(Object[] a, int index) {
398378
}
399379
```
400380

401-
### 适用场景
381+
### 2. 适用场景
402382

403383
CopyOnWriteArrayList 在写操作的同时允许读操作,大大提高了读操作的性能,因此很适合读多写少的应用场景。
404384

@@ -430,30 +410,29 @@ transient Node<E> first;
430410
transient Node<E> last;
431411
```
432412

433-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/c8563120-cb00-4dd6-9213-9d9b337a7f7c.png" width="500px"> </div><br>
413+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208233940066.png"/> </div><br>
434414

435415
### 2. 与 ArrayList 的比较
436416

437-
- ArrayList 基于动态数组实现,LinkedList 基于双向链表实现;
438-
- ArrayList 支持随机访问,LinkedList 不支持;
439-
- LinkedList 在任意位置添加删除元素更快。
417+
ArrayList 基于动态数组实现,LinkedList 基于双向链表实现。ArrayList 和 LinkedList 的区别可以归结为数组和链表的区别:
418+
419+
- 数组支持随机访问,但插入删除的代价很高,需要移动大量元素;
420+
- 链表不支持随机访问,但插入删除只需要改变指针。
440421

441422
## HashMap
442423

443424
为了便于理解,以下源码分析以 JDK 1.7 为主。
444425

445426
### 1. 存储结构
446427

447-
内部包含了一个 Entry 类型的数组 table。
428+
内部包含了一个 Entry 类型的数组 table。Entry 存储着键值对。它包含了四个字段,从 next 字段我们可以看出 Entry 是一个链表。即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使用拉链法来解决冲突,同一个链表中存放哈希值和散列桶取模运算结果相同的 Entry。
429+
430+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208234948205.png"/> </div><br>
448431

449432
```java
450433
transient Entry[] table;
451434
```
452435

453-
Entry 存储着键值对。它包含了四个字段,从 next 字段我们可以看出 Entry 是一个链表。即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使用拉链法来解决冲突,同一个链表中存放哈希值和散列桶取模运算结果相同的 Entry。
454-
455-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9420a703-1f9d-42ce-808e-bcb82b56483d.png" width="550px"> </div><br>
456-
457436
```java
458437
static class Entry<K,V> implements Map.Entry<K,V> {
459438
final K key;
@@ -528,7 +507,7 @@ map.put("K3", "V3");
528507
- 计算键值对所在的桶;
529508
- 在链表上顺序查找,时间复杂度显然和链表的长度成正比。
530509

531-
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e0870f80-b79e-4542-ae39-7420d4b0d8fe.png" width="550px"> </div><br>
510+
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191208235258643.png"/> </div><br>
532511

533512
### 3. put 操作
534513

27.4 KB
Loading
32.3 KB
Loading
61.2 KB
Loading
61.9 KB
Loading
77.6 KB
Loading

0 commit comments

Comments
 (0)