更新
This commit is contained in:
		
							
								
								
									
										637
									
								
								java/Guava中的类型增强.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										637
									
								
								java/Guava中的类型增强.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,637 @@
 | 
				
			|||||||
 | 
					# Guava中的类型增强 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Map - Table、BiMap、Multimap、RangeMap、ClassToInstanceMap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 1. 简介[#](https://www.cnblogs.com/cao-lei/p/17806222.html#3979976375)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  日常开发中使用Map时经常会遇到很多复杂的处理场景,例如:多个键的Map、不仅可以根据键获取值也可以根据值获取键且不用遍历、重复键的Map、数字等范围内映射相同的值、内存中缓存对象等,Guava提供了以上场景的解决方案。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| 场景                                             | 解决方案           | 具体实现                                                     |
 | 
				
			||||||
 | 
					| ------------------------------------------------ | ------------------ | ------------------------------------------------------------ |
 | 
				
			||||||
 | 
					| 多个键的Map                                      | Table              | HashBasedTable、TreeBasedTable、ImmutableTable               |
 | 
				
			||||||
 | 
					| 不仅可以根据键获取值也可以根据值获取键且不用遍历 | BiMap              | HashBiMap、ImmutableBiMap                                    |
 | 
				
			||||||
 | 
					| 重复键的Map                                      | Multimap           | ArrayListMultimap、LinkedListMultimap、LinkedHashMultimap、ImmutableListMultimap、ImmutableSetMultimap |
 | 
				
			||||||
 | 
					| 数字等范围内映射相同的值                         | RangeMap           | TreeRangeMap、ImmutableRangeMap                              |
 | 
				
			||||||
 | 
					| 内存中缓存对象                                   | ClassToInstanceMap | MutableClassToInstanceMap、ImmutableClassToInstanceMap       |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  本博客将详细描述具体的示例代码。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 2. 添加依赖[#](https://www.cnblogs.com/cao-lei/p/17806222.html#1443701749)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Maven项目pom.xml中添加依赖:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```xml
 | 
				
			||||||
 | 
					Copy<dependency>
 | 
				
			||||||
 | 
					    <groupId>com.google.guava</groupId>
 | 
				
			||||||
 | 
					    <artifactId>guava</artifactId>
 | 
				
			||||||
 | 
					    <version>32.0.0-jre</version>
 | 
				
			||||||
 | 
					</dependency>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 3. Tbale - 表结构数据[#](https://www.cnblogs.com/cao-lei/p/17806222.html#848306248)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  官方注释翻译:将一对有序键(称为行键和列键)与单个值相关联的集合。
 | 
				
			||||||
 | 
					  示例代码(需求: 记录各个公司每个部门的人数):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```swift
 | 
				
			||||||
 | 
					Copy// HashMap
 | 
				
			||||||
 | 
					Map<String, Integer> deptMap = new HashMap<>();
 | 
				
			||||||
 | 
					deptMap.put("A部门", 10);
 | 
				
			||||||
 | 
					deptMap.put("B部门", 20);
 | 
				
			||||||
 | 
					Map<String, Map<String, Integer>> companyMap = new HashMap<>();
 | 
				
			||||||
 | 
					companyMap.put("xx公司", deptMap);
 | 
				
			||||||
 | 
					// HashMap 获取值
 | 
				
			||||||
 | 
					Integer val = companyMap.get("xx公司").get("A部门");
 | 
				
			||||||
 | 
					System.out.println("HashMap 获取值: " + val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建Hash类型Table, 基于Hash表实现
 | 
				
			||||||
 | 
					// Table<R, C, V>中三个泛型: R-行, C-列, V-值
 | 
				
			||||||
 | 
					Table<String, String, Integer> hashTable = HashBasedTable.create();
 | 
				
			||||||
 | 
					hashTable.put("xx公司", "A部门", 10);
 | 
				
			||||||
 | 
					hashTable.put("xx公司", "B部门", 20);
 | 
				
			||||||
 | 
					hashTable.put("xx公司", "C部门", 30);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nHash Table: " + hashTable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建Tree类型Table, 基于红黑树实现
 | 
				
			||||||
 | 
					Table<String, String, Integer> treeTable = TreeBasedTable.create();
 | 
				
			||||||
 | 
					treeTable.put("xx公司", "C部门", 30);
 | 
				
			||||||
 | 
					treeTable.put("xx公司", "B部门", 20);
 | 
				
			||||||
 | 
					treeTable.put("xx公司", "A部门", 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nTree Table: " + treeTable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建不可变Table, 无法新增、更新或删除
 | 
				
			||||||
 | 
					Table<String, String, Integer> immutableTable = ImmutableTable.<String, String, Integer>builder()
 | 
				
			||||||
 | 
					        .put("xx公司", "C部门", 30)
 | 
				
			||||||
 | 
					        .put("xx公司", "B部门", 20)
 | 
				
			||||||
 | 
					        .put("xx公司", "A部门", 10)
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nImmutable Table: " + immutableTable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Table 获取值
 | 
				
			||||||
 | 
					Integer val2 = hashTable.get("xx公司", "A部门");
 | 
				
			||||||
 | 
					System.out.println("\nTable 获取值: " + val2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Table 删除值
 | 
				
			||||||
 | 
					Integer remove = hashTable.remove("xx公司", "C部门");
 | 
				
			||||||
 | 
					System.out.println("\nTable 删除值: " + remove);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据行获取列和值映射
 | 
				
			||||||
 | 
					Map<String, Integer> columnvalueMap = hashTable.row("xx公司");
 | 
				
			||||||
 | 
					System.out.println("\nTable 列和值 映射: " + columnvalueMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据列获取行和值映射
 | 
				
			||||||
 | 
					Map<String, Integer> rowvalueMap = hashTable.column("A部门");
 | 
				
			||||||
 | 
					System.out.println("\nTable 行和值 映射: " + rowvalueMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取key集合
 | 
				
			||||||
 | 
					Set<String> rowKeySet = hashTable.rowKeySet();
 | 
				
			||||||
 | 
					System.out.println("\nTable Row key 集合: " + rowKeySet);
 | 
				
			||||||
 | 
					Set<String> columnKeySet = hashTable.columnKeySet();
 | 
				
			||||||
 | 
					System.out.println("\nTable Column key 集合: " + columnKeySet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取值集合
 | 
				
			||||||
 | 
					Collection<Integer> values = hashTable.values();
 | 
				
			||||||
 | 
					System.out.println("\nTable 值集合: " + values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 判断包含行
 | 
				
			||||||
 | 
					boolean containsRow = hashTable.containsRow("xx公司");
 | 
				
			||||||
 | 
					System.out.println("\nTable 包含行: " + containsRow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 判断包含列
 | 
				
			||||||
 | 
					boolean containsColumn = hashTable.containsColumn("A部门");
 | 
				
			||||||
 | 
					System.out.println("\nTable 包含列: " + containsColumn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 判断包含行和列
 | 
				
			||||||
 | 
					boolean contains = hashTable.contains("xx公司", "A部门");
 | 
				
			||||||
 | 
					System.out.println("\nTable 包含行和列: " + contains);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 判断包含值
 | 
				
			||||||
 | 
					boolean containsValue = hashTable.containsValue(10);
 | 
				
			||||||
 | 
					System.out.println("\nTable 包含值: " + containsValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 行和列转置 - 行 转 列
 | 
				
			||||||
 | 
					Table<String, String, Integer> transposeTable = Tables.transpose(hashTable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取所有的行
 | 
				
			||||||
 | 
					Set<Table.Cell<String, String, Integer>> cells = transposeTable.cellSet();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 遍历输出
 | 
				
			||||||
 | 
					System.out.println("\n遍历输出开始----------------------------");
 | 
				
			||||||
 | 
					cells.forEach(cell -> System.out.println(cell.getRowKey() + ", " + cell.getColumnKey() + ", " + cell.getValue()));
 | 
				
			||||||
 | 
					System.out.println("\n遍历输出结束----------------------------");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 转换为嵌套的Map
 | 
				
			||||||
 | 
					Map<String, Map<String, Integer>> rowMap = hashTable.rowMap();
 | 
				
			||||||
 | 
					System.out.println("\nTable RowMap: " + rowMap);
 | 
				
			||||||
 | 
					Map<String, Map<String, Integer>> columnMap = hashTable.columnMap();
 | 
				
			||||||
 | 
					System.out.println("\nTable ColumnMap: " + columnMap);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  执行结果:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```yaml
 | 
				
			||||||
 | 
					CopyHashMap 获取值: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hash Table: {xx公司={A部门=10, B部门=20, C部门=30}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tree Table: {xx公司={A部门=10, B部门=20, C部门=30}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Immutable Table: {xx公司={C部门=30, B部门=20, A部门=10}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 获取值: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 删除值: 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 列和值 映射: {A部门=10, B部门=20}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 行和值 映射: {xx公司=10}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table Row key 集合: [xx公司]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table Column key 集合: [A部门, B部门]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 值集合: [10, 20]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 包含行: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 包含列: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 包含行和列: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table 包含值: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					遍历输出开始----------------------------
 | 
				
			||||||
 | 
					A部门, xx公司, 10
 | 
				
			||||||
 | 
					B部门, xx公司, 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					遍历输出结束----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table RowMap: {xx公司={A部门=10, B部门=20}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table ColumnMap: {A部门={xx公司=10}, B部门={xx公司=20}}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 4. BiMap - 双向映射Map[#](https://www.cnblogs.com/cao-lei/p/17806222.html#2347438548)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  官方注释翻译:双映射(或“双向映射”)是一种保留其值及其键的唯一性的映射。此约束使双映射能够支持“反向视图”,即另一个双映射,其中包含与此双映射相同的条目,但具有相反的键和值。
 | 
				
			||||||
 | 
					  示例代码(需求: 数组和英文翻译):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```csharp
 | 
				
			||||||
 | 
					Copy// 创建BiMap, 底层为两个Hash表的Map
 | 
				
			||||||
 | 
					BiMap<Integer, String> biMap = HashBiMap.create();
 | 
				
			||||||
 | 
					biMap.put(1, "one");
 | 
				
			||||||
 | 
					biMap.put(2, "two");
 | 
				
			||||||
 | 
					biMap.put(3, "three");
 | 
				
			||||||
 | 
					biMap.put(4, "four");
 | 
				
			||||||
 | 
					biMap.put(5, "five");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("BiMap: " + biMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建不可变BiMap, 无法新增、更新或删除
 | 
				
			||||||
 | 
					BiMap<Object, Object> immutableBiMap = ImmutableBiMap.builder()
 | 
				
			||||||
 | 
					        .put(1, "one")
 | 
				
			||||||
 | 
					        .put(2, "two")
 | 
				
			||||||
 | 
					        .put(3, "three")
 | 
				
			||||||
 | 
					        .put(4, "four")
 | 
				
			||||||
 | 
					        .put(5, "five")
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nImmutable BiMap: " + immutableBiMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 通过key获取value
 | 
				
			||||||
 | 
					String value = biMap.get(1);
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 根据key获取value: " + value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Integer key = biMap.inverse().get("one");
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 根据value获取key: " + key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 翻转后修改
 | 
				
			||||||
 | 
					biMap.inverse().put("six", 6);
 | 
				
			||||||
 | 
					// 返回双映射的逆视图, 并没有创建新对象, 还是之前的对象, 所以操作翻转后的BiMap会影响之前的BiMap
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 被影响: " + biMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 底层是HashMap, key不可重复
 | 
				
			||||||
 | 
					// value不可重复
 | 
				
			||||||
 | 
					try {
 | 
				
			||||||
 | 
					    biMap.put(11, "one");
 | 
				
			||||||
 | 
					} catch (Exception e) {
 | 
				
			||||||
 | 
					    System.err.println("BiMap 替换value异常: " + e.getMessage());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 翻转后key不能重复
 | 
				
			||||||
 | 
					try {
 | 
				
			||||||
 | 
					    biMap.inverse().put("first", 1);
 | 
				
			||||||
 | 
					} catch (Exception e) {
 | 
				
			||||||
 | 
					    System.err.println("BiMap 替换key异常: " + e.getMessage());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// key和value可为null
 | 
				
			||||||
 | 
					biMap.put(null, null);
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 根据Null key获取Null value: " + biMap.get(null));
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 根据Null value获取Null key: " + biMap.inverse().get(null));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 强制替换key
 | 
				
			||||||
 | 
					biMap.forcePut(11, "one");
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 获取新key: " + biMap.inverse().get("one"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// values为Set集合
 | 
				
			||||||
 | 
					Set<String> values = biMap.values();
 | 
				
			||||||
 | 
					System.out.println("\nBiMap 不重复的value: " + values);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  执行结果:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```mipsasm
 | 
				
			||||||
 | 
					CopyBiMap: {1=one, 2=two, 3=three, 4=four, 5=five}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Immutable BiMap: {1=one, 2=two, 3=three, 4=four, 5=five}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 根据key获取value: one
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 根据value获取key: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 被影响: {1=one, 2=two, 3=three, 4=four, 5=five, 6=six}
 | 
				
			||||||
 | 
					BiMap 替换value异常: value already present: one
 | 
				
			||||||
 | 
					BiMap 替换key异常: key already present: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 根据Null key获取Null value: null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 根据Null value获取Null key: null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 获取新key: 11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BiMap 不重复的value: [two, three, four, five, six, null, one]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 5. Multimap - 多重映射Map[#](https://www.cnblogs.com/cao-lei/p/17806222.html#819077997)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  官方注释翻译将键映射到值的集合,类似于 Map,但其中每个键可能与 多个 值相关联。
 | 
				
			||||||
 | 
					  示例代码(需求: 学生和各科选修课成绩):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```swift
 | 
				
			||||||
 | 
					Copy// 创建Multimap, key为HashMap, value为ArrayList
 | 
				
			||||||
 | 
					Multimap<String, Integer> arrayListMultimap = ArrayListMultimap.create();
 | 
				
			||||||
 | 
					arrayListMultimap.put("张三", 90);
 | 
				
			||||||
 | 
					arrayListMultimap.put("张三", 80);
 | 
				
			||||||
 | 
					arrayListMultimap.put("张三", 100);
 | 
				
			||||||
 | 
					arrayListMultimap.put("李四", 88);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("Multimap key为HashMap, value为ArrayList: " + arrayListMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建Multimap, key为HashMap, value为HashSet
 | 
				
			||||||
 | 
					Multimap<String, Integer> hashMultimap = HashMultimap.create();
 | 
				
			||||||
 | 
					hashMultimap.put("张三", 90);
 | 
				
			||||||
 | 
					hashMultimap.put("张三", 80);
 | 
				
			||||||
 | 
					hashMultimap.put("张三", 100);
 | 
				
			||||||
 | 
					hashMultimap.put("李四", 88);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nMultimap key为HashMap, value为HashSet: " + hashMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建Multimap, key为LinkedHashMap, value为LinkedList
 | 
				
			||||||
 | 
					Multimap<String, Integer> linkedListMultimap = LinkedListMultimap.create();
 | 
				
			||||||
 | 
					linkedListMultimap.put("张三", 90);
 | 
				
			||||||
 | 
					linkedListMultimap.put("张三", 80);
 | 
				
			||||||
 | 
					linkedListMultimap.put("张三", 100);
 | 
				
			||||||
 | 
					linkedListMultimap.put("李四", 88);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nMultimap key为LinkedHashMap, value为LinkedList: " + linkedListMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建Multimap, key为LinkedHashMap, value为LinkedHashMap
 | 
				
			||||||
 | 
					Multimap<String, Integer> linkedHashMultimap = LinkedHashMultimap.create();
 | 
				
			||||||
 | 
					linkedHashMultimap.put("张三", 90);
 | 
				
			||||||
 | 
					linkedHashMultimap.put("张三", 80);
 | 
				
			||||||
 | 
					linkedHashMultimap.put("张三", 100);
 | 
				
			||||||
 | 
					linkedHashMultimap.put("李四", 88);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nMultimap key为LinkedHashMap, value为LinkedHashMap: " + linkedHashMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建Multimap, key为TreeMap, value为TreeSet
 | 
				
			||||||
 | 
					Multimap<String, Integer> treeMultimap = TreeMultimap.create();
 | 
				
			||||||
 | 
					treeMultimap.put("张三", 90);
 | 
				
			||||||
 | 
					treeMultimap.put("张三", 80);
 | 
				
			||||||
 | 
					treeMultimap.put("张三", 100);
 | 
				
			||||||
 | 
					treeMultimap.put("李四", 88);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nMultimap key为TreeMap, value为TreeSet: " + treeMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建不可变Multimap, 无法新增、更新或删除, key为ImmutableMap, value为ImmutableList
 | 
				
			||||||
 | 
					Multimap<String, Integer> immutableListMultimap = ImmutableListMultimap.<String, Integer>builder()
 | 
				
			||||||
 | 
					        .put("张三", 90)
 | 
				
			||||||
 | 
					        .put("张三", 80)
 | 
				
			||||||
 | 
					        .put("张三", 100)
 | 
				
			||||||
 | 
					        .put("李四", 88)
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nMultimap key为ImmutableMap, value为ImmutableList: " + immutableListMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建不可变Multimap, 无法新增、更新或删除, key为ImmutableMap, value为ImmutableSet
 | 
				
			||||||
 | 
					Multimap<String, Integer> immutableSetMultimap = ImmutableSetMultimap.<String, Integer>builder()
 | 
				
			||||||
 | 
					        .put("张三", 90)
 | 
				
			||||||
 | 
					        .put("张三", 80)
 | 
				
			||||||
 | 
					        .put("张三", 100)
 | 
				
			||||||
 | 
					        .put("李四", 88)
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("\nMultimap key为ImmutableMap, value为ImmutableSet: " + immutableSetMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取值
 | 
				
			||||||
 | 
					Collection<Integer> values = arrayListMultimap.get("张三");
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 获取值集合: " + values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取不存在key的值, 返回的是空集合, 而不是null
 | 
				
			||||||
 | 
					Collection<Integer> valuesByNotExistsKey = arrayListMultimap.get("王五");
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 获取不存在的Key值集合: " + valuesByNotExistsKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取值集合添加值
 | 
				
			||||||
 | 
					// 返回的是多重映射中关联的值的视图集合, 并没有创建新对象, 还是之前的对象, 所以操作值集合会影响之前的Multimap
 | 
				
			||||||
 | 
					values.add(60);
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 被影响: " + arrayListMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取大小
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 大小:" + arrayListMultimap.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 判断是否为空
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 是否为空: " + arrayListMultimap.isEmpty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 包含key
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 包含key: " + arrayListMultimap.containsKey("张三"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 包含value
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 包含value: " + arrayListMultimap.containsValue(60));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 包含key-value键值对
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 包含key-value对: " + arrayListMultimap.containsEntry("张三", 60));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 替换value
 | 
				
			||||||
 | 
					arrayListMultimap.replaceValues("张三", Arrays.asList(10, 20, 30));
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 替换value: " + arrayListMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据key-value删除
 | 
				
			||||||
 | 
					arrayListMultimap.remove("张三", 10);
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 根据key-value删除: " + arrayListMultimap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据key删除
 | 
				
			||||||
 | 
					Collection<Integer> removeAll = arrayListMultimap.removeAll("张三");
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 根据key删除: " + removeAll);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取key集合
 | 
				
			||||||
 | 
					Set<String> keySet = arrayListMultimap.keySet();
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 获取key集合(HashSet): " + keySet);
 | 
				
			||||||
 | 
					Multiset<String> keys = arrayListMultimap.keys();
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 获取key集合(MultiSet): " + keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取所有的key-value
 | 
				
			||||||
 | 
					Collection<Map.Entry<String, Integer>> entries = arrayListMultimap.entries();
 | 
				
			||||||
 | 
					System.out.println("\n遍历key-value开始--------------------------");
 | 
				
			||||||
 | 
					entries.forEach(entry -> System.out.println(entry.getKey() + " : " + entry.getValue()));
 | 
				
			||||||
 | 
					System.out.println("\n遍历key-value结束--------------------------");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 转换为Map<K, Collection<V>>
 | 
				
			||||||
 | 
					Map<String, Collection<Integer>> collectionMap = arrayListMultimap.asMap();
 | 
				
			||||||
 | 
					System.out.println("\nMultimap 转换为Map<K, Collection<V>>: " + collectionMap);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  执行结果:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```mipsasm
 | 
				
			||||||
 | 
					CopyMultimap key为HashMap, value为ArrayList: {李四=[88], 张三=[90, 80, 100]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap key为HashMap, value为HashSet: {李四=[88], 张三=[80, 100, 90]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap key为LinkedHashMap, value为LinkedList: {张三=[90, 80, 100], 李四=[88]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap key为LinkedHashMap, value为LinkedHashMap: {张三=[90, 80, 100], 李四=[88]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap key为TreeMap, value为TreeSet: {张三=[80, 90, 100], 李四=[88]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap key为ImmutableMap, value为ImmutableList: {张三=[90, 80, 100], 李四=[88]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap key为ImmutableMap, value为ImmutableSet: {张三=[90, 80, 100], 李四=[88]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 获取值集合: [90, 80, 100]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 获取不存在的Key值集合: []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 被影响: {李四=[88], 张三=[90, 80, 100, 60]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 大小:5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 是否为空: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 包含key: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 包含value: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 包含key-value对: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 替换value: {李四=[88], 张三=[10, 20, 30]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 根据key-value删除: {李四=[88], 张三=[20, 30]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 根据key删除: [20, 30]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 获取key集合(HashSet): [李四]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 获取key集合(MultiSet): [李四]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					遍历key-value开始--------------------------
 | 
				
			||||||
 | 
					李四 : 88
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					遍历key-value结束--------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multimap 转换为Map<K, Collection<V>>: {李四=[88]}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 6. RangeMap - 范围映射Map[#](https://www.cnblogs.com/cao-lei/p/17806222.html#684335507)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  官方注释翻译:从不相交的非空范围到非 null 值的映射。查询查找与包含指定键的范围(如果有)关联的值。
 | 
				
			||||||
 | 
					  示例代码(需求:考试成绩分类):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```swift
 | 
				
			||||||
 | 
					Copy// if-else
 | 
				
			||||||
 | 
					int score = 88;
 | 
				
			||||||
 | 
					String rank;
 | 
				
			||||||
 | 
					if (0 <= score && score < 60) {
 | 
				
			||||||
 | 
					    rank = "不及格";
 | 
				
			||||||
 | 
					} else if (60 <= score && score <= 84) {
 | 
				
			||||||
 | 
					    rank = "及格";
 | 
				
			||||||
 | 
					} else if (84 < score && score <= 100) {
 | 
				
			||||||
 | 
					    rank = "优秀";
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					    rank = "无效";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.out.println("if-else 获取值: " + rank);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建RangeMap, 基于TreeMap(红黑树)实现
 | 
				
			||||||
 | 
					RangeMap<Integer, String> treeRangeMap = TreeRangeMap.create();
 | 
				
			||||||
 | 
					treeRangeMap.put(Range.closedOpen(0, 60), "不及格");
 | 
				
			||||||
 | 
					treeRangeMap.put(Range.closed(60, 84), "及格");
 | 
				
			||||||
 | 
					treeRangeMap.put(Range.openClosed(84, 100), "优秀");
 | 
				
			||||||
 | 
					treeRangeMap.put(Range.lessThan(0), "无效");
 | 
				
			||||||
 | 
					treeRangeMap.put(Range.greaterThan(100), "无效");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rank = treeRangeMap.get(score);
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 获取值: " + rank);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建不可变RangeMap, 无法新增、更新或删除
 | 
				
			||||||
 | 
					ImmutableRangeMap<Integer, String> immutableRangeMap = ImmutableRangeMap.<Integer, String>builder()
 | 
				
			||||||
 | 
					        .put(Range.closedOpen(0, 60), "不及格")
 | 
				
			||||||
 | 
					        .put(Range.closed(60, 84), "及格")
 | 
				
			||||||
 | 
					        .put(Range.openClosed(84, 100), "优秀")
 | 
				
			||||||
 | 
					        .put(Range.lessThan(0), "无效")
 | 
				
			||||||
 | 
					        .put(Range.greaterThan(100), "无效")
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rank = immutableRangeMap.get(score);
 | 
				
			||||||
 | 
					System.out.println("\nImmutableRangeMap 获取值: " + rank);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取key-value对
 | 
				
			||||||
 | 
					Map.Entry<Range<Integer>, String> entry = treeRangeMap.getEntry(88);
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 获取key-value对: " + entry.getKey() + " : " + entry.getValue());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 返回不可变的升序的Map
 | 
				
			||||||
 | 
					Map<Range<Integer>, String> asMapOfRanges = treeRangeMap.asMapOfRanges();
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 不可变的升序的Map: " + asMapOfRanges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 返回不可变的降序的Map
 | 
				
			||||||
 | 
					Map<Range<Integer>, String> asDescendingMapOfRanges = treeRangeMap.asDescendingMapOfRanges();
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 不可变的降序的Map: " + asDescendingMapOfRanges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 相连范围合并
 | 
				
			||||||
 | 
					RangeMap<Integer, String> treeRangeMap2 = TreeRangeMap.create();
 | 
				
			||||||
 | 
					treeRangeMap2.putCoalescing(Range.closedOpen(0, 60), "不及格");
 | 
				
			||||||
 | 
					treeRangeMap2.putCoalescing(Range.closed(60, 84), "及格");
 | 
				
			||||||
 | 
					treeRangeMap2.putCoalescing(Range.openClosed(84, 100), "及格"); // 或者 [60..84]范围合并
 | 
				
			||||||
 | 
					treeRangeMap2.putCoalescing(Range.lessThan(0), "无效");
 | 
				
			||||||
 | 
					treeRangeMap2.putCoalescing(Range.greaterThan(100), "无效");
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 不合并相连范围: " + treeRangeMap.asMapOfRanges());
 | 
				
			||||||
 | 
					System.out.println("RangeMap 合并相连范围: " + treeRangeMap2.asMapOfRanges());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 最小范围
 | 
				
			||||||
 | 
					Range<Integer> span = treeRangeMap.span();
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 最小范围: " + span);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 子范围Map
 | 
				
			||||||
 | 
					RangeMap<Integer, String> subRangeMap = treeRangeMap.subRangeMap(Range.closed(70, 90));
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 子范围Map: " + subRangeMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 合并范围
 | 
				
			||||||
 | 
					treeRangeMap.merge(Range.closed(60, 100), "及格", (s, s2) -> s2);
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 合并Map: " + treeRangeMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 移除范围
 | 
				
			||||||
 | 
					treeRangeMap.remove(Range.open(90, 95));
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 移除范围: " + treeRangeMap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 清除所有范围
 | 
				
			||||||
 | 
					treeRangeMap.clear();
 | 
				
			||||||
 | 
					System.out.println("\nRangeMap 清除所有范围: " + treeRangeMap);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  执行结果:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```javascript
 | 
				
			||||||
 | 
					Copyif-else 获取值: 优秀
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 获取值: 优秀
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ImmutableRangeMap 获取值: 优秀
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 获取key-value对: (84..100] : 优秀
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 不可变的升序的Map: {(-∞..0)=无效, [0..60)=不及格, [60..84]=及格, (84..100]=优秀, (100..+∞)=无效}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 不可变的降序的Map: {(100..+∞)=无效, (84..100]=优秀, [60..84]=及格, [0..60)=不及格, (-∞..0)=无效}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 不合并相连范围: {(-∞..0)=无效, [0..60)=不及格, [60..84]=及格, (84..100]=优秀, (100..+∞)=无效}
 | 
				
			||||||
 | 
					RangeMap 合并相连范围: {(-∞..0)=无效, [0..60)=不及格, [60..100]=及格, (100..+∞)=无效}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 最小范围: (-∞..+∞)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 子范围Map: {[70..84]=及格, (84..90]=优秀}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 合并Map: [(-∞..0)=无效, [0..60)=不及格, [60..84]=及格, (84..100]=及格, (100..+∞)=无效]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 移除范围: [(-∞..0)=无效, [0..60)=不及格, [60..84]=及格, (84..90]=及格, [95..100]=及格, (100..+∞)=无效]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RangeMap 清除所有范围: []
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 7. ClassToInstanceMap - 类型映射到实例Map[#](https://www.cnblogs.com/cao-lei/p/17806222.html#85873049)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  官方注释翻译:映射,其每个条目将一个 Java 原始类型 映射到该类型的实例。除了实现 Map之外,还提供额外的类型安全操作 putInstance 和 getInstance 。与任何其他 Map<Class, Object>映射一样,此映射可能包含基元类型的条目,并且基元类型及其相应的包装器类型可以映射到不同的值。
 | 
				
			||||||
 | 
					  示例代码(需求:缓存Bean(不交给Spring管理,自己管理Bean)):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```csharp
 | 
				
			||||||
 | 
					Copyclass UserBean {
 | 
				
			||||||
 | 
					    private final Integer id;
 | 
				
			||||||
 | 
					    private final String username;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public UserBean(Integer id, String username) {
 | 
				
			||||||
 | 
					        this.id = id;
 | 
				
			||||||
 | 
					        this.username = username;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String toString() {
 | 
				
			||||||
 | 
					        return "UserBean{" + "id=" + id + ", username='" + username + '\'' + '}';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// 创建Bean
 | 
				
			||||||
 | 
					UserBean userBean = new UserBean(1, "张三");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HashMap
 | 
				
			||||||
 | 
					HashMap<Class, Object> hashMap = new HashMap<>();
 | 
				
			||||||
 | 
					hashMap.put(UserBean.class, userBean);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取值,需要强转
 | 
				
			||||||
 | 
					UserBean value = (UserBean) hashMap.get(UserBean.class);
 | 
				
			||||||
 | 
					System.out.println("HashMap 获取对象实例: " + value);
 | 
				
			||||||
 | 
					System.out.println("HashMap 获取对象实例等于创建的Bean: " + (value == userBean));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建ClassToInstanceMap
 | 
				
			||||||
 | 
					ClassToInstanceMap<Object> classToInstanceMap = MutableClassToInstanceMap.create();
 | 
				
			||||||
 | 
					classToInstanceMap.putInstance(UserBean.class, userBean);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取值,无需强转
 | 
				
			||||||
 | 
					UserBean value2 = classToInstanceMap.getInstance(UserBean.class);
 | 
				
			||||||
 | 
					System.out.println("\nClassToInstanceMap 获取对象实例: " + value2);
 | 
				
			||||||
 | 
					System.out.println("ClassToInstanceMap 获取对象实例等于创建的Bean: " + (value2 == userBean));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建不可变ClassToInstanceMap, 无法新增、更新或删除
 | 
				
			||||||
 | 
					ClassToInstanceMap<UserBean> immutableClassToInstanceMap = ImmutableClassToInstanceMap.<UserBean>builder()
 | 
				
			||||||
 | 
					        .put(UserBean.class, userBean)
 | 
				
			||||||
 | 
					        .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取值,无需强转
 | 
				
			||||||
 | 
					UserBean value3 = immutableClassToInstanceMap.getInstance(UserBean.class);
 | 
				
			||||||
 | 
					System.out.println("\nImmutableClassToInstanceMap 获取对象实例: " + value3);
 | 
				
			||||||
 | 
					System.out.println("ImmutableClassToInstanceMap 获取对象实例等于创建的Bean: " + (value3 == userBean));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 限制类型,避免使用HashMap存储对象时,因为使用Object值类型而在添加缓存时需要今天类型校验
 | 
				
			||||||
 | 
					ClassToInstanceMap<Collection> classToInstanceMap1 = MutableClassToInstanceMap.create();
 | 
				
			||||||
 | 
					classToInstanceMap1.put(ArrayList.class, new ArrayList());
 | 
				
			||||||
 | 
					classToInstanceMap1.put(HashSet.class, new HashSet());
 | 
				
			||||||
 | 
					// 编译保存: 'put(java.lang.Class<? extends java.util.@org.checkerframework.checker.nullness.qual.NonNull Collection>, java.util.Collection)' in 'com.google.common.collect.MutableClassToInstanceMap' cannot be applied to '(java.lang.Class<java.util.HashMap>, java.util.HashMap)'
 | 
				
			||||||
 | 
					//        classToInstanceMap1.put(HashMap.class, new HashMap());
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  执行结果:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					CopyHashMap 获取对象实例: UserBean{id=1, username='张三'}
 | 
				
			||||||
 | 
					HashMap 获取对象实例等于创建的Bean: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ClassToInstanceMap 获取对象实例: UserBean{id=1, username='张三'}
 | 
				
			||||||
 | 
					ClassToInstanceMap 获取对象实例等于创建的Bean: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ImmutableClassToInstanceMap 获取对象实例: UserBean{id=1, username='张三'}
 | 
				
			||||||
 | 
					ImmutableClassToInstanceMap 获取对象实例等于创建的Bean: true
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										10
									
								
								java/mybatis-plus.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								java/mybatis-plus.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					### mybtais-plus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mybtais-plus 默认空字段 不插入 导致生成的sql  字段不完整,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					在批量插入时, 因为每个po 空值不确定 导致 sql 重写失效, 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					&reWriteBatchedInserts=true
 | 
				
			||||||
							
								
								
									
										29
									
								
								openwrt/openVPN.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								openwrt/openVPN.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					## openWrt 路由器中的 openVPN  组件
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| **连接类型**          | 配置文件说明                                                | **模式** | **网络类型**      | **适用场景**                                                 | **对应配置文件示例** |
 | 
				
			||||||
 | 
					| :-------------------- | ----------------------------------------------------------- | :------- | :---------------- | :----------------------------------------------------------- | :------------------- |
 | 
				
			||||||
 | 
					| **client_tap_bridge** | Client configuration for an ethernet bridge VPN             | 客户端   | TAP(以太网桥接) | 客户端需完全接入服务器局域网(如访问 SMB 共享、网络打印机等) | `client-bridge.conf` |
 | 
				
			||||||
 | 
					| **client_tun**        | Client configuration for a routed multi-client VPN          | 客户端   | TUN(IP 路由)    | 标准多客户端 VPN,适用于远程办公、访问内网服务               | `client-routed.conf` |
 | 
				
			||||||
 | 
					| **client_tun_ptp**    | Simple client configuration for a routed point-to-point VPN | 客户端   | TUN(点对点路由) | 仅 1 对 1 连接,适合设备间专用加密隧道(如远程管理)         | `client-p2p.conf`    |
 | 
				
			||||||
 | 
					| **server_tap_bridge** | Server configuration for an ethernet bridge VPN             | 服务器   | TAP(以太网桥接) | 服务器提供桥接模式 VPN,客户端像本地设备一样访问整个 LAN     | `server-bridge.conf` |
 | 
				
			||||||
 | 
					| **server_tun**        | Server configuration for a routed multi-client VPN          | 服务器   | TUN(IP 路由)    | 标准多客户端 VPN 服务器,适用于企业远程访问                  | `server-routed.conf` |
 | 
				
			||||||
 | 
					| **server_tun_ptp**    | Simple server configuration for a routed point-to-point VPN | 服务器   | TUN(点对点路由) | 仅支持 1 对 1 连接的 VPN 服务器(如站点间 VPN)              | `server-p2p.conf`    |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### **关键说明**:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **配置文件名**:
 | 
				
			||||||
 | 
					   - 通常 OpenVPN 会根据 `option value` 生成对应的配置文件(如 `client_tun` → `client-routed.conf`)。
 | 
				
			||||||
 | 
					   - 实际文件名可能因系统不同有所变化,但逻辑一致。
 | 
				
			||||||
 | 
					2. **TAP vs. TUN**:
 | 
				
			||||||
 | 
					   - **TAP(`tap_bridge`)**:模拟以太网设备,适合需要广播/组播的应用(如网络游戏、局域网发现)。
 | 
				
			||||||
 | 
					   - **TUN(`tun`)**:仅路由 IP 流量,更高效,适合大多数 VPN(如网页访问、SSH)。
 | 
				
			||||||
 | 
					3. **多客户端 vs. 点对点(P2P)**:
 | 
				
			||||||
 | 
					   - **普通模式(`server_tun`/`client_tun`)**:支持多个客户端同时连接。
 | 
				
			||||||
 | 
					   - **点对点(`_ptp`)**:仅限两个节点直接通信,延迟更低。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### **典型应用**:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- **企业远程办公** → `server_tun` + `client_tun`
 | 
				
			||||||
 | 
					- **家庭局域网扩展** → `server_tap_bridge` + `client_tap_bridge`
 | 
				
			||||||
 | 
					- **服务器间加密通道** → `server_tun_ptp` + `client_tun_ptp`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user