Skip to content

Commit fcb1049

Browse files
committed
update
1 parent cb394f6 commit fcb1049

39 files changed

+1380
-978
lines changed

java/0-JavaSE/c-集合类/4-CopyOnWrite集合.md

+445
Large diffs are not rendered by default.

java/0-JavaSE/c-集合类/5-集合的遍历.md

+227-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,241 @@
1-
## . Set集合遍历
1+
## 一.Set集合遍历
22

3+
### 1.迭代器遍历
34

5+
```java
6+
// 1. 迭代器遍历
7+
public static void getSet1(Set<String> set) {
8+
Iterator<String> iterator = set.iterator();
9+
while (iterator.hasNext()) {
10+
String value = iterator.next();
11+
System.out.print(value + " ");
12+
}
13+
}
14+
```
415

5-
## 2. Map集合遍历
16+
### 2.增强for
617

7-
**【方式一】通过map.keySet()获取key,通过key找到value**
18+
```java
19+
// 2. for-each
20+
public static void getSet2(Set<String> set) {
21+
for (String s : set) {
22+
System.out.print(s + " ");
23+
}
24+
}
25+
```
826

9-
![](5-集合的遍历.assets/20200525110552.png)
27+
### 3. Collection中的toArray()方法遍历
1028

11-
**【方式二】通过Map.Entry(String,String)获取,然后使用entry.getKey()获取到键,通过entry.getValue()获取到值**
29+
```java
30+
// 3. 使用Collection中的toArray()方法遍历
31+
public static void getSet3(Set<String> set) {
32+
Object[] objs = set.toArray();
33+
for (int i = 0; i < objs.length; i++) {
34+
System.out.print(objs[i] + " ");
35+
}
36+
}
37+
```
1238

13-
![](5-集合的遍历.assets/20200525111456.png)
39+
### 4.Lambda表达式
1440

15-
**【方式三】先放入Set集合中,Iterator遍历获取**
41+
同理相同的代码可以遍历List集合
1642

17-
![](5-集合的遍历.assets/20200525111943.png)
43+
**遍历Set集合**
1844

19-
**【方式四】只遍历键或者值,通过加强for循环**
45+
```java
46+
// 4.使用Collection中的toArray(T[] t)方法遍历
47+
public static void getSet4(Set<String> set) {
48+
set.forEach(n -> System.out.println(n));
49+
set.forEach(System.out::println);
50+
}
51+
```
2052

