Java 数据类型:集合接口Map:HashTable;HashMap;IdentityHashMap;LinkedHashMap;Properties类读取配置文件;SortedMap接口和TreeMap实现类:【线程安全的ConcurrentHashMap】
Map集合java.util.Map
方法:
- (1), void clear() : 删除该Map对象中所有的key-value对
- (2), boolean containsKey(Object key) : 查询Map中是否包含指定的key,如果包含返回true
- (3), boolean containsValue(Object value): 查询Map中是否包含一个或者多个value,如果包含,返回true,否则返回false.
- (4), Set entrySet(): 返回Map中包含key-value对所组成的Set集合,每个元素都是Map.Entry对象
- (5), Object get(Object key): 返回指定的key所对应的value,如果此Map中不包含该key,则返回null
- (6), boolean isEmpty(): 查询该Map是否为空
- (7), Set keySet(): 返回该Map中所有key组成的Set集合
- (8), Object put(Object key, Object value): 添加一个key-value对,如果Map中已经存在了对应的key了,那么会覆盖原来的。
- (9), void putAll(Map m):将制定的Map中的key-value复制到本Map中
- (10), Object remove(Object key) : 删除指定key锁对应的key-value对,返回被删除key所关联的value,如果key不存在,那么返回null。
- (11), boolean remove(Object key, Object value): 这个是java8新增的方法,删除制定key,value所对应的key-value对。如果从该Map中成功的删除该key-value对,该方法返回true,否则返回false
- (12), int size(): 返回该Map李对应的key-value对的个数
- (13), Collection values() : 返回该Map李所有value组成的Collection
Java8新增方法:
- Object compute(Object key, BitFunction remappingFunction): 该方法使用remappingFunction根据key-value计算一个新的value。只要value不为null,就是用新value覆盖原value,如果原value不为null,但是新value为null,则删除原来的key-value对。如果原value和新value都是null,那么该方法不改变任何的key-value对,直接返回null。
- Object computeIfAbsent(Object key, Function mappingFunction): 如果传给该方法的key参数在Map中对应的value为null, 则使用mappingFunction根据key计算一个新的结果,如果计算结果不为null,则用计算结果覆盖原有的value。如果原Map不包含该key,那么该方法可能会添加一组key-value对。
- void forEach(BiConsumer action): 该方法是Java8为Map新增的一个遍历Key-value对的方法,通过该方法可以更加简洁的遍历Map的key-value对。
- Object getOrDefault(Object key, V defaultValue) : 获取指定的key对应的value。如果key不存在,那么直接返回defaultValue
- Object merge(Object key, Object value, BiFunction remappingFunction): 该方法会先根据key参数获取该map中对象的value。如果获取的value为null,则直接用传入的value覆盖有缘的value(在这种情况下,可能要新添加一组key-value对);如果获取的value不为null,则使用remappingFunction函数根据原value,新value计算一个新的结果,并用得到的结果去覆盖原有的value。
- Object putIfAbsent(Object key, Object value): 该方法会自动检测指定key对应value是否为null,如果该key对应的value为null,该方法将会用新的value替代原来的value。
- Object replace(Object key, Object oldValue, Object newValue): 将Map中指定的key-value对的原value替换成新的value,如果Map中找到指定的key-value对,执行替换并返回true,否则返回false。
- void replaceAll(BiFunction function) : 该方法使用BiFunction对原key-value对执行计算,并且将计算结果作为该key-value对的value值。
void forEach(BiConsumer action): 测试
persons.forEach((key,value)-> System.out.println(key + "=" + value));
void replaceAll(BiFunction function) 测试
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction; public class MapExample {
public static void main(String[] args) {
Map persons = new HashMap();
//put方法就是添加key-value对
persons.put("张三",23);
persons.put("李四",28);
persons.put("王五",23);
System.out.println(persons);//{李四=28, 张三=23, 王五=23}
//对原有元素做自定义处理运算
persons.replaceAll((key,value) -> (int)value -1);
System.out.println(persons); //{李四=27, 张三=22, 王五=22}
}
}
Java8改进的HashMap和HashTable实现类:
- (1),HashTable是一个线程安全的Map实现,但是HashMap是线程不安全的实现,所以它比HashTable的性能高了一些。
- (2),HashTable不允许使用null作为key和value,如果试图把null的值放进HashTable中,将会引发NullPointerException异常。但是HashMap可以使用null作为key或者value。
HashMap和HashTable存储位置问题:
HashMap和HashTable的containsValue(Object object )方法判断相等其实就是equals:
IdentityHashMap
LinkedHashMap
- 性能要比HashMap低一些
- 元素维持着插入时的顺序
- 但是迭代LinkedHashMap的时候,效率会更快。
public class LinkHahsMapExample {
public static void main(String[] args) {
Map linkHashMap = new LinkedHashMap();
linkHashMap.put("张三",2);
linkHashMap.put("李四",3);
linkHashMap.put("老刘",4);
linkHashMap.forEach((k,v) -> System.out.println(k + "=====>" + v));
}
}
Properties类读取配置文件:
- 用来读取键值对的配置文件。
- String getProperty(String key): 获取Properties中指定属性名对应的属性值。
- Object setProperty(String key, String value): 设置属性值
- void load(InputStream inStream) : 从属性文件中加载key-value对。
- void store(OutputStream out, String comments): 将properties中的key-value对输出到指定的文件中。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties; /**
* @ClassName PropertiesExample
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/10.
*/
public class PropertiesExample {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.load(new FileReader("D:\\JavaStudy2\\集合\\src\\configTest.ini"));
properties.forEach((k,v) -> System.out.println(k + "=" + v));
/**如上输出
* password=xxx
* username=zmd
*/
properties.setProperty("qjj","hehe"); //新增或者设置老的key对应值
properties.store(new FileWriter("D:\\JavaStudy2\\集合\\src\\configTest2.ini"),"测试"); //保存到文件中
}
}
SortedMap接口和TreeMap实现类(排序的Map):
- Map.Entry firstEntry(): 返回该Map中key最小的key-value对,如果Map为空会返回null
- Object firstKey(): 返回该Map中最小的key值,如果该Map为空,返回null
- Map.Entry lastEntry(): 返回该Map中最大的key对应的key-value对,如果该Map为空或不存在key-value时,则都返回null。
- Object lastKey(): 返回该Map中最大的Key值,如果该Map为空或者不存在这样的key,则都返回null。
- Map.Entry higherEntity(Object key): 返回该Map中位于key后一位的key-value对(即大于指定key的最小key所对应的key-value对)。如果该Map为空,则返回null.
- Object higherKey(Object key): 返回该Map中位于key后一位的key-value对的key,如果Map为空返回null
- Map.Entry lowerEntry(Object key): 返回该Map中位于key前一位的key-value对,如果Map为空返回null.
- Object lowerKey(Object key): 返回该Map中位于key前一位的key的值。如果该Map为空,或者不存在这样的key,都返回null。
- 省略若干........。
import java.util.Map;
import java.util.TreeMap; public class TreeMapTest {
private static class A implements Comparable {
int count;
public A(int count) {
this.count = count;
}
@Override
public int compareTo(Object o) {
A a = (A) o;
return count - a.count;
} @Override
public String toString() {
return "A{count=" + count + '}';
}
}
public static void main(String[] args) {
TreeMap treeMap = new TreeMap();
treeMap.put(new A(9), "李一桐");
treeMap.put(new A(7), "刘亦菲");
treeMap.put(new A(-1), "鞠婧祎");
treeMap.put(new A(4), "蔡依林");
System.out.println(treeMap);
Map.Entry firstEntry = treeMap.firstEntry();
System.out.println(firstEntry);
System.out.println(firstEntry.getKey() + "------->" + firstEntry.getValue());
System.out.println("lastKey is " + treeMap.lastKey());
System.out.println(treeMap.higherEntry(new A(4)));
}
}
EnumMap
import java.util.EnumMap; public class EnumMapTest {
private enum SEASON {
SPRING, SUMMER, FALL, WINTER
}
public static void main(String[] args) {
EnumMap enumMap = new EnumMap(SEASON.class);
enumMap.put(SEASON.SPRING, "春乱花开");
enumMap.put(SEASON.SUMMER, "夏日炎炎");
enumMap.put(SEASON.FALL, "秋高气爽");
enumMap.put(SEASON.WINTER, "白雪皑皑");
System.out.println(enumMap);
}
}
各种Map性能分析:
总结:
线程安全的HashMap
1、ConcurrentHashMap - 推荐
private Map<String, Object> map = new ConcurrentHashMap<>();
这是最推荐使用的线程安全的Map,也是实现方式最复杂的一个集合,每个版本的实现方式也不一样,在jdk8之前是使用分段加锁的一个方式,分成16个桶,每次只加锁其中一个桶,而在jdk8又加入了红黑树和CAS算法来实现。性能好
2、HashTable
private Map<String, Object> map = new Hashtable<>();
HashTable的get/put方法都被synchronized关键字修饰,说明它们是方法级别阻塞的,它们占用共享资源锁,所以导致同时只能一个线程操作get或者put,而且get/put操作不能同时执行,所以这种同步的集合效率非常低,一般不建议使用这个集合。
3、SynchronizedMap
private Map<String, Object> map = Collections.synchronizedMap(new HashMap<String, Object>());
这种是直接使用工具类里面的方法创建SynchronizedMap,把传入进行的HashMap对象进行了包装同步而已。这个同步方式实现也比较简单,看出SynchronizedMap的实现方式是加了个对象锁,每次对HashMap的操作都要先获取这个mutex的对象锁才能进入,所以性能也不会比HashTable好到哪里去,也不建议使用。
看源码
============历史笔记==================
Map集合java.util.Map
以键值对的方式
HashMap hashMap = new HashMap(); //非线程安全
Hashtable hashtable = new Hashtable(); //线程安全
HashMap:底层是Hash表(散列表)
HashTable:线程安全的Hash表。
--Properties 继承了hashTable,键、值都是String字符串用来设置/读取系统属性
TreeMap: 实现了SortedMap接口可以根据键自然排序,要求键必须是可比较的
键是根据红黑树原理排序的,红黑树:一种自平衡二叉树
Map的操作:
clear() 清除元素
containsKey() 判断是否包含键
containsValue() 判断是否包含值
entrySet() 返回所有Entry的集合,
get(Object Key) 返回当前Map中键key对应的Value值
isEmpty() 判断是否为空
KeySet() 返回所有键的集合
put(K key,V value) 向Map中添加元素
putAll(Map<?extends K, ?extend V> m)
remove(Object key) 从map中删除键与key匹配的键值对
remove(Object key, Object value) 从map中删除键与key匹配的键值对
replace(K key , V value) 把map中键与key匹配的值替换为value
size() 返回键值对的数量
values() 返回所有值的集合
15-1 HashMap
15-1-1 示例代码:
//1、定义一个map集合,使用HashMap类实现
Map<String,Integer> map = new HashMap<>();
//2、添加数据
map.put("zhangsan",1300);
map.put("lisi",2370);
map.put("wangwu",2300);
map.put("zhaoliu",17800);
//3、直接打印调用HashMap的toString方法
System.out.println(map);//{lisi=2370, zhaoliu=17800, zhangsan=1300, wangwu=2300}
//4、Map的键不允许重复
map.put("zhaoliu",1234);//如果已存在,用put重复添加将会更新原来的数据=replace的效果
System.out.println(map); //{lisi=2370, zhaoliu=1234, zhangsan=1300, wangwu=2300}
//5、更改
map.replace("zhaoliu",1234);
System.out.println(map);
//6、判断
System.out.println(map.containsKey("zhangsan"));
System.out.println(map.containsValue(2300));
//7、获取Value
System.out.println(map.get("zhangsan"));
System.out.println(map.get("zhangsi")); //不存在返回null
//8、删除
map.remove("zhangsan",9999); //键值都匹配上才删除
System.out.println(map);
map.remove("zhangsan");//键在就删除
System.out.println(map);
//9、遍历
//返回所有键的集合
Set<String> set = map.keySet();
System.out.println(set);
//返回所有值的集合,
for (Integer value : map.values()) {
System.out.println(value);
}
//10、遍历
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
典型应用示例:
//统计一个字符串中每个字符出现的次数
Map<Character,Integer> map = new HashMap<>();
String text = "1234567uyutrewqwertyuytrerfdsadfghjkokmkool,,kxcmnbzsertfgvxfwerdfxdweetrgfdsewethfgcxvcz";
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (map.containsKey(c)){ //如果已存在键,把值取出来+1
map.replace(c,map.get(c) + 1); //把值取出来+1,更新键值对
}else {
map.put(c,1); //如果原来没有,put进去,值为1
}
}
System.out.println(map);
15-1-2 HashMap的工作原理
put工作原理:
1)HashMap底层是哈希表,哈希表就是一个数组,数组元素是链表。
2)put添加键值对时:
先根据键的哈希码,经过hash函数计算hash值,根据hash值计算数组下标,访问table[i]元素,
如果该元素为null,就创建节点保存到元素中。
如果该元素不为null,遍历table[i]存储的链表中所有节点
如果有节点的key与当前键相等(Equals),就是用新的value值替换节点中的值
如果所有节点的key都不匹配,就创建一个新的节点插入到链表的尾部
--------传说中的哈希函数:
static final int hash(Object key)
int h;
rerurn (key == null ) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
//如果key为null 返回0;
//如果不为null,用key的hash码 和 哈希码右移16位 取异或的值。
//(int 占用4个字节,共计32位的长度)
get工作原理: }
先根据键的哈希码,经过hash函数计算hash值,根据hash值计算数组下标,访问table[i]元素,
如果该元素为null返回null
如果不为null,遍历table[i]的链表,如果链表中有节点的键和与当前键Equals相等,就把该节点的value值返回,如果所有节点的key与当前get的键不匹配,返回null
知识点:
如何解决hash碰撞的?
答:-----就是用链表法
JDB中对HashMap做了哪些改进:
答:1、新增节点插入链表尾部
2、链表长度大于8个,会转换为红黑树(自平衡二叉树)
应用案例:取出url中所有请求参数params
Map<String,String[]> map = new HashMap<>();
String urlText = "http://www.baihe.com/register?name=lisi&age=22&gender=女&interest=sing&interest=dance&interest=rap&interest=ball";
//取出url中所有搜索值
int index = urlText.indexOf("?");
//从?后面开始取子串
String paramText = urlText.substring(index + 1);
System.out.println(paramText);//name=lisi&age=22&gender=女&interest=sing&interest=dance&interest=rap&interest=ball
//取出的所有参数缠粉为数组
String[] paramTextArray= paramText.split("[=&]");//正则表达式放到双引号里面
System.out.println(Arrays.toString(paramTextArray));
//对数组遍历取值//每次从paramTextArray数组中取出参数名和参数值两个数据,所以步长为2
for (int i = 0; i < paramTextArray.length; i+=2 ) {
//如果key不存在,就创建一个数组放进map中,key为下标为i的paramTextArray数组值
if (! map.containsKey(paramTextArray[i])){
//添加/创建一个数据放到map集合中,值为一个新数组,创建是传入数据初始化即可
map.put(paramTextArray[i],new String[]{paramTextArray[i+1]});
}else {
//如果已存在则取出原来的数组更新
String[] paramArray = map.get(paramTextArray[i]);
//更新前首先要扩容数组长度
paramArray = Arrays.copyOf(paramArray,paramArray.length +1);
//新增数组元素
paramArray[paramArray.length -1 ] = paramTextArray[i + 1];
//更新元素到
map.replace(paramTextArray[i],paramArray);
}
}
//打印取值的map结果
for (Map.Entry<String, String[]> entry : map.entrySet()) {
System.out.println(entry.getKey() + "="+ Arrays.toString(entry.getValue()));
}
//输出
// gender=[女]
//interest=[sing, dance, rap, ball]
//name=[lisi]
//age=[22]
15-2 HashTable
1)底层都是hash表,HashTable是线程安全的,HahsMap不是线程安全的。
2)初始化容量HashTable为11,HashMap为16
3)加载因子:0.75 当键值对数量> 容量*加载因子 个数进行扩容。
4)扩容:HashTable按2倍+1扩容,HashMap按2倍大小扩容
5) 在使用时HashTable的键与值都不能为null,而HashMap的键和值都可以为null
6)在创建是可以指定初始化容量,HashMap会吧初始化容量自动跳转为2的幂次方,为了快速计算数组下标;而HashTable指定多少就是多少
15-2-1 Properties
继承了HashTable
键值都是String字符串
经常用户设置读取系统属性
方法
setProperty(属性名、属性值)
getProperty(属性名、属性值)
//默认键值都是String,无需指定
示例代码:
Properties properties = new Properties();
properties.setProperty("tdq","123123");
System.out.println(properties.getProperty("tdq"));
System.out.println(properties.getProperty("td"));
//读取系统属性
properties = System.getProperties();
//遍历取值
/* for (Object o : properties.keySet()) {
System.out.println(o);//取key
}*/
//遍历取值entrySet
for (Map.Entry<Object, Object> objectObjectEntry : properties.entrySet()) {
System.out.println(objectObjectEntry.getKey() + "=" + objectObjectEntry.getValue());
}
读取配置文件示例代码:
//propertiesTest02.java
【方法一:代码文件.class.getResourceAsStream()/Thread.currentThread()】
//1、键值默认都是String,创建Properties对象
Properties properties = new Properties();
//2、加载配置文件
InputStream in = propertiesTest02.class.getResourceAsStream("/resources/config.properties");
InputStream in2 = Thread.currentThread().getContextClassLoader().getResourceAsStream("resources/config.properties");
properties.load(in2);//load异常Alt + Enter 选择第一个处理
//3、读取配置文件
System.out.println(properties.getProperty("zmd"));
System.out.println(properties.getProperty("pwd"));
【方法二:通过ResourceBundle.getBundle("相对路径")】
用法ResourceBundle.getBundle("")不需要扩展名和/ ;这个是 静态方法
ResourceBundle resourceBundle = ResourceBundle.getBundle("resources/config");
System.out.println(resourceBundle.getString("zmd"));
System.out.println(resourceBundle.getString("pwd"));
-----------------------------------------------------------
配置文件
目录:properites
文件:propertiesTest02.java
目录:resources
文件:config.properties 【创建方法IDEA new resource bundle】
内容如下:
name=zmd
pwd:123
15-3 TreeMap
TreeMap 实现了SortedMap 接口,可以根据键自然排序,要求键必须是可比较的
1)在构造方法中指定Comparator比较器
2)让键实现Comparable接口
3)TreeMap只能根据键排序,不能根据值排序
4)使用String作为键,String本身已经实现了Comparable接口
示例代码:
//创建TreeMap存储<员工姓名,工资> 要求根据姓名降序排序
TreeMap<String,Integer> treeMap = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
treeMap.put("lisi",2000);
treeMap.put("wangwu",1234);
treeMap.put("zhaoliu",8863);
treeMap.put("chenqi",7800);
System.out.println(treeMap); //{zhaoliu=8863, wangwu=1234, lisi=2000, chenqi=7800}
//注意:TreeMap只能根据键排序,不能根据值排序
//如果没有在构造方法中指定Comparator,键实现Comparable接口即可。基本数据类型已经实现Comparable接口
TreeMap<String,Integer> treeMap1 = new TreeMap<>();
treeMap1.putAll(treeMap);
System.out.println(treeMap1);//默认根据键升序排列
TreeMap中的键是根据共黑树原理排序,是一种自平衡二叉树
二叉树了解:
遍历二叉树的方式有:先序遍历
后序遍历
中序遍历(左子树、根、右子树)
Java 数据类型:集合接口Map:HashTable;HashMap;IdentityHashMap;LinkedHashMap;Properties类读取配置文件;SortedMap接口和TreeMap实现类:【线程安全的ConcurrentHashMap】的更多相关文章
- Java——(七)Map之HashMap和Hashtable实现类
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- Map Map用于具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的ke ...
- Java容器深入浅出之Map、HashMap、Hashtable及其它实现类
在Java中,Set的底层事实上是基于Map实现的,Map内部封装了一个Entry内部接口,由实现类来封装key-value对,当value值均为null时,key的集合就形成了Set.因此,Map集 ...
- Java:集合,Map接口框架图
Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...
- JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API
森林森 一份耕耘,一份收获 博客园 首页 新随笔 联系 管理 订阅 随笔- 397 文章- 0 评论- 78 JAVA基础学习day16--集合三-Map.HashMap,TreeMap与常用A ...
- java:容器/集合(Map(HashMap,TreeMap)Collection和Collections,(Collection-value();)
*Map接口:采用是键值对的方式存放数据.无序 HashMap: *常见的实现类: *--HashMap:基于哈希表的 Map 接口的实现. *常用的构造方法: * HashMap()构造一个具有默认 ...
- java容器类2:Map及HashMap深入解读
Java的编程过程中经常会和Map打交道,现在我们来一起了解一下Map的底层实现,其中的思想结构对我们平时接口设计和编程也有一定借鉴作用.(以下接口分析都是以jdk1.8源码为参考依据) 1. Map ...
- Map,Hashmap,LinkedHashMap,Hashtable,TreeMap
java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap. Map主要用于存储健值对, ...
- java基础集合简介Map(三)下
--Map接口简介 今天来看一看map集合,map映射接口,用于存放键值对,<key,value>,通过key来查找value,顾名思义key不能为空,唯一且不重复,不然底层怎么查呢! 可 ...
- Java之集合(十四)Hashtable
转载请注明源出处:http://www.cnblogs.com/lighten/p/7426522.html 1.前言 HashTable这个类很奇特,其继承了Dictionary这个没有任何具体实现 ...
随机推荐
- spring boot的mybatis开启日志
logging: level: com: xxx: xxxx: xxxx: mapper: DEBUG logging.level.mapper对应的包名=DEBUG
- 微信小程序-物流api
原来用的快递100的接口有变动,现有系统上不能使用了.查看快递100提供的api,探寻微信小程序端的使用情况.有几个是比较合适的:1.跳转api(https://www.kuaidi100.com/o ...
- Sentry 监控 - Snuba 数据中台本地开发环境配置实战
系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...
- 使用protobuf-java-format包 JsonFormat转Json部分默认值字段消失问题
使用protobuf-java-format包 JsonFormat转Json部分默认值字段消失问题 1.产生的bug XXXXXXXXRequest.Builder request = XXXXXX ...
- Codeforces 453E - Little Pony and Lord Tirek(二维线段树+ODT)
Codeforces 题目传送门 & 洛谷题目传送门 一道难度 *3100 的 DS,而且被我自己搞出来了! 不过我终究还是技不如人,因为这是一个 \(n\log^2n\) + 大常数的辣鸡做 ...
- CF1578I Interactive Rays:ICPC WF Moscow Invitational Contest I 题解
题意简述:在平面上有一个坐标 \((x_c,y_c)\) 和半径 \(r\) 都是整数的圆 \((1\leq r_c\leq \sqrt{x_c^2+y_c^2}-1)\),你可以询问不超过 \(60 ...
- 【百奥云GS专栏】全基因组选择之工具篇
目录 1. 免费开源包/库 1.1 R包 1.2 Python库 2. 成熟软件 3. WEB/GUI工具 前面我们已经介绍了基因组选择的各类模型,今天主要来了解一下做GS有哪些可用的软件和工具.基因 ...
- 全网最详细的ReentrantReadWriteLock源码剖析(万字长文)
碎碎念) 花了两天时间,终于把ReentrantReadWriteLock(读写锁)解析做完了.之前钻研过AQS(AbstractQueuedSynchronizer)的源码,弄懂读写锁也没有想象中那 ...
- Netty之Channel*
Netty之Channel* 本文内容主要参考**<<Netty In Action>> ** 和Netty的文档和源码,偏笔记向. 先简略了解一下ChannelPipelin ...
- Kafka入门教程(二)
转自:https://blog.csdn.net/yuan_xw/article/details/79188061 Kafka集群环境安装 相关下载 JDK要求1.8版本以上. JDK安装教程:htt ...