21-
![](5-集合的遍历.assets/20200525112035.png)
53+
**遍历List集合**
54+
55+
```java
56+
list.forEach(n -> System.out.println(n));
57+
58+
System.out.println("=====4.使用lambda表达式遍历List集合=====");
59+
60+
list.forEach(System.out::println);
61+
```
62+
63+
## 二.Map集合遍历
64+
65+
![在这里插入图片描述](https://iqqcode-blog.oss-cn-beijing.aliyuncs.com/imgs02/20200926130339543.png)
66+
67+
🔉Map集合是我们几乎每天都要使用的集合类,但是其无法像数组那样直接遍历,而是通过迭代器来遍历。以下列举五种遍历方式,推荐使用第一种。
68+
69+
### 1. EntrySet
70+
entrySet是 `key-value` 的集合,Set里面的类型是Map.Entry,就是存放Map中的某一对key-value,一般可以通过map.entrySet()得到。
71+
72+
- entrySet实现了Set接口,里面存放的是键值对。一个K对应一个V。
73+
74+
- 即通过`getKey()`得到K,`getValue()`得到V
75+
76+
**for-each 和 迭代器两种遍历**
77+
78+
```java
79+
/**
80+
* 【EntrySet】
81+
* 通过Map.Entry(String,String)来映射结果集
82+
* - 然后使用entry.getKey()获取到键
83+
* - 通过entry.getValue()获取到值
84+
*/
85+
86+
@Test
87+
public void test1() {
88+
Map<String, String> map = new HashMap<>();
89+
map.put("张三", "内蒙古");
90+
map.put("李四", "北京");
91+
map.put("王五", "上海");
92+
map.put("赵六", "杭州");
93+
map.put("田七", "南京");
94+
95+
//增强for遍历
96+
//entry.getKey()获取到键,通过entry.getValue()获取到值
97+
for (Map.Entry<String, String> entry : map.entrySet()) {
98+
System.out.println("key:" + entry.getKey() + " value:" + entry.getValue());
99+
}
100+
101+
System.out.println("========================分割线==============================");
102+
103+
//迭代器遍历
104+
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
105+
while (it.hasNext()) {
106+
Map.Entry<String, String> entry = it.next();
107+
System.out.println("键key :" + entry.getKey() + " value :" + entry.getValue());
108+
}
109+
}
110+
```
111+
112+
<br>
113+
114+
### 2. keySet获取key结果集
115+
通过`map.keySet()`获取key的结果集,Set里面的类型即key的类型
116+
- 通过key找到value
117+
118+
**for-each 和 迭代器两种遍历**
119+
120+
```java
121+
/**
122+
* 【KeySet】: 将HashMap中的key取出放入到Set集合中,根据key映射value
123+
* - 通过map.keySet()获取key
124+
* - 通过key找到value
125+
*/
126+
127+
@Test
128+
public void test2() {
129+
Map<String, String> map = new HashMap<>();
130+
map.put("张三", "内蒙古");
131+
map.put("李四", "北京");
132+
map.put("王五", "上海");
133+
map.put("赵六", "杭州");
134+
map.put("田七", "南京");
135+
136+
//通过map.keySet()获取key, 通过key找到value
137+
for (String key : map.keySet()) {
138+
String value = map.get(key);
139+
System.out.println("key:" + key + " value:" + value);
140+
}
141+
142+
System.out.println("========================分割线==============================");
143+
144+
Iterator<String> iterator = map.keySet().iterator();
145+
while (iterator.hasNext()) {
146+
String key = iterator.next();
147+
System.out.println(key);
148+
System.out.println(map.get(key));
149+
}
150+
}
151+
```
152+
153+
### 3. Lambda-forEach
154+
通过`Map.Entry(String,String)`来映射结果集,然后使用`entry.getKey()`获取到键,通过entry.getValue()获取到值
155+
156+
```java
157+
/**
158+
* 【Lambda】
159+
* JDLK8 后Map默认的迭代
160+
*/
161+
162+
@Test
163+
public void test3() {
164+
Map<String, String> map = new HashMap<>();
165+
map.put("张三", "内蒙古");
166+
map.put("李四", "北京");
167+
map.put("王五", "上海");
168+
map.put("赵六", "杭州");
169+
map.put("田七", "南京");
170+
// key-value的类型省略
171+
map.forEach((key, value) -> {
172+
System.out.println("key:" + key + " value:" + value);
173+
});
174+
}
175+
```
176+
<br>
177+
178+
### 4. Stream-forEach
179+
```java
180+
/**
181+
* 【Streams API 单线程】
182+
*/
183+
184+
@Test
185+
public void test4() {
186+
Map<String, String> map = new HashMap<>();
187+
map.put("张三", "内蒙古");
188+
map.put("李四", "北京");
189+
map.put("王五", "上海");
190+
map.put("赵六", "杭州");
191+
map.put("田七", "南京");
192+
map.put("贾七", "南京");
193+
// 遍历
194+
map.entrySet().stream().forEach((entry) -> {
195+
System.out.println(entry.getKey());
196+
System.out.println(entry.getValue());
197+
});
198+
}
199+
```
200+
201+
202+
<br>
203+
204+
### 5. key和value分开遍历
205+
206+
Set集合分别获取key与value -- **key不能重复, key-value顺序不对应**
207+
- 遍历map的键
208+
- 获取map的值的集合 [map.values ->返回 Collections]
209+
```java
210+
/**
211+
* 【Set集合分别获取key与value -- key不能重复, key-value顺序不对应】
212+
* - 遍历map的键[]
213+
* - 遍历map的值
214+
*/
215+
216+
@Test
217+
public void test5() {
218+
Map<String, String> map = new HashMap<>();
219+
map.put("张三", "内蒙古");
220+
map.put("李四", "北京");
221+
map.put("王五", "上海");
222+
map.put("赵六", "杭州");
223+
map.put("田七", "南京");
224+
map.put("郑八", "南京");
225+
226+
//第三种只遍历键或者值,通过加强for循环
227+
//遍历map的键
228+
for (String key : map.keySet()) {
229+
System.out.println("key: " + key);
230+
}
231+
232+
//获取到 map的value集合
233+
Collection<String> values = map.values();
234+
for (String value : map.values()) {
235+
System.out.println("value: " + value);
236+
}
237+
}
238+
```
22239

23240
----------------------------------------------------------------------------------
24241

@@ -47,5 +264,3 @@
47264
- put(key, 1)
48265

49266
5. 遍历Map集合,输出结果
50-
51-
![](5-集合的遍历.assets/20200525114532.png)

java/0-JavaSE/c-集合类/a-ArraayList.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ public class SafeArrayList {
2020

2121

2222

23-
24-
25-
26-
27-
23+
### 解决方法
2824

2925
**【方法一】我们先想到到是用Vector来替换ArrayList**
3026

java/0-JavaSE/c-集合类/c-ConcurrentHashMap对比.md

+14-6
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
5和3添加的位置不同,但是由于是重量级锁,所以5无法获取锁,只能等待
1414

15-
- HashTable不允许`key``value`为null
16-
- ConcurrentHashMap不允许`key``value`为null
15+
- HashTable **不允许** `key``value`为null
16+
- ConcurrentHashMap **不允许** `key``value`为null
1717
- **HashTable是线程安全的**
1818

1919
<br>
@@ -26,17 +26,23 @@
2626

2727

2828

29-
## 2. Hashtable与ConcurrentHashMap对比
29+
## 2. Hashtable与HashMap对比
3030

31-
- **实现方式不同**:Hashtable 继承了 Dictionary类,而 HashMap 继承的是 AbstractMap 类。
31+
- **线程安全:**Hashtable线程安全
32+
33+
- **实现方式不同**:Hashtable 继承了 Dictionary类,而 HashMap 继承的是 AbstractMap 类。二者都实现了Map接口
3234

3335
- **初始化容量不同**:HashMap 的初始容量为:16,Hashtable 初始容量为:11,两者的负载因子默认都是:0.75。
3436

35-
- **扩容机制不同**:当现有容量大于总容量 * 负载因子时,HashMap 扩容规则为当前容量翻倍Hashtable 扩容规则为当前容量翻倍 + 1。
37+
- **扩容机制不同**:当现有容量大于总容量 * 负载因子时,HashMap 扩容规则为当前容量翻倍Hashtable 扩容规则为`2N + 1`
3638

3739
- **迭代器不同**:HashMap 中的 Iterator 迭代器是 **fail-fast** 的,而 Hashtable 的 Enumerator 不是 fail-fast 的。
3840

3941
所以,当其他线程改变了HashMap 的结构,如:增加、删除元素,将会抛出`ConcurrentModificationException` 异常,而 Hashtable 则不会。
42+
43+
- **key和value是否允许null值:** Hashtable不予许为`null-null`;HashMap只允许有一个
44+
45+
> 当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用**containsKey()**方法来判断
4046
4147
<br>
4248

@@ -135,6 +141,8 @@ ConcurrentHashMap定位一个元素的过程需要进行**两次Hash**操作
135141

136142
ConcurrentHashMap 的 get 方法是非常高效的,**因为整个过程都不需要加锁**
137143

144+
145+
138146
如果容量大小是16,他的并发度就是16,可以同时允许16个线程操作16个Segment而且还是线程安全的
139147

140148
所以,通过这一种结构,ConcurrentHashMap的并发能力可以大大的提高。
@@ -211,7 +219,7 @@ class Node<K,V> implements Map.Entry<K,V> {
211219

212220
JDK-7版本的**ReentrantLock + Segment + HashEntry**
213221

214-
JDK-8版本中**synchronized + CAS + HashEntry + 红黑树**
222+
JDK-8版本中**synchronized + CAS + Node + 红黑树**
215223

216224
**1. 数据结构**:取消了Segment分段锁的数据结构,取而代之的是数组+链表+红黑树的结构。
217225

0 commit comments

Comments
 (0)