作者:じ☆ve宝贝
你是否曾经有过要计算一个非常大的数据(几百GB)的需求?或在里面搜索,或其它操作——一些无法并行的操作。数据专家们,我是在对你们说。你可能有一个4核或更多核的CPU,但我们合适的工具,例如 **grep, bzip2, wc, awk, sed**等等,都是单线程的,只能使用一个CPU内核。 借用卡通人物Cartman的话,“如何我能使用这些内核”? 要想让Linux命令使用所有的CPU内核,我们需要用到GNU Parallel命令,它让我们所有的CPU内核在单机内做神奇的map-reduce操作,当然,这还要借助很少用到的–pipes 参数(也叫做–spreadstdin)。这样,你的负载就会平均分配到各CPU上,真的。 ###BZIP2 bzip2是比gzip更好的压缩工具,但它很慢!别折腾了,我们有办法解决这问题。 ###以前的做法: ` cat bigfile.bin | bzip2 --best > compressedfile.bz2 ` 现在这样: ` cat bigfile.bin | parallel --pipe --recend '' -k bzip2 --best > compressedfile.bz2 ` 尤其是针对bzip2,GNU parallel在多核CPU上是超级的快。你一不留神,它就执行完成了。 ###GREP 如果你有一个非常大的文本文件,以前你可能会这样: ` grep pattern bigfile.txt ` 现在你可以这样: ` cat bigfile.txt | parallel --pipe grep 'pattern' ` 或者这样: ` cat bigfile.txt | parallel --block 10M --pipe grep 'pattern' ` 这第二种用法使用了 –block 10M参数,这是说每个内核处理1千万行——你可以用这个参数来调整每个CUP内核处理多少行数据。 ###AWK 下面是一个用awk命令计算一个非常大的数据文件的例子。 常规用法: ` cat rands20M.txt | awk '{s+=$1} END {print s}' ` 现在这样: ` cat rands20M.txt | parallel --pipe awk \'{s+=\$1} END {print s}\' | awk '{s+=$1} END {print s}' ` 这个有点复杂:parallel命令中的–pipe参数将cat输出分成多个块分派给awk调用,形成了很多子计算操作。这些子计算经过第二个管道进入了同一个awk命令,从而输出最终结果。第一个awk有三个反斜杠,这是GNU parallel调用awk的需要。 ###WC 想要最快的速度计算一个文件的行数吗? 传统做法: ` wc -l bigfile.txt ` 现在你应该这样: ` cat bigfile.txt | parallel --pipe wc -l | awk '{s+=$1} END {print s}' ` 非常的巧妙,先使用parallel命令‘mapping’出大量的wc -l调用,形成子计算,最后通过管道发送给awk进行汇总。 ###SED 想在一个巨大的文件里使用sed命令做大量的替换操作吗? 常规做法: ` sed s^old^new^g bigfile.txt ` 现在你可以: ` cat bigfile.txt | parallel --pipe sed s^old^new^g ` …然后你可以使用管道把输出存储到指定的文件里。
作者:微信小助手
<h1 style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong>一、数据库瓶颈</strong></span></h1> <h1 style="margin-left: 8px;margin-right: 8px;"><br></h1> <h1 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值。</span><span style="">在业务Service来看就是,可用数据库连接少甚至无连接可用。接下来就可以想象了吧(并发量、吞吐量、崩溃)。</span></h1> <p><br></p> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">1. IO瓶颈</span></strong><strong><span style="font-size: 14px;font-family: 黑体;"></span></strong></span></h2> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">第一种:</span><span style="font-size: 14px;">磁盘读IO瓶颈,热点数据太多,数据库缓存放不下,每次查询时会产生大量的IO,降低查询速度 -> <strong>分库和垂直分表</strong>。</span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">第二种:</span><span style="font-size: 14px;">网络IO瓶颈,请求的数据太多,网络带宽不够 -> <strong>分库</strong>。</span></p> <p><br></p> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">2. CPU瓶颈</span></strong><strong><span style="font-size: 14px;font-family: 黑体;"></span></strong></span></h2> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">第一种:</span><span style="font-size: 14px;">SQL问题,如SQL中包含join,group by,order by,非索引字段条件查询等,增加CPU运算的操作 -> SQL优化,建立合适的索引,在业务Service层进行业务计算。</span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">第二种:</span><span style="font-size: 14px;">单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈 -> <strong>水平分表</strong>。</span></p> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong>二、分库分表</strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong style="font-size: 16px;"><span style="font-size: 14px;font-family: 黑体;"><br></span></strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong style="font-size: 16px;"><span style="font-size: 14px;font-family: 黑体;">1. 水平分库</span></strong><strong style="font-size: 16px;"><span style="font-size: 14px;font-family: 黑体;"></span></strong></span></p> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-family: 黑体;font-size: 14px;"></span></h2> <h2><br></h2> <h2 style="margin-left: 8px;margin-right: 8px;text-align: center;"><img class="" data-ratio="0.4046242774566474" src="/upload/d00e0483f086e6d424677842ceca2e92.png" data-type="png" data-w="692"></h2> <ul class=" list-paddingleft-2" style="list-style-type: circle;"> <li><h2 style="white-space: normal;"><span style="font-size: 14px;">概念:</span><span style="font-size: 14px;"><span style="font-size: 14px;font-family: "Microsoft YaHei"">以</span><strong style="font-family: "Microsoft YaHei"">字段</strong><span style="font-size: 14px;font-family: "Microsoft YaHei"">为依据,按照一定策略(hash、range等),将一个<strong>库</strong>中的数据拆分到多个<strong>库</strong>中。</span></span></h2></li> <li><p><span style="font-size: 14px;">结果:</span></p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p><span style="font-size: 14px;">每个<strong>库</strong>的<strong>结构</strong>都一样;</span></p></li> <li><p><span style="font-size: 14px;">每个<strong>库</strong>的<strong>数据</strong>都不一样,没有交集;</span></p></li> <li><p><span style="font-size: 14px;">所有<strong>库</strong>的<strong>并集</strong>是全量数据;</span></p></li> </ul> <li><p><span style="font-size: 14px;">场景:</span><span style="font-size: 14px;">系统绝对并发量上来了,分表难以根本上解决问题,并且还没有明显的业务归属来垂直分库。</span></p></li> <li><p><span style="font-size: 14px;">分析:</span><span style="font-size: 14px;">库多了,io和cpu的压力自然可以成倍缓解。</span></p></li> </ul> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;"><br></span></strong></span></h2> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">2. 水平分表</span></strong><strong><span style="font-size: 14px;font-family: 黑体;"></span></strong></span></h2> <p style="margin-left: 8px;margin-right: 8px;text-align: center;"><span style="font-family: 黑体;font-size: 14px;"><img class="" data-ratio="0.8746177370030581" src="/upload/909310d04e3c8651de1a59ff051fd820.png" data-type="png" data-w="327"></span></p> <ul class=" list-paddingleft-2" style="list-style-type: circle;"> <li><p><span style="font-size: 14px;">概念:</span><span style="font-size: 14px;">以<strong>字段</strong>为依据,按照一定策略(hash、range等),将一个<strong>表</strong>中的数据拆分到多个<strong>表</strong>中。</span></p></li> <li><p><span style="font-size: 14px;">结果:</span></p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p><span style="font-size: 14px;">每个<strong>表</strong>的<strong>结构</strong>都一样;</span></p></li> <li><p><span style="font-size: 14px;">每个<strong>表</strong>的<strong>数据</strong>都不一样,没有交集;</span></p></li> <li><p><span style="font-size: 14px;">所有<strong>表</strong>的<strong>并集</strong>是全量数据;</span></p></li> </ul> <li><p><span style="font-size: 14px;">场景:</span><span style="font-size: 14px;">系统绝对并发量并没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为瓶颈。</span></p></li> <li><p><span style="font-size: 14px;">分析:</span><span style="font-size: 14px;">表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。</span></p></li> </ul> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-family: 黑体;font-size: 14px;"><br></span></h2> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">3. 垂直分库</span></strong><strong><span style="font-size: 14px;font-family: 黑体;"></span></strong></span></h2> <p style="margin-left: 8px;margin-right: 8px;text-align: center;"><span style="font-family: 黑体;font-size: 14px;"><img class="" data-ratio="0.4924406047516199" src="/upload/92c2b009abdfd39fffd4cc561deb00a8.png" data-type="png" data-w="463"></span></p> <ul class=" list-paddingleft-2" style="list-style-type: circle;"> <li><p><span style="font-size: 14px;">概念:</span><span style="font-size: 14px;">以<strong>表</strong>为依据,按照业务归属不同,将不同的<strong>表</strong>拆分到不同的<strong>库</strong>中。</span></p></li> <li><p><span style="font-size: 14px;">结果:</span></p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p><span style="font-size: 14px;">每个<strong>库</strong>的<strong>结构</strong>都不一样;</span></p></li> <li><p><span style="font-size: 14px;">每个<strong>库</strong>的<strong>数据</strong>也不一样,没有交集;</span></p></li> <li><p><span style="font-size: 14px;">所有<strong>库</strong>的<strong>并集</strong>是全量数据;</span></p></li> </ul> <li><p><span style="font-size: 14px;">场景:</span><span style="font-size: 14px;">系统绝对并发量上来了,并且可以抽象出单独的业务模块。</span></p></li> <li><p><span style="font-size: 14px;">分析:</span><span style="font-size: 14px;">到这一步,基本上就可以服务化了。</span><span style="font-size: 14px;">例如,随着业务的发展一些公用的配置表、字典表等越来越多,这时可以将这些表拆到单独的库中,甚至可以服务化。</span><span style="font-size: 14px;">再有,随着业务的发展孵化出了一套业务模式,这时可以将相关的表拆到单独的库中,甚至可以服务化。</span></p></li> </ul> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-family: 黑体;font-size: 14px;"><br></span></h2> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">4. 垂直分表</span></strong><strong><span style="font-size: 14px;font-family: 黑体;"></span></strong></span></h2> <p style="margin-left: 8px;margin-right: 8px;text-align: center;"><img class="" data-ratio="0.37050359712230213" src="/upload/a4855d045e7df1ed13b3ee431e9b9105.png" data-type="png" data-w=""></p> <ul class=" list-paddingleft-2" style="list-style-type: circle;"> <li><p><span style="font-size: 14px;">概念:</span><span style="font-size: 14px;">以<strong>字段</strong>为依据,按照字段的活跃性,将<strong>表</strong>中字段拆到不同的<strong>表</strong>(主表和扩展表)中。</span></p></li> <li><p><span style="font-size: 14px;">结果:</span></p></li> <ul class=" list-paddingleft-2" style="list-style-type: square;"> <li><p><span style="font-size: 14px;">每个<strong>表</strong>的<strong>结构</strong>都不一样;</span></p></li> <li><p><span style="font-size: 14px;">每个<strong>表</strong>的<strong>数据</strong>也不一样,一般来说,每个表的<strong>字段</strong>至少有一列交集,一般是主键,用于关联数据;</span></p></li> <li><p><span style="font-size: 14px;">所有<strong>表</strong>的<strong>并集</strong>是全量数据;</span></p></li> </ul> <li><p><span style="font-size: 14px;">场景:</span><span style="font-size: 14px;">系统绝对并发量并没有上来,表的记录并不多,但是字段多,并且热点数据和非热点数据在一起,单行数据所需的存储空间较大。</span><span style="font-size: 14px;">以至于数据库缓存的数据行减少,查询时会去读磁盘数据产生大量的随机读IO,产生IO瓶颈。</span></p></li> <li><p><span style="font-size: 14px;">分析:</span><span style="font-size: 14px;">可以用列表页和详情页来帮助理解。</span><span style="font-size: 14px;">垂直分表的拆分原则是将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。</span><span style="font-size: 14px;">这样更多的热点数据就能被缓存下来,进而减少了随机读IO。</span><span style="font-size: 14px;">拆了之后,要想获得全部数据就需要关联两个表来取数据。</span><span style="font-size: 14px;">但记住,千万别用join,因为join不仅会增加CPU负担并且会讲两个表耦合在一起(必须在一个数据库实例上)。</span><span style="font-size: 14px;">关联数据,应该在业务Service层做文章,分别获取主表和扩展表数据然后用关联字段关联得到全部数据。</span></p></li> </ul> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong>三、分库分表工具</strong><strong><br></strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong><br></strong></span></p> <ul class=" list-paddingleft-2" style="list-style-type: circle;"> <li><p><span style="font-size: 14px;">sharding-sphere:</span><span style="font-size: 14px;">jar,前身是sharding-jdbc;</span></p></li> <li><p class="title-article"><span style="font-size: 14px;">TDDL:</span><span style="font-size: 14px;">jar,Taobao Distribute Data Layer;</span></p></li> <li><p><span style="font-size: 14px;">Mycat:</span><span style="font-size: 14px;">中间件。</span></p></li> </ul> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">注:</span><span style="font-size: 14px;">工具的利弊,请自行调研,官网和社区优先。</span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: white;font-family: 黑体;font-size: 14px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong><span style="color: rgb(64, 118, 0);font-size: 14px;font-family: 黑体;">四、分库分表步骤</span></strong><strong><span style="color: rgb(64, 118, 0);font-size: 14px;font-family: 黑体;"></span></strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: white;font-family: 黑体;font-size: 14px;"><br></span></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">根据容量(当前容量和增长量)评估分库或分表个数 -> 选key(均匀)-> 分表规则(hash或range等)-> 执行(一般双写)-> 扩容问题(尽量减少数据的移动)。</span></p> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong>五、分库分表问题</strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">1. 非partition key的查询问题</span></strong><span style="font-size: 14px;font-family: 黑体;">(水平分库分表,拆分策略为常用的hash法)</span></span></h2> <p><span style="font-family: 黑体;font-size: 14px;"><br></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 14px;"><strong>端上</strong>除了partition key只有一个非partition key作为条件查询</span></p></li> </ul> <ol class=" list-paddingleft-2" style="margin-left: 8px;margin-right: 8px;"> <ul class=" list-paddingleft-2" style=""> <li><p><span style="font-size: 14px;"><strong>映射法</strong></span><br><img class="" data-ratio="0.5647058823529412" src="/upload/36e685c2d45f7f6f2a1965fddfacf70d.png" data-type="png" data-w="510"></p></li> <li><p><span style="font-size: 14px;"><strong>基因法</strong></span><br><img class="" data-ratio="0.40668523676880225" src="/upload/e53cc375321231cfd24fa41185a765fc.png" data-type="png" data-w="718"></p><p><span style="font-size: 14px;">注:</span><span style="font-size: 14px;">写入时,基因法生成user_id,如图。</span><span style="font-size: 14px;">关于xbit基因,例如要分8张表,2<sup>3</sup>=8,故x取3,即3bit基因。</span><span style="font-size: 14px;">根据user_id查询时可直接取模路由到对应的分库或分表。</span><span style="font-size: 14px;">根据user_name查询时,先通过user_name_code生成函数生成user_name_code再对其取模路由到对应的分库或分表。</span><span style="font-size: 14px;">id生成常用<strong>snowflake算法</strong>。</span></p></li> </ul> </ol> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 14px;"><strong>端上</strong>除了partition key不止一个非partition key作为条件查询</span></p></li> </ul> <ol class=" list-paddingleft-2" style="margin-left: 8px;margin-right: 8px;"> <ul class=" list-paddingleft-2" style=""> <li><p><span style="font-size: 14px;"><strong>映射法</strong></span><br><img class="" data-ratio="0.5079365079365079" src="/upload/c155424a485caa47deda3231b83588d.png" data-type="png" data-w="567"></p></li> <li><p><span style="font-size: 14px;"><strong>冗余法</strong></span><br><img class="" data-ratio="0.5095890410958904" src="/upload/4ee1ee6c15d607946ef13e6ae41852fc.png" data-type="png" data-w="730"></p><p><span style="font-size: 14px;">注:</span><span style="font-size: 14px;">按照order_id或buyer_id查询时路由到db_o_buyer库中,按照seller_id查询时路由到db_o_seller库中。</span><span style="font-size: 14px;">感觉有点本末倒置!</span><span style="font-size: 14px;">有其他好的办法吗?</span><span style="font-size: 14px;">改变技术栈呢?</span></p></li> </ul> </ol> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 14px;"><strong>后台</strong>除了partition key还有各种非partition key组合条件查询</span></p></li> </ul> <ol class=" list-paddingleft-2" style="margin-left: 8px;margin-right: 8px;"> <ul class=" list-paddingleft-2" style=""> <li><p><span style="font-size: 14px;">NoSQL法</span><br><img class="" data-ratio="0.9614325068870524" src="/upload/92a2f44c840d6f514eb910b87f215d57.png" data-type="png" data-w="363"></p></li> <li><p><span style="font-size: 14px;">冗余法</span><br><img class="" data-ratio="0.8106235565819861" src="/upload/d49aef3a133300ade0d969077518e46b.png" data-type="png" data-w="433"></p></li> </ul> </ol> <p><br></p> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">2. 非partition key跨库跨表分页查询问题</span></strong><span style="font-size: 14px;font-family: 黑体;">(水平分库分表,拆分策略为常用的hash法)</span></span></h2> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">注:</span><span style="font-size: 14px;">用<strong>NoSQL法</strong>解决(ES等)。</span></p> <p><br></p> <h2 style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;"><strong><span style="font-size: 14px;font-family: 黑体;">3. 扩容问题</span></strong><span style="font-size: 14px;font-family: 黑体;">(水平分库分表,拆分策略为常用的hash法)</span></span></h2> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 14px;">水平扩容库(升级从库法)</span><br><img class="" data-ratio="1.5122324159021407" src="/upload/2ae26877a69ab98dc0b80eb5f5f87871.png" data-type="png" data-w="654"></p><p><span style="font-size: 14px;">注:</span><span style="font-size: 14px;">扩容是成倍的。</span></p></li> <li><p><span style="font-size: 14px;">水平扩容表(双写迁移法)</span><br><img class="" data-ratio="0.44550408719346046" src="/upload/e6b60f86e673ad2de0cd30fcba54d32f.png" data-type="png" data-w="734"><br><span style="font-size: 14px;">第一步:</span><span style="font-size: 14px;">(同步双写)应用配置双写,部署;</span><br><span style="font-size: 14px;">第二步:</span><span style="font-size: 14px;">(同步双写)将老库中的老数据复制到新库中;</span><br><span style="font-size: 14px;">第三步:</span><span style="font-size: 14px;">(同步双写)以老库为准校对新库中的老数据;</span><br><span style="font-size: 14px;">第四步:</span><span style="font-size: 14px;">(同步双写)应用去掉双写,部署;</span></p></li> </ul> <p style="margin-left: 8px;margin-right: 8px;"><span style="font-size: 14px;">注:</span><span style="font-size: 14px;"><strong>双写</strong>是通用方案。</span></p> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong>六、分库分表总结</strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 14px;">分库分表,首先得知道瓶颈在哪里,然后才能合理地拆分(分库还是分表?</span><span style="font-size: 14px;">水平还是垂直?</span><span style="font-size: 14px;">分几个?</span><span style="font-size: 14px;">)。</span><span style="font-size: 14px;">且不可为了分库分表而拆分。</span></p></li> <li><p><span style="font-size: 14px;">选key很重要,既要考虑到拆分均匀,也要考虑到非partition key的查询。</span></p></li> <li><p><span style="font-size: 14px;">只要能满足需求,拆分规则越简单越好。</span></p></li> </ul> <p><br></p> <p style="margin-left: 8px;margin-right: 8px;"><span style="color: rgb(64, 118, 0);font-size: 14px;"><strong>七、分库分表示例</strong></span></p> <p style="margin-left: 8px;margin-right: 8px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;text-align: left;"><span style="font-size: 14px;">示例GitHub地址:</span><span style="font-size: 14px;">https://github.com/littlecharacter4s/study-sharding</span></p> <p style="margin-left: 8px;margin-right: 8px;text-align: left;"><br></p> <p style="margin-left: 8px;margin-right: 8px;text-align: left;"><span style="font-size: 14px;">本文来自博客园尜尜人物:</span><span style="font-size: 14px;">www.cnblogs.com/littlecharacter</span><span style=""></span></p> <p style="border-color: currentcolor;border-style: none;border-width: medium;margin: 5px 8px 0px;padding: 10px 0px;background: none 0% 0% repeat scroll rgba(0, 0, 0, 0);line-height: normal;"><span style="color: rgb(136, 136, 136);font-size: 14px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。</span></p> <section label="Copyright © 2014 playhudong All Rights Reserved." style="border-color: currentcolor;border-style: none;border-width: medium;-moz-border-top-colors: none;-moz-border-left-colors: none;-moz-border-bottom-colors: none;-moz-border-right-colors: none;margin: 5px 0px 0px;padding: 10px 0px;background: rgba(0, 0, 0, 0) none repeat scroll 0% 0%;"> <img class="" data-ratio="0.05278592375366569" src="/upload/895b409cfe0a5638b397d0f31154356a.png" data-type="png" data-w="341" style="width: 160px;margin: 0px auto;display: block;"> <br> </section> <p style="text-align: center;line-height: 25.6px;font-size: 14px;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;">架构文摘</strong></span></p> <p style="text-align: center;line-height: 25.6px;font-size: 14px;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;">ID:ArchDigest</span></p> <p style="text-align: center;line-height: 25.6px;font-size: 14px;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;">互联网应用架构丨架构技术丨大型网站丨大数据</span></p> <p style="text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="1.0505836575875487" data-s="300,640" src="/upload/34c06f9af7df907d751d410136379287.png" data-type="png" data-w="257" style="width: 163px;height: 171px;"></p> <p style="text-align: center;white-space: normal;min-height: 1em;max-width: 100%;background-color: rgb(255, 255, 255);overflow-wrap: break-word;margin-left: 8px;margin-right: 8px;box-sizing: border-box !important;"><span style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word;"><span style="color: rgb(255, 255, 255);line-height: 25.6px;font-family: 宋体;font-size: 12px;max-width: 100%;background-color: rgb(79, 97, 40);">更多精彩文章,请点击下方:</span><span style="color: rgb(255, 255, 255);line-height: 25.6px;font-family: 宋体;font-size: 12px;max-width: 100%;background-color: rgb(192, 0, 0);">阅读原文</span></span></p>
作者:微信小助手
<section style="box-sizing: border-box;"> <section class="V5" style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;box-sizing: border-box;background-color: rgb(239, 239, 239);"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;"> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">网易考拉(以下简称考拉)是网易旗下以跨境业务为主的综合型电商,自 2015 年 1 月 9 日上线公测后,业务保持了高速增长,这背后离不开其技术团队的支撑。</span></p> </section> <section style="clear: both;box-sizing: border-box;"></section> </section> </section> </section> </section> <p style="line-height: 1.75em;"><br></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="" data-copyright="0" data-ratio="0.5599415204678363" data-s="300,640" src="/upload/f0ae1707bc36745b7370ef90bbb3f977.
作者:微信小助手
<section style="margin-top: -1px;white-space: normal;max-width: 100%;background: rgb(238, 239, 239);border-radius: 4px;height: 40px;line-height: 40px;text-indent: 0.5rem;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(110, 109, 109);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击上方<span style="max-width: 100%;color: rgb(96, 127, 166);">“ITeye”</span>关注我们</span> </section> <p style="white-space: normal;"><span style="font-size: 15px;"> </span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">今天我们分析一下 spring 的 IOC,梳理一下 IOC 和 DI 的概念与原理。在网上看到开涛有篇文章写的不错,提取其中一部分精华内容并做一些解读。</span></p> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">1.1.IOC是什么?</span></h1> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。</span>在Java开发中,<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。</span></span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">●<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">谁控制谁,控制什么:</span>传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">。</span></span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">提到控制就要理解控制的含义,控制就是对象的创建、初始化、销毁。创建对象,原来是 new 一个,现在给 Spring 容器创建了;对象初始化,比如 A 依赖 B,原来是我们通过构造器或者 setter 方法赋值,现在给 Spring 容器自动注入了;销毁对象,原来是我们直接赋值 null 或者做一些销毁操作,现在给 Spring 容器管理生命周期负责销毁。明白了吧,IOC 解决了繁琐的对象生命周期的操作,解耦了我们的代码。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">●<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">为何是反转,哪些方面反转了:</span>有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。</span></span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">反转的是什么?反转的是控制权。前面提到 Spring 控制了对象的生命周期,那么对象的控制就完全脱离了我们的控制,交给了 Spring。这个反转是指,我们由对象的控制者变成了 IOC 的被动接受者。我们无法决定对象生命周期的任何一个阶段,最多是借助于 Spring 的扩展机制做一些微小的动作,我们甚至无法预判依赖的对象真正被注入的是哪一个。反转好比你家的机器人决定了你的生活节奏,必须听他的。</span></p> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">1.2.IOC能做什么?</span></h1> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们设计出松耦合、更优良的程序。把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">借助 IOC 容器完美解决了耦合问题,甚至可以让八竿子打不着的类型产生注入关系。比如二方包 a 里面有个类型 A1,三方包 b 里面有个类型 B1,这两个都是 readOnly 的,你不可能去创建或修改内部的依赖。但是借助于 IOC,可以把我们自己的类 C1 注入进去,让 A1、B1 依赖于 C1,从而改变二方包的行为。这也是大型企业级开发中 IOC 比较常见的用法。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">其实<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。</span></span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">在 IOC 模式下,设计流程变成了真正的无关业务完全独立的流程化设计。你只需要设计良好的流程和依赖,定义出需要什么,然后把控制权交给 Spring 即可。Spring 给你什么对象,你就用什么对象,不要对对象做任何的假设,也不要期待对象有什么特性,只需要等待 Spring 提供对象即可。控制反转就像乔布斯的理念,我告诉你你需要什么。</span></p> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">1.3.IOC和DI</span></h1> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">DI—Dependency Injection,即“依赖注入”</span>:<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">组件之间依赖关系</span>由容器在运行期决定,形象的说,即<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">由容器动态的将某个依赖关系注入到组件之中</span>。<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。</span>通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">依赖注入是一种实现,而 IOC 是一种设计思想。从 IOC 到 DI,就是从理论到了实践。你把依赖交给了容器,容器帮你管理依赖,这就是依赖注入的核心。越是大型的项目,越难以管理依赖关系,开发工作逐渐变化为一个个节点的开发,而这些节点通过依赖注入关联起来。依赖注入降低了开发的成本、提高了代码的复用率、提高了软件的灵活性,也给软件开发带来了挑战,你根本不知道运行时容器会给你什么。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">●<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">谁依赖于谁:</span>当然是<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">应用程序依赖于IoC容器</span>;</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">●<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源</span>;</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">●<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">谁注入谁:</span>很明显是<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">IoC容器注入应用程序某个对象,应用程序依赖的对象</span>;</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">●注入了什么:</span>就是<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">注入某个对象所需要的外部资源(包括对象、资源、常量数据)</span>。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">DI 即依赖注入,重点就在于 “依赖”、“注入” 两个概念。什么是依赖?对象运行所需要的外部的数据、资源就是依赖,没有这些东西对象不能完成业务处理,必须拿到才能运行。什么是注入?注入这个词真的很形象,就像打针一样,从外部注入到内部,容器加载了外部的文件、URL、配置和对象然后把这些数据、对象按需注入给对象。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">IoC和DI</span>由什么<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">关系</span>呢?其实它们<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">是同一个概念的不同角度描述</span>,由于控制反转概念比较含糊,所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,<span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。</span></span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">解读:</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">IOC 和 DI 是同一个概念的不同角度描述,但实际上又是有区别的。IOC 强调的是容器和对象的控制权发生了反转,而 DI 强调的是对象的依赖由容器进行注入,大部分情况下说两者相同也不算错。 但是广义上 IOC 是一种软件开发模式,也就是说还可以通过别的方式实现,而 DI 只是其中一种,Spring 选择了 DI 从而使 DI 在 Java 开发中深入人心。</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"><br></span></p> <hr style="white-space: normal;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section label="Copyright © 2016 playhudong All Rights Reserved." style="margin-right: auto;margin-left: auto;white-space: normal;max-width: 100%;width: 20em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;width: 320px;text-align: center;line-height: 1.5em;font-size: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">想了解更多?那就赶紧来关注我们</span></p> </section> <section style="margin-top: 1em;margin-bottom: 1em;max-width: 100%;width: 320px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img title="https://image.ipaiban.com/upload-ueditor-image-20180627-1530029388314035035.jpg" class="" data-ratio="1" data-type="jpeg" data-w="1280" src="/upload/49126aae7a67399241ae1fc5cfc94372.jpg" style="display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 160px !important;visibility: visible !important;"> </section> <section class="" style="max-width: 100%;width: 320px;text-align: center;border-top: 2px solid rgb(253, 208, 39);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section class="" style="max-width: 100%;background: rgb(253, 208, 39);display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-right: 0.5em;max-width: 100%;width: 0px;height: 0px;border-top: 1.6em solid transparent;border-left: 0.5em solid rgb(255, 255, 255);float: left;display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"></section> <section style="max-width: 100%;width: auto;color: rgb(255, 255, 255);line-height: 1em;font-size: 0.87em;display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">长按二维码 关注我们</span></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> </section> </section> </section> </section> <p><br></p> <p><br></p>
作者:演戏
Mycat 是什么?从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了 MySQL 协议的 的 Server,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以 用 MySQL 原生(Native)协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通 信,其核心功能是分表分库,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他数 据库里。 Mycat 发展到目前的版本, 已经不是一个单纯的 MySQL 代理了, 它的后端可以支持 MySQL、 SQL Server、 Oracle、DB2、PostgreSQL 等主流数据库,也支持 MongoDB 这种新型 NoSQL 方式的存储,未来还会支持更多 类型的存储。而在最终用户看来,无论是那种存储方式,在 Mycat 里,都是一个传统的数据库表,支持标 准的 SQL 语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度, 在测试阶段,可以将一个表定义为任何一种 Mycat 支持的存储方式,比如 MySQL 的 MyASIM 表、内存表、 或者 MongoDB、 LevelDB 以及号称是世界上最快的内存数据库 MemSQL 上。 试想一下, 用户表存放在 MemSQL 上,大量读频率远超过写频率的数据如订单的快照数据存放于 InnoDB 中,一些日志数据存放于 MongoDB 中,而且还能把 Oracle 的表跟 MySQL 的表做关联查询,你是否有一种不能呼吸的感觉?而未来,还能通过 Mycat 自动将一些计算分析后的数据灌入到 Hadoop 中,并能用 Mycat+Storm/Spark Stream 引擎做大规模数 据分析,看到这里,你大概明白了,Mycat 是什么?Mycat 就是 BigSQL,Big Data On SQL Database。 对于 DBA 来说,可以这么理解 Mycat: Mycat 就是 MySQL Server, 而 Mycat 后面连接的 MySQL Server, 就好象是 MySQL 的存储引擎,如 InnoDB, MyISAM 等,因此,Mycat 本身并不存储数据,数据是在后端的 MySQL 上存储的,因此数据可靠性以及事务 等都是 MySQL 保证的, 简单的说, Mycat 就是 MySQL 最佳伴侣, 它在一定程度上让 MySQL 拥有了能跟 Oracle PK 的能力。 对于软件工程师来说,可以这么理解 Mycat: Mycat 就是一个近似等于 MySQL 的数据库服务器,你可以用连接 MySQL 的方式去连接 Mycat(除了端 口不同,默认的 Mycat 端口是 8066 而非 MySQL 的 3306,因此需要在连接字符串上增加端口信息) ,大多数 情况下,可以用你熟悉的对象映射框架使用 Mycat,但建议对于分片表,尽量使用基础的 SQL 语句,因为这 样能达到最佳性能,特别是几千万甚至几百亿条记录的情况下。 对于架构师来说,可以这么理解 Mycat: 31 Mycat 是一个强大的数据库中间件,不仅仅可以用作读写分离、以及分表分库、容灾备份,而且可以用 于多租户应用开发、云平台基础设施、让你的架构具备很强的适应性和灵活性,借助于即将发布的 Mycat 智能优化模块,系统的数据访问瓶颈和热点一目了然,根据这些统计分析数据,你可以自动或手工调整后 端存储,将不同的表映射到不同存储引擎上,而整个应用的代码一行也不用改变。 当前是个大数据的时代,但究竟怎样规模的数据适合数据库系统呢?对此,国外有一个数据库领域的 权威人士说了一个结论:千亿以下的数据规模仍然是数据库领域的专长,而 Hadoop 等这种系统,更适合的 是千亿以上的规模。所以,Mycat 适合 1000 亿条以下的单表规模,如果你的数据超过了这个规模,请投靠 Mycat Plus 吧! #### ## MYCAT 原理 Mycat 的原理并不复杂,复杂的是代码,如果代码也不复杂,那么早就成为一个传说了。Mycat 的原理 中最重要的一个动词是 “拦截” , 它拦截了用户发送过来的 SQL 语句, 首先对 SQL 语句做了一些特定的分析: 如分片分析、路由分析、读写分离分析、缓存分析等,然后将此 SQL 发往后端的真实数据库,并将返回的 结果做适当的处理,最终再返回给用户。  上述图片里,Orders 表被分为三个分片 datanode(简称 dn),这三个分片是分布在两台 MySQL Server 上(DataHost),即 datanode=database@datahost 方式,因此你可以用一台到 N 台服务器来分片,分片规则为 (sharding rule)典型的字符串枚举分片规则,一个规则的定义是分片字段(sharding column)+分片函数(rule function),这里的分片字段为 prov 而分片函数为字符串枚举方式。 当 Mycat 收到一个 SQL 时, 会先解析这个 SQL, 查找涉及到的表, 然后看此表的定义, 如果有分片规则, 则获取到 SQL 里分片字段的值,并匹配分片函数,得到该 SQL 对应的分片列表,然后将 SQL 发往这些分片 去执行,最后收集和处理所有分片返回的结果数据,并输出到客户端。以 select * from Orders where prov=? 语句为例,查到 prov=wuhan,按照分片函数,wuhan 返回 dn1,于是 SQL 就发给了 MySQL1,去取 DB1 上 的查询结果,并返回给用户。 如果上述 SQL 改为 select * from Orders where prov in ( ‘wuhan’ , ‘beijing’ ), 那么, SQL 就会发给 MySQL1 与 MySQL2 去执行,然后结果集合并后输出给用户。但通常业务中我们的 SQL 会有 Order By 以及 Limit 翻页 语法,此时就涉及到结果集在 Mycat 端的二次处理,这部分的代码也比较复杂,而最复杂的则属两个表的 Jion 问题,为此,Mycat 提出了创新性的 ER 分片、全局表、HBT(Human Brain Tech)人工智能的 Catlet、以 及结合 Storm/Spark 引擎等十八般武艺的解决办法,从而成为目前业界最强大的方案,这就是开源的力量!
作者:微信小助手
<section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;box-sizing: border-box;background-color: rgb(239, 239, 239);"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;" title="" class="horizontal-tb" opera-tn-ra-cell="_$.pages:0.layers:0.comps:0.txt1"> <section style="box-sizing: border-box;"> “ </section></span> <section class="horizontal-tb" style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">一个复杂的系统往往都是从一个小而简的系统发展衍化而来,为了满足日益增长的业务需求,不断的增加系统的复杂度,从单体架构逐步发展为分布式架构,而分布式系统架构的设计主要关注:高性能,高可用,高拓展。</span></p> </section> <section style="clear: both;box-sizing: border-box;"></section> </section> </section> </section> <section style="line-height: 1.75em;"> <br> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;"><img class="rich_pages" data-ratio="0.66640625" data-s="300,640" src="/upload/3342f5ab9e7dd01e806275cdb5ad5bef.jpg" data-type="jpeg" data-w="1280" style=""></p> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em>图片来自 Pexels</em></span> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section class="horizontal-tb" style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="line-height: 1.2;box-sizing: border-box;">分布式事务</span></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">高可用是指系统无中断的执行功能的能力,代表了系统的可用程度,是进行系统设计时必须要遵守的准则之一。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">而高可用的实现方案,无外乎就是冗余,就存储的高可用而言,问题不在于如何进行数据备份,而在于如何规避数据不一致对业务造成的影响。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">对于分布式系统而言,要保证分布式系统中的数据一致性就需要一种方案,可以保证数据在子系统中始终保持一致,避免业务出现问题。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种实现方案就叫做分布式事务,要么一起成功,要么一起失败,必须是一个整体性的事务。</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="transform: rotate(0deg);-webkit-transform: rotate(0deg);-moz-transform: rotate(0deg);-o-transform: rotate(0deg);box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;"> <section class="horizontal-tb" style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="line-height: 1.2;box-sizing: border-box;"></span></p> <p class="heading" style="box-sizing: border-box;">理论基础</p> </section> </section> </section> </section> <p><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"> 在讲解具体方案之前,有必要了解一下分布式中数据设计需要遵循的理论基础,CAP 理论和 BASE 理论,为后面的实践铺平道路。</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section class="horizontal-tb" style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="heading" style="box-sizing: border-box;"><strong>CAP 理论</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(71, 193, 168);font-size: 15px;letter-spacing: 1px;">CAP,Consistency Availability Partition tolerance 的简写:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Consistency:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">一致性,</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">对某个客户端来说,读操作能够返回最新的写操作结果。</span></p></li> <li><p><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Availability:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可用性,</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">非故障节点在合理的时间内返回合理的响应。</span></p></li> <li><p><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Partition tolerance:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">分区容错性,</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">当出现网络分区后,系统能够继续提供服务,你知道什么是网络分区吗?</span></p></li> </ul> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">因为分布式系统中系统肯定部署在多台机器上,无法保证网络做到 100% 的可靠,所以网络分区一定存在,即 P 一定存在。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在出现网络分区后,就出现了可用性和一致性的问题,我们必须要在这两者之间进行取舍,</span> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">因此就有了两种架构:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">CP 架构</span></strong></p></li> <li><p><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">AP 架构</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p></li> </ul> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <section style="line-height: normal;"> <br> </section> <h4 class="heading" data-id="heading-3" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①CP 架构</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></h4> <p style="line-height: normal;"><br></p> <p style="line-height: normal;text-align: center;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.7949367088607595" data-s="300,640" src="/upload/57ae9f3221dd4fac4f47547739e7c654.png" data-type="png" data-w="395" style="line-height: 29.75px;white-space: normal;"></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当没有出网络分区时,系统 A 与系统 B 的数据一致,X=1。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">将系统 A 的 X 修改为 2,X=2。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当出现网络分区后,系统 A 与系统 B 之间的数据同步数据失败,系统 B 的 X=1。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当客户端请求系统 B 时,为了保证一致性,此时系统 B 应拒绝服务请求,返回错误码或错误信息。</span></p></li> </ul> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面这种方式就违背了可用性的要求,只满足一致性和分区容错,即 CP,</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">CAP 理论是忽略网络延迟,从系统 A 同步数据到系统 B 的网络延迟是忽略的。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">CP 架构保证了客户端在获取数据时一定是最近的写操作,或者获取到异常信息,绝不会出现数据不一致的情况。</span> </section> <section style="line-height: normal;"> <br> </section> <h4 class="heading" data-id="heading-4" style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②AP 架构</span></strong></h4> <section style="line-height: normal;"> <br> </section> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.8412698412698413" data-s="300,640" src="/upload/86906f3020a33203de5853aaf0cf777a.png" data-type="png" data-w="378" style="line-height: 29.75px;white-space: normal;"> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">当网络分区出现后,为了保证可用性,系统 B 可以返回旧值,保证系统的可用性:</span> </section> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当没有出网络分区时,系统 A 与系统 B 的数据一致,X=1。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">将系统 A 的 X 修改为 2,X=2。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当出现网络分区后,系统 A 与系统 B 之间的数据同步数据失败,系统 B 的 X=1。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当客户端请求系统 B 时,为了保证可用性,此时系统 B 应返回旧值,X=1。</span></p></li> </ul> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面这种方式就违背了一致性的要求,只满足可用性和分区容错,即 AP,</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">AP 架构保证了客户端在获取数据时无论返回的是最新值还是旧值,系统一定是可用的。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">CAP 理论关注粒度是数据,而不是整体系统设计的策略。</span> </section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section class="horizontal-tb" style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p class="heading" style="box-sizing: border-box;"><strong>BASE 理论</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"> BASE 理论指的是基本可用 Basically Available,软状态 Soft State,最终一致性 Eventual Consistency,核心思想是即便无法做到强一致性,但应该采用适合的方式保证最终一致性。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="color: rgb(71, 193, 168);font-size: 15px;letter-spacing: 1px;">BASE,Basically Available Soft State Eventual Consistency 的简写:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">BA:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Basically Available 基本可用,</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。</span></p></li> <li><p><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">S:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Soft State 软状态,</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">允许系统�
作者:微信小助手
<section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;box-sizing: border-box;background-color: rgb(239, 239, 239);"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;" title="" opera-tn-ra-cell="_$.pages:0.layers:0.comps:0.txt1"> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">学过数据结构都知道二叉树的概念,而又有多种比较常见的二叉树类型,比如完全二叉树、满二叉树、二叉搜索树、均衡二叉树、完美二叉树等。</span></p> </section> <section style="clear: both;box-sizing: border-box;"></section> </section> </section> </section> <section style="line-height: 1.75em;"> <br> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.7394695787831513" data-s="300,640" src="/upload/4c30337df0cc272aaf4e9037463cd104.png" data-type="png" data-w="641" style=""> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em>图片来自 Pexels</em></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">今天我们要说的红黑树就是就是一棵非严格均衡的二叉树,均衡二叉树又是在二叉搜索树的基础上增加了自动维持平衡的性质,插入、搜索、删除的效率都比较高。红黑树也是实现 TreeMap 存储结构的基石。</span></p> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">二叉搜索树</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">二叉搜索树又叫二叉查找树、二叉排序树,我们先看一下典型的二叉搜索树,这样的二叉树有何规则特点呢?</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">二叉搜索树有如下几个特点:</span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">节点的左子树小于节点本身</span></strong></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">节点的右子树大于节点本身</span></strong></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">左右子树同样为二叉搜索树</span></strong></p></li> </ul> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">下图就是一棵典型的二叉搜索树:</span> </section> <p style="text-align: center;line-height: 1.75em;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.3397590361445783" data-s="300,640" src="/upload/f53b13d2c6ab588329a337a98d4807a0.png" data-type="png" data-w="1660" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">二叉搜索树是均衡二叉树的基础,我们看一下它的搜索步骤如何。</span><span style="font-size: 15px;line-height: 1.6;color: rgb(89, 89, 89);letter-spacing: 1px;">我们要从二叉树中找到值为 58 的节点。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">第一步:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先查找到根节点,值为 60 的节点。</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.3397590361445783" data-s="300,640" src="/upload/53c1039a02d28d0101fb772ad562200a.png" data-type="png" data-w="1660" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">第二步:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">比较我们要找的值 58 与该节点的大小。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果等于,那么恭喜,已经找到;</span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果小于,继续找左子树;如果大于,那么找右子树。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">很明显 58<60,因此我们找到左子树的节点 56,此时我们已经定位到了节点 56。</span> </section> <p style="text-align: center;line-height: 1.75em;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.3397590361445783" data-s="300,640" src="/upload/fbe91448323705b26bb511a7b69cc5e7.png" data-type="png" data-w="1660" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">第三步:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">按照第二步的规则继续找。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">58>56 我们需要继续找右子树,定位到了右子树节点 58,恭喜,此时我们已经找到了。</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.3397590361445783" data-s="300,640" src="/upload/4e2d2b5ae520ce5776de038c3c8908f3.png" data-type="png" data-w="1660" style=""> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们经过三步就已经找到了,其实就是我们平时所说的二分查找,这种二叉搜索树好像查找效率很高,但同样它也有缺陷,如下面这样的二叉搜索树。</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.775974025974026" data-s="300,640" src="/upload/ae5ed69357ab7e9279300794da505a83.png" data-type="png" data-w="616" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">看到这样的二叉搜索树是否很别扭,典型的大长腿瘸子,但它也是二叉搜索树,如果我们要找值为 50 的节点,基本上和单链表查询没多大区别了,性能将大打折扣。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这个时候我们的均衡二叉树就粉墨登场了,均衡二叉树就是在二叉搜索树的基础上添加了自动维持平衡的性质。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面的大长腿瘸子二叉搜索树经过自动平衡后,可能就成为了下面这样的二叉树。</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.5934256055363322" data-s="300,640" src="/upload/f55190a3cf5d1817cca161a27f587698.png" data-type="png" data-w="578" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">经过了自动平衡,再去找值为 50 的节点,查找性能将提升很多。红黑树就是非严格均衡的二叉搜索树。</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">红黑树规则特点</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">红黑树具体有哪些规则特点呢?具体如下:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">节点分为红色或者黑色。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">根节点必为黑色。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">叶子节点都为黑色,且为 null。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">连接红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点)。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">从任意节点出发,到其每个叶子节点的路径中包含相同数量的黑色节点。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">新加入到红黑树的节点为红色节点。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">规则看着好像挺多,没错,因为红黑树也是均衡二叉树,需要具备自动维持平衡的性质,上面的 6 条就是红黑树给出的自动维持平衡所需要具备的规则。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们看一看一个典型的红黑树到底是什么样儿?</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.3779963122311002" data-s="300,640" src="/upload/b894194e6b5cf6c681e3dc44a6921c8b.png" data-type="png" data-w="1627" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">首先解读一下规则,除了字面上看到的意思,还隐藏了哪些意思呢?</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①从根节点到叶子节点的最长路径不大于最短路径的 2 倍</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">怎么样的路径算最短路径?</span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">从规则 5 中,我们知道从根节点到每个叶子节点的黑色节点数量是一样的,那么纯由黑色节点组成的路径就是最短路径。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">什么样的路径算是最长路径?</span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">根据规则 4 和规则 3,若有红色节点,则必然有一个连接的黑色节点,当红色节点和黑色节点数量相同时,就是最长路径,也就是黑色节点(或红色节点)*2。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②为什么说新加入到红黑树中的节点为红色节点</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">从规则 4 中知道,当前红黑树中从根节点到每个叶子节点的黑色节点数量是一样的,此时假如新的是黑色节点的话,必然破坏规则。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但加入红色节点却不一定,除非其父节点就是红色节点,因此加入红色节点,破坏规则的可能性小一些,下面我们也会举例来说明。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">什么情况下,红黑树的结构会被破坏呢?破坏后又怎么维持平衡,维持平衡主要通过两种方式【变色】和【旋转】,【旋转】又分【左旋】和【右旋】,两种方式可相互结合。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">下面我们从插入和删除两种场景来举例说明。</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">红黑树节点插入</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">当我们插入值为 66 的节点时,红黑树变成了这样:</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.3803076923076923" data-s="300,640" src="/upload/fbb0ff8e1729e79f6c37941ddbc887d8.png" data-type="png" data-w="1625" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">很明显,这个时候结构依然遵循着上述 6 大规则,无需启动自动平衡机制调整节点平衡状态。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="line-height: 1.6;font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">如果再向里面插入值为 51 的节点,这个时候红黑树变成了这样:</span> <span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-copyright="0" data-ratio="0.4566153846153846" data-s="300,640" src="/upload/4c876ba539ae7af1daf5fe91a2a404a.png" data-type="png" data-w="1625" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">很明显现在的结构不遵循规则 4 了,这个时候就需要启动自动平衡机制调整节点平衡状态。</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>变色</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">我们可以通过变色的方式,使结构满足红黑树的规则:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先解决结构不遵循规则 4 这一点(红色节点相连,节点 49-51),需将节点 49 改为黑色。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">此时我们发现又违反了规则 5(56-49-51-XX 路径中黑色节点超过了其他路径),那么我们将节点 45 改为红色节点。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">哈哈,妹的,又违反了规则 4(红色节点相连,节点 56-45-43),那么我们将节点 56 和节点 43 改为黑色节点。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但是我们发现此时又违反了规则 5(60-56-XX 路径的黑色节点比 60-68-XX 的黑色节点多),因此我们需要调整节点 68 为黑色。</span></p></li> <li><p style="margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">完成!</span></p></li> </ul> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <section style="text-align: justify;line-height: 1.75em;"></section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.3082965144820815" data-s="300,640" src="/upload/7ff0efe2afaf36a6fe6036d9dedccf35.png" data-type="png" data-w="2037" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">最终调整完成后的树为:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.4566153846153846" data-s="300,640" src="/upload/37557720bbc8c287037e4cdf71ca4673.png" data-type="png" data-w="1625" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但并不是什么时候都那么幸运,可以直接通过变色就达成目的,大多数时候还需要通过旋转来解决。</span> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="color: rgb(71, 193, 168);font-size: 15px;letter-spacing: 1px;">如在下面这棵树的基础上,加入节点 65:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.3803076923076923" data-s="300,640" src="/upload/fbb0ff8e1729e79f6c37941ddbc887d8.png" data-type="png" data-w="1625" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">插入节点 65 后进行以下步骤:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.3938080495356037" data-s="300,640" src="/upload/d331016956311c4553406a222051c94d.png" data-type="png" data-w="1615" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这个时候,你会发现对于节点 64 无论是红色节点还是黑色节点,都会违反规则 5,路径中的黑色节点始终无法达成一致,这个时候仅通过【变色】已经无法达成目的。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们需要通过旋转操作,当然【旋转】操作一般还需要搭配【变色】操作。</span> <span style="font-size: 15px;line-height: 1.6;color: rgb(89, 89, 89);letter-spacing: 1px;">旋转包括【左旋】和【右旋】。</span> </section> <p style="line-height: normal;"><br></p> <h5 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">左旋:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">逆时针旋转两个节点,让一个节点被其右子节点取代,而该节点成为右子节点的左子节点。</span></h5> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">左旋操作步骤如下:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先断开节点 PL 与右子节点 G 的关系,同时将其右子节点的引用指向节点 C2;然后断开节点 G 与左子节点 C2 的关系,同时将 G 的左子节点的应用指向节点 PL。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.16630196936542668" data-s="300,640" src="/upload/af96f67cd88bce7b4f7caa34bb5715f7.png" data-type="png" data-w="1828" style=""></p> <h5 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">右旋:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">顺时针旋转两个节点,让一个节点被其左子节点取代,而该节点成为左子节点的右子节点。</span></h5> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">右旋操作步骤如下:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">首先断开节点 G 与左子节点 PL 的关系,同时将其左子节点的引用指向节点 C2;然后断开节点 PL 与右子节点 C2 的关系,同时将 PL 的右子节点的应用指向节点 G。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.16231732776617955" data-s="300,640" src="/upload/22ea12ad8656416ff44bffdeca0c4c9c.png" data-type="png" data-w="1916" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">无法通过变色而进行旋转的场景分为以下四种:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>左左节点旋转</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种情况下,父节点和插入的节点都是左节点,如下图(旋转原始图1)这种情况下,我们要插入节点 65。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">规则如下:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">以祖父节点【右旋】,搭配【变色】。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.608421052631579" data-s="300,640" src="/upload/ceef80f37a2df5ef573dafdbae35da09.png" data-type="png" data-w="475" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">按照规则,步骤如下:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="line-height: 1.6;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.21136865342163355" data-s="300,640" src="/upload/50da8568ae001ed9343d0d03614349bc.png" data-type="png" data-w="1812" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>左右节点旋转</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种情况下,父节点是左节点,插入的节点是右节点,在旋转原始图 1 中,我们要插入节点 67。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">规则如下:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">先父节点【左旋】,然后祖父节点【右旋】,搭配【变色】。</span> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">按照规则,步骤如下:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.16943231441048034" data-s="300,640" src="/upload/e3b6a787f4d45304fdfe562e611a0465.png" data-type="png" data-w="2290" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>右左节点旋转</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种情况下,父节点是右节点,插入的节点是左节点,如下图(旋转原始图 2<span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 29.75px;">)</span>这种情况,我们要插入节点 68。</span> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">规则如下:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">先父节点【右旋】,然后祖父节点【左旋】,搭配【变色】。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.8921568627450981" data-s="300,640" src="/upload/efb9df09fae9c39cfea78f94215ac689.png" data-type="png" data-w="306" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">按照规则,步骤如下:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.18618324350808427" data-s="300,640" src="/upload/730042aded49ca1bd0fcbb5caa07af66.png" data-type="png" data-w="2041" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>右右节点旋转</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种情况下,父节点和插入的节点都是右节点,在旋转原始图 2 中,我们要插入节点 70。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">规则如下:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">以祖父节点【左旋】,搭配【变色】。</span> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">按照规则,步骤如下:</span><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.21932424422050978" data-s="300,640" src="/upload/1595de766c7df1d4540ff02477163b15.png" data-type="png" data-w="1687" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>红黑树插入总结</strong></p> </section> </section> </section> <h3 style="line-height: normal;"><br></h3> <h3 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;line-height: 1.75em;color: rgb(71, 193, 168);">红黑树插入总结如下图:</span></h3> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.18585858585858586" data-s="300,640" src="/upload/6d541c58f082976c42793aeba323e5bc.png" data-type="png" data-w="990" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">红黑树节点删除</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">相比较于红黑树的节点插入,删除节点更为复杂,我们从子节点是否为 null 和红色为思考维度来讨论。</span> </section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>子节点至少有一个为 null</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">当待删除的节点的子节点至少有一个为 null 节点时,删除了该节点后,将其有值的节点取代当前节点即可。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">若都为 null,则将当前节点设置为 null,当然如果违反规则了,则按需调整,如【变色】以及【旋转】。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.36700829673011226" data-s="300,640" src="/upload/35df4e6e4ddc708a4c4a095cf94edb95.png" data-type="png" data-w="2049" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>子节点都是非 null 节点</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这种情况下,</span> <span style="line-height: 1.75em;font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">第一步:找到该节点的前驱或者后继。</span> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">前驱:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">左子树中值最大的节点(可得出其最多只有一个非 null 子节点,可能都为 null)。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">后继:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">右子树中值最小的节点(可得出其最多只有一个非 null 子节点,可能都为 null)。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">前驱和后继都是值最接近该节点值的节点,类似于该节点.prev=前驱,该节点.next=后继。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">第二步:将前驱或者后继的值复制到该节点中,然后删掉前驱或者后继。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果删除的是左节点,则将前驱的值复制到该节点中,然后删除前驱;如果删除的是右节点,则将后继的值复制到该节点中,然后删除后继。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这相当于是一种“取巧”的方法,我们删除节点的目的是使该节点的值在红黑树上不存在。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">因此专注于该目的,我们并不关注删除节点时是否真是我们想删除的那个节点,同时我们也不需考虑树结构的变化,因为树的结构本身就会因为自动平衡机制而经常进行调整。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">前面我们已经说了,我们要删除的实际上是前驱或者后继,因此我们就以前驱为主线来讲解。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">后继的学习可参考前驱,包括下面几种情况:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <p style="line-height: normal;"><br></p> <h4 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①前驱为黑色节点,并且有一个非 null 子节点</span></strong></h4> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.13406292749658003" data-s="300,640" src="/upload/7420d72340d5d5e9b3a8160258f6be84.png" data-type="png" data-w="3655" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">分析:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> <span style="font-size: 15px;line-height: 1.6;color: rgb(89, 89, 89);letter-spacing: 1px;">因为要删除的是左节点 64,找到该节点的前驱 63;然后用前驱的值 63替换待删除节点的值 64,此时两个节点(待删除节点和前驱)的值都为 63;</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">删除前驱 63,此时成为上图过程中间环节,但我们发现其不符合红黑树规则 4,因此需要进行自动平衡调整。</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">这里直接通过【变色】即可完成。</span> </section> <p style="line-height: normal;"><br></p> <h4 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②前驱为黑色节点,同时子节点都为 null</span></strong></h4> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.2002027369488089" data-s="300,640" src="/upload/d3f00f08041ddf35df740fa41a4aba38.png" data-type="png" data-w="1973" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">分析:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> <span style="font-size: 15px;line-height: 1.6;color: rgb(89, 89, 89);letter-spacing: 1px;">因为要删除的是左节点 64,找到该节点的前驱 63;然后用前驱的值 63 替换待删除节点的值 64,此时两个节点(待删除节点和前驱)的值都为 63。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">删除前驱 63,此时成为上图过程中间环节,但我们发现其不符合红黑树规则 5,因此需要进行自动平衡调整。</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;line-height: 1.75em;">这里直接通过【变色】即可完成。</span> </section> <p style="line-height: normal;"><br></p> <h4 style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">③前驱为红色节点,同时子节点都为 null</span></strong></h4> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-copyright="0" data-ratio="0.23232323232323232" data-s="300,640" src="/upload/d9d4d8365281f16778709f02c65a04fc.png" data-type="png" data-w="1683" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">分析:</span></strong> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> <span style="font-size: 15px;line-height: 1.6;color: rgb(89, 89, 89);letter-spacing: 1px;">因为要删除的是左节点 64,找到该节点的前驱 63;然后用前驱的值 63替换待删除节点的值 64,此时两个节点(待删除节点和前驱)的值都为 63;删除前驱 63,树的结构并没有打破规则。</span> </section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="width: 0.6em;display: inline-block;vertical-align: middle;box-sizing: border-box;"> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.2;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <span style="width: 0.6em;height: 0.6em;display: block;opacity: 0.6;margin-top: 2px;margin-bottom: 2px;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> <strong><span style="width: 0.6em;height: 0.6em;display: block;opacity: 1;box-sizing: border-box;background-color: rgb(89, 89, 89);"></span> </strong> </section> <section style="display: inline-block;vertical-align: middle;font-size: 18px;padding-left: 5px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><strong>红黑树删除总结</strong></p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">红黑树删除的情况比较多,但也就存在以下情况:</span> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;"></span> </section> <ul class=" list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">删除的是根节点,则直接将根节点置为 null。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">待删除节点的左右子节点都为 null,删除时将该节点置为 null。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">待删除节点的左右子节点有一个有值,则用有值的节点替换该节点即可。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">待删除节点的左右子节点都不为 null,则找前驱或者后继,将前驱或者后继的值复制到该节点中,然后删除前驱或者后继。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">节点删除后可能会造成红黑树的不平衡,这时我们需通过【变色】+【旋转】的方式来调整,使之平衡,上面也给出了例子,建议大家多多练习,而不必背下来。</span></p></li> </ul> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"></section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom-width: 6px;border-bottom-style: solid;border-color: rgb(89, 89, 89);margin-bottom: -1px;font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">总结</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">本文主要介绍了红黑树的相关原理,首先红黑树的基础二叉搜索树,我们先简单说了一下二叉搜索树,并且讲了一下搜索的流程。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">然后就针对红黑树的六大规则特点,红黑树的插入操作,删除操作,都使用了大量的图形来加以说明。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">技术都是练出来的,有时候很多似是而非的地方,当动笔去写的时候,其实很好理解。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">红黑树的使用非常广泛,如 TreeMap 和 TreeSet 都是基于红黑树实现的,而 JDK8 中 HashMap 当链表长度大于 8 时也会转化为红黑树。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">红黑树比较复杂,本人也是还在学习过程中,如果有不对的地方请批评指正,望共同进步谢谢。</span> </section> <p style="line-height: normal;"><br></p> <section style="white-space: normal;line-height: normal;"> <em style="color: rgb(89, 89, 89);letter-spacing: 1px;line-height: 1.75em;"><span style="font-size: 14px;">作者:梁洪</span></em> <br> </section> <section style="white-space: normal;line-height: normal;"> <em style="color: rgb(89, 89, 89);letter-spacing: 1px;line-height: 1.75em;"><span style="font-size: 14px;">简介:<em style="white-space: normal;color: rgb(89, 89, 89);letter-spacing: 1px;line-height: 1.75em;"><span style="font-size: 14px;">网名工匠初心</span></em>,热爱技术,喜欢钻研与分享,6 年 Java 开发经验,专注于 Java 以及 Spring 生态圈,同时也喜欢研究物联网、大数据、AI 等前沿技术,带过 15 人以下的小团队,做过项目管理,现在是一家软件公司的部门经理。</span></em> </section> <p style="white-space: normal;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;"><em><span style="font-size: 14px;">编辑:陶家龙、孙淑娟</span></em></span><br></p> <p style="white-space: normal;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em>出处:https://www.cnblogs.com/LiaHon/p/11203229.html</em></span></p> <p style="white-space: normal;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em><em style="max-width: 100%;color: rgb(89, 89, 89);font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 14px;letter-spacing: 1px;line-height: 29.75px;white-space: normal;box-sizing: border-box !important;word-wrap: break-word !important;background-color: rgb(255, 255, 255);">征稿:有投稿、寻求报道意向技术人请联络 editor@51cto.com</em></em></span></p> <p style="text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="0.39375" src="/upload/4b473bf28d09c2d07ab6afe478b5ede3.gif" data-type="gif" data-w="640" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="font-size: 15px;border-style: solid;border-width: 0px 0px 1px;color: rgb(89, 89, 89);border-bottom-color: rgba(215, 215, 215, 0.960784);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><strong>精彩文章推荐:</strong></span></p> </section> </section> </section> <section style="line-height: 2em;"> <a href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655822247&idx=1&sn=d65f8646120671b654a9e76e8e4589d6&chksm=bd74ec708a0365666477170c2e40d113986d7a04c8cfdd93c0c73c09f07931bb7a9027872e07&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">傻瓜都能看懂,30张图彻底理解红黑树!</span></a> <br> </section> <section style="line-height: 2em;"> <a href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655823045&idx=1&sn=4b26147c86a456f3dc9e738cad9f5051&chksm=bd74e9128a0360049bac7b6c7d210f682f0361223967fc1642e69c2fe6fed8325fca6398149b&scene=21#wechat_redirect" target="_blank" data-itemshowtype="11" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">为什么MySQL数据库要用B+树存储索引?</span></a> <br> </section> <section style="line-height: 2em;"> <a href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655826147&idx=1&sn=ece0b1912830846414fdf21d96b11a44&chksm=bd74fd348a03742211da706ba8f396cf71fc82bf49d21b9173420c877d0bd9e9333a3bceb152&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">面试不再慌!跟着老司机吃透Spring Cloud</span></a> <br> </section>
作者:じ☆ve宝贝
 1、c程序员看不起c++程序员, c++程序员看不起java程序员, java程序员看不起c#程序员,c#程序员看不起美工, 周末了,美工带着妹子出去约会了…一群SX程序员还在加班! 2、爱情就是他妈这么个过程:确定喜欢的类型是需求分析;初步接触是概要设计,深入接触是详细设计;确定恋爱关系是编写代码;同居就是测试;吵架就是fix bug;上线就是结婚;项目经理离职是丧偶;项目升级是生孩子;项目下线就是他妈的离婚。 3、某游戏公司招了个日本人当主策,上班第一天就对下属说:“我是个加班狂,希望大家配合我。”一个月之后他回日本了,最后一句话是:“你们这样加班是不人道的。” 4、大学毕业三年,几个同学在班群聊天,聊的全是技术,java,xml之类。另一同学家里开厂,早早做上管理者,插不上嘴,心里很不爽,过了半天插了一句:本公司因业务拓展,招聘门卫一名,要求:4年java开发经验!顿时群里安静了。
作者:微信小助手
<section class="xmteditor" style="display:none;" data-tools="新媒体管家" data-label="powered by xmt.cn"></section> <section class="output_wrapper" style="font-size: 15px;color: rgb(62, 62, 62);line-height: 1.8;word-spacing: 2px;letter-spacing: 2px;font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <p style="text-align: center;"><img class="" data-copyright="0" data-cropselx1="0" data-cropselx2="654" data-cropsely1="0" data-cropsely2="278" data-ratio="0.4255555555555556" data-s="300,640" src="/upload/c4d5e49c41c9ee870e66c915e4860a1d.jpg" data-type="jpeg" data-w="900" style="width: 654px;height: 278px;"></p> <h5 style="margin-top: 0.8em;margin-bottom: 0.8em;font-weight: bold;font-size: 1.2em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 2px;white-space: normal;word-spacing: 2px;max-width: 100%;background-color: rgb(255, 255, 255);line-height: inherit;text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(216, 100, 87);box-sizing: border-box !important;overflow-wrap: break-word !important;">第 82 篇原创</span></h5> <p><span style="color: inherit;font-size: inherit;"></span></p> <section class="output_wrapper" style="font-size: 15px;color: rgb(62, 62, 62);line-height: 1.8;word-spacing: 2px;letter-spacing: 2px;font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">今天是 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">0214</strong> ,打乱一下数字就是 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">1024</strong>,程序员最喜欢的一个数字之一。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">当然,除此之外,今天也是一年一度的 <strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">情人节</strong>。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><span style="color: inherit;font-size: inherit;">这个日子肯定少不了表白。那程序员怎么去表白?</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><span style="color: inherit;font-size: inherit;">当然是 </span><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">写---代---码!</strong><br></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;">每到情人节,脑洞大开的程序员们就纷纷出动,想出了各种别出心裁的表白代码。虽然结局不一定美好,但这些也是一种撩妹手段。</p> </section> <h3 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="font-size: inherit;line-height: inherit;display: inline-block;font-weight: normal;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">从古</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;"> </span><br></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">采葛: 一日不见,如三月兮</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.491362763915547" src="/upload/f74cde356f8b3d4856cc407ec8eb4031.jpg" data-type="jpeg" data-w="1042" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="彼采葛兮,一日不见,如三月兮"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 彼采葛兮,一日不见,如三月兮 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">顾城 :《门前》</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.48433420365535246" src="/upload/69d5b8bd374dbc11dd70757b9025f21b.jpg" data-type="jpeg" data-w="1532" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="门前"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 门前 </figcaption> </figure> <h3 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="font-size: inherit;line-height: inherit;display: inline-block;font-weight: normal;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">至今</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;"> </span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">春风十里不如你</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.5834829443447038" src="/upload/f28b6bba7bab8b5ecf2083199f6ef6a1.jpg" data-type="jpeg" data-w="1114" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="春风十里不如你"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 春风十里不如你 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">舒婷:致橡树</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.968609865470852" src="/upload/9ed858e8d2272bef85402dcbb6f60b06.jpg" data-type="jpeg" data-w="1115" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="致橡树"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 致橡树 </figcaption> </figure> <h3 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="font-size: inherit;line-height: inherit;display: inline-block;font-weight: normal;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">一见钟情</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;"> </span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">一见钟情,相濡以沫,不忘初心,真爱永恒</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.6109022556390977" src="/upload/d8efb9252242419fb1bd950103376f49.jpg" data-type="jpeg" data-w="1064" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="一见钟情,相濡以沫,不忘初心,真爱永恒"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 一见钟情,相濡以沫,不忘初心,真爱永恒 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">直到死之前,每天爱你多一点</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.658307210031348" src="/upload/41f30ae421b98d46b8dd2403053048e.jpg" data-type="jpeg" data-w="638" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="直到死之前,每天爱你多一点"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 直到死之前,每天爱你多一点 </figcaption> </figure> <h3 style="color: inherit;line-height: inherit;margin-top: 1.6em;margin-bottom: 1.6em;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="font-size: inherit;line-height: inherit;display: inline-block;font-weight: normal;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">爱你一万年</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;"> </span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">爱你爱到天荒地老</strong></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.4085603112840467" src="/upload/6b521dbd73e4fcdce71a7c2e01cdb06e.jpg" data-type="jpeg" data-w="1028" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="爱你爱到天荒地老"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 爱你爱到天荒地老 </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.7em;margin-bottom: 1.7em;"><strong style="font-size: inherit;line-height: inherit;color: rgb(233, 105, 0);">山无陵, 江水为竭, 冬雷震震, 夏雨雪, 天地合, 乃敢与君绝!</strong><br></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"> <img class="" data-ratio="0.3717948717948718" src="/upload/a21d32dea8e77accdfce6cdbba31602d.jpg" data-type="jpeg" data-w="1872" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="山无陵, 江水为竭, 冬雷震震, 夏雨雪, 天地合, 乃敢与君绝!"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> 山无陵, 江水为竭, 冬雷震震, 夏雨雪, 天地合, 乃敢与君绝! </figcaption> </figure> </section> <p><br></p> <p style="margin-right: 8px;margin-left: 8px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;word-spacing: 2px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);letter-spacing: 0.5px;widows: 1;background-color: rgb(255, 255, 255);line-height: 27px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">今日问题:</strong></p> <p style="margin-right: 8px;margin-left: 8px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;word-spacing: 2px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);letter-spacing: 0.5px;widows: 1;background-color: rgb(255, 255, 255);line-height: 27px;box-sizing: border-box !important;overflow-wrap: break-word !important;">请使用你熟悉的编程语言来写一句情话。</p> <p style="font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;word-spacing: 2px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);letter-spacing: 0.5px;widows: 1;background-color: rgb(255, 255, 255);line-height: 27px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="margin-right: 8px;margin-left: 8px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;word-spacing: 2px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);letter-spacing: 0.5px;widows: 1;background-color: rgb(255, 255, 255);line-height: 27px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">打卡格式:</strong></p> <p style="margin-right: 8px;margin-left: 8px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;word-spacing: 2px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);letter-spacing: 0.5px;widows: 1;background-color: rgb(255, 255, 255);line-height: 27px;box-sizing: border-box !important;overflow-wrap: break-word !important;">打卡 X 天,答:xxx 。</p> <p style="margin-right: 8px;margin-left: 8px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;white-space: normal;word-spacing: 2px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);letter-spacing: 0.5px;widows: 1;background-color: rgb(255, 255, 255);line-height: 27px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 2px;white-space: normal;word-spacing: 2px;text-align: center;"><a href="http://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247484441&idx=1&sn=39ea0929f45718995305bc5b5425a467&chksm=fa0e6b98cd79e28e12fed3c3024bc9a368e07605abd0cf909dc45c7d88cc5f331f32d5076311&scene=21#wechat_redirect" target="_blank" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="top: auto;left: auto;margin: 0px;right: auto;bottom: auto;"><img class="" data-copyright="0" data-ratio="0.3333333333333333" data-s="300,640" src="/upload/278e39379409264acd8e24e98dc9b0fa.png" data-type="png" data-w="600" style="width: 600px;top: auto;left: auto;right: auto;bottom: auto;margin: 0px;"></span></a></p>
作者:微信小助手
<section style="margin-top: -1px;white-space: normal;max-width: 100%;background: rgb(238, 239, 239);border-radius: 4px;height: 40px;line-height: 40px;text-indent: 0.5rem;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(110, 109, 109);font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击上方<span style="max-width: 100%;color: rgb(96, 127, 166);">“ITeye”</span>关注我们</span> </section> <p style="white-space: normal;"><span style="font-size: 15px;"> </span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;"> 目前Google Guava在实际应用中非常广泛,本篇博客将以博主对Guava使用的认识以及在项目中的经验来给大家分享!学习使用Google Guava可以让你写出优雅的JAVA代码!</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;font-weight: 700;">以面向对象思想处理字符串:Joiner/Splitter/CharMatcher</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">JDK提供的String还不够好么?也许还不够友好,至少让我们用起来还不够爽,还得操心!举个栗子,比如String提供的split方法,我们得关心空字符串吧,还得考虑返回的结果中存在null元素吧,只提供了前后trim的方法(如果我想对中间元素进行trim呢)。</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">那么,看下面的代码示例,guava让你不必在操心这些:</span></p> <p><img class="" data-ratio="0.4109375" src="/upload/5c4ea2aef62dc05eb1227a1edc59ed2a.jpg" data-type="jpeg" data-w="640" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Joiner/Splitter</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">Joiner是连接器,Splitter是分割器,通常我们会把它们定义为static final,利用on生成对象后在应用到String进行处理,这是可以复用的。要知道apache commons StringUtils提供的都是static method。更加重要的是,guava提供的Joiner/Splitter是经过充分测试,它的稳定性和效率要比apache高出不少,这个你可以自行测试下~发现没有我们想对String做什么操作,就是生成自己定制化的Joiner/Splitter,多么直白,简单,流畅的API!对于Joiner,常用的方法是 跳过NULL元素:skipNulls() / 对于NULL元素使用其他替代:useForNull(String)对于Splitter,常用的方法是: trimResults()/omitEmptyStrings()。注意拆分的方式,有字符串,还有正则,还有固定长度分割(太贴心了!)</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">其实除了Joiner/Splitter外,guava还提供了字符串匹配器:CharMatcher</span></p> <p><img class="" data-ratio="0.2714285714285714" src="/upload/4462c3f72e8cb998ef9b9d502a7caa61.jpg" data-type="jpeg" data-w="700" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">CharMatcher</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">CharMatcher,将字符的匹配和处理解耦,并提供丰富的方法供你使用!</span> </blockquote> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">对基本类型进行支持</span></h1> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">guava对JDK提供的原生类型操作进行了扩展,使得功能更加强大!</span> </blockquote> <p><img class="" data-ratio="0.5953177257525084" src="/upload/361713b14e7d177ba312327870528e19.jpg" data-type="jpeg" data-w="598" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Ints</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">guava提供了Bytes/Shorts/Ints/Iongs/Floats/Doubles/Chars/Booleans这些基本数据类型的扩展支持,只有你想不到的,没有它没有的!</span> </blockquote> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">对JDK集合的有效补充</span></h1> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">灰色地带:Multiset</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">JDK的集合,提供了有序且可以重复的List,无序且不可以重复的Set。那这里其实对于集合涉及到了2个概念,一个order,一个dups。那么List vs Set,and then some ?</span> </blockquote> <p><img class="" data-ratio="0.43272727272727274" src="/upload/bd4919f3bca51d1b39db3a0e025b0b01.jpg" data-type="jpeg" data-w="550" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Multiset</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">Multiset是什么,我想上面的图,你应该了解它的概念了。Multiset就是无序的,但是可以重复的集合,它就是游离在List/Set之间的“灰色地带”!(至于有序的,不允许重复的集合嘛,guava还没有提供,当然在未来应该会提供UniqueList,我猜的,哈哈)</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">来看一个Multiset的示例:</span></p> <p><img class="" data-ratio="0.4592274678111588" src="/upload/40d0e07bccf6601c845adeac30cdf39f.jpg" data-type="jpeg" data-w="466" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Multiset Code</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">Multiset自带一个有用的功能,就是可以跟踪每个对象的数量。</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Immutable vs unmodifiable</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">来我们先看一个unmodifiable的例子:</span></p> <p><img class="" data-ratio="0.3964968152866242" src="/upload/1f3d439abaf73ed5a3875d789dda7884.jpg" data-type="jpeg" data-w="628" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">unmodifiable</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">你看到JDK提供的unmodifiable的缺陷了吗?实际上,Collections.unmodifiableXxx所返回的集合和源集合是同一个对象,只不过可以对集合做出改变的API都被override,会抛出UnsupportedOperationException。也即是说我们改变源集合,导致不可变视图(unmodifiable View)也会发生变化,oh my god!</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">当然,在不使用guava的情况下,我们是怎么避免上面的问题的呢?</span></p> <p><img class="" data-ratio="0.23" src="/upload/f80f8f58492428ba0f862f1b9a7098ef.jpg" data-type="jpeg" data-w="700" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">defensive copies</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">上面揭示了一个概念:Defensive Copies,保护性拷贝。</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">OK,unmodifiable看上去没有问题呢,但是guava依然觉得可以改进,于是提出了Immutable的概念,来看:</span></p> <p><img class="" data-ratio="0.2342857142857143" src="/upload/421c2a6333c0d960ca2fb504dc944909.jpg" data-type="jpeg" data-w="700" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Immutable</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">就一个copyOf,你不会忘记,如此cheap~用Google官方的说法是:we're using just one class,just say exactly what we mean,很了不起吗(不仅仅是个概念,Immutable在COPY阶段还考虑了线程的并发性等,很智能的!),O(∩_∩)O哈哈~guava提供了很多Immutable集合,比如ImmutableList/ImmutableSet/ImmutableSortedSet/ImmutableMap/......</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">看一个ImmutableMap的例子:</span></p> <p><img class="" data-ratio="0.16457960644007155" src="/upload/c0b766fa7f1bd8155a48af222c3e7c35.jpg" data-type="jpeg" data-w="559" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">ImmutableMap</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">可不可以一对多:Multimap</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">JDK提供给我们的Map是一个键,一个值,一对一的,那么在实际开发中,显然存在一个KEY多个VALUE的情况(比如一个分类下的书本),我们往往这样表达:Map<k,List<v>>,好像有点臃肿!臃肿也就算了,更加不爽的事,我们还得判断KEY是否存在来决定是否new 一个LIST出来,有点麻烦!更加麻烦的事情还在后头,比如遍历,比如删除,so hard......</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">来看guava如何替你解决这个大麻烦的:</span></p> <p><img class="" data-ratio="0.3096153846153846" src="/upload/c574f29a01a4b03f47125b38ffb1b9b0.jpg" data-type="jpeg" data-w="520" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Multimap</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">友情提示下,guava所有的集合都有create方法,这样的好处在于简单,而且我们不必在重复泛型信息了。get()/keys()/keySet()/values()/entries()/asMap()都是非常有用的返回view collection的方法。Multimap的实现类有:ArrayListMultimap/HashMultimap/LinkedHashMultimap/TreeMultimap/ImmutableMultimap/......</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">可不可以双向:BiMap</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">JDK提供的MAP让我们可以find value by key,那么能不能通过find key by value呢,能不能KEY和VALUE都是唯一的呢。这是一个双向的概念,即forward+backward。在实际场景中有这样的需求吗?比如通过用户ID找到mail,也需要通过mail找回用户名。没有guava的时候,我们需要create forward map AND create backward map,and now just let guava do that for you.</span> </blockquote> <p><img class="" data-ratio="0.4326923076923077" src="/upload/a74cfc5732acde8ddb4258e845debfde.jpg" data-type="jpeg" data-w="624" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">BiMap</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">biMap / biMap.inverse() / biMap.inverse().inverse() 它们是什么关系呢?你可以稍微看一下BiMap的源码实现,实际上,当你创建BiMap的时候,在内部维护了2个map,一个forward map,一个backward map,并且设置了它们之间的关系。因此,biMap.inverse() != biMap ; biMap.inverse().inverse() == biMap</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">可不可以多个KEY:Table</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">我们知道数据库除了主键外,还提供了复合索引,而且实际中这样的多级关系查找也是比较多的,当然我们可以利用嵌套的Map来实现:Map<k1,Map<k2,v2>>。为了让我们的代码看起来不那么丑陋,guava为我们提供了Table。</span> </blockquote> <p><img class="" data-ratio="0.709375" src="/upload/e123dac1e314967d752f5bf1e994634e.jpg" data-type="jpeg" data-w="640" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Table</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">Table涉及到3个概念:rowKey,columnKey,value,并提供了多种视图以及操作方法让你更加轻松的处理多个KEY的场景。</span> </blockquote> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">函数式编程:Functions</span></h1> <p><img class="" data-ratio="0.7140575079872205" src="/upload/55ed3e90082fd1bb4f518e51429d6175.jpg" data-type="jpeg" data-w="626" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Functions</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">上面的代码是为了完成将List集合中的元素,先截取5个长度,然后转成大写。函数式编程的好处在于在集合遍历操作中提供自定义Function的操作,比如transform转换。我们再也不需要一遍遍的遍历集合,显著的简化了代码!</span> </blockquote> <p><img class="" data-ratio="0.5200729927007299" src="/upload/bb1deffdc26667a027eb02b26a46b73a.jpg" data-type="jpeg" data-w="548" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">对集合的transform操作可以通过Function完成</span></p> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">断言:Predicate</span></h1> <p><img class="" data-ratio="0.3796875" src="/upload/f955980ba7ff2ff9c3a1b2848bcde978.jpg" data-type="jpeg" data-w="640" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">Predicate最常用的功能就是运用在集合的过滤当中!</span> </blockquote> <p><img class="" data-ratio="0.5096359743040685" src="/upload/fbd75e54f82f8209884c58bb52fd9eb7.jpg" data-type="jpeg" data-w="467" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">filter</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">需要注意的是Lists并没有提供filter方法,不过你可以使用Collections2.filter完成!</span> </blockquote> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">check null and other:Optional、Preconditions</span></h1> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">在guava中,对于null的处理手段是快速失败,你可以看看guava的源码,很多方法的第一行就是:Preconditions.checkNotNull(elements);</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">要知道null是模糊的概念,是成功呢,还是失败呢,还是别的什么含义呢?</span></p> <p><img class="" data-ratio="0.4984375" src="/upload/22f751f88ccfbfbc00a0c6164977f716.jpg" data-type="jpeg" data-w="640" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Preconditions/Optional</span></p> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Cache is king</span></h1> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">对于大多数互联网项目而言,缓存的重要性,不言而喻!如果我们的应用系统,并不想使用一些第三方缓存组件(如redis),我们仅仅想在本地有一个功能足够强大的缓存,很可惜JDK提供的那些SET/MAP还不行!</span> </blockquote> <p><img class="" data-ratio="0.6390625" src="/upload/e43d015eb9f35c743d1fdb5c5cf3b614.jpg" data-type="jpeg" data-w="640" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">CacheLoader</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="font-size: 15px;-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">首先,这是一个本地缓存,guava提供的cache是一个简洁、高效,易于维护的。为什么这么说呢?因为并没有一个单独的线程用于刷新 OR 清理cache,对于cache的操作,都是通过访问/读写带来的,也就是说在读写中完成缓存的刷新操作!其次,我们看到了,我们非常通俗的告诉cache,我们的缓存策略是什么,SO EASY!在如此简单的背后,是guava帮助我们做了很多事情,比如线程安全。</span> </blockquote> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><br style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;"></h1> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">让异步回调更加简单</span></h1> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">JDK中提供了Future/FutureTask/Callable来对异步回调进行支持,但是还是看上去挺复杂的,能不能更加简单呢?比如注册一个监听回调。</span> </blockquote> <p><img class="" data-ratio="0.7609375" src="/upload/1f3a18dd21818ab041785dc11ed34ea0.jpg" data-type="jpeg" data-w="640" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">异步回调</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">我们可以通过guava对JDK提供的线程池进行装饰,让其具有异步回调监听功能,然后在设置监听器即可!</span> </blockquote> <hr style="-webkit-tap-highlight-color: transparent;box-sizing: content-box;height: 4px;overflow: visible;margin: 40px auto;width: 64px;background: rgb(237, 64, 64);outline: none;border-width: initial;border-style: none;border-color: initial;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;"> <h1 style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-size: 24px;margin-top: 36px;margin-bottom: 22px;font-weight: 700;line-height: 32px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">Summary</span></h1> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">到这里,这篇文章也只介绍了guava的冰山一角,其实还有很多内容:</span></p> <p><img class="" data-ratio="1.44043321299639" src="/upload/e4232070c56bf399d88fcad202868d6f.jpg" data-type="jpeg" data-w="277" style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;border-style: none;display: block;margin: 10px auto;"></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="font-size: 15px;">guava package</span></p> <blockquote style=" -webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 1em;margin-bottom: 1em;padding-top: 12px;padding-right: 10px;padding-bottom: 12px; font-size: 16px;line-height: 1.5;color: rgb(153, 153, 153);background: rgb(244, 245, 246);border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgb(232, 232, 232);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;text-align: start;white-space: normal; "> <span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">比如反射、注解、网络、并发、IO等等</span> </blockquote> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;">希望这篇文章让你快速进阶</span></p> <p style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;margin-top: 16px;margin-bottom: 16px;color: rgb(34, 34, 34);font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif;font-size: 16px;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);"><span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;font-size: 15px;"><br></span></p> <hr style="white-space: normal;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section label="Copyright © 2016 playhudong All Rights Reserved." style="margin-right: auto;margin-left: auto;white-space: normal;max-width: 100%;width: 20em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;width: 320px;text-align: center;line-height: 1.5em;font-size: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">想了解更多?那就赶紧来关注我们</span></p> </section> <section style="margin-top: 1em;margin-bottom: 1em;max-width: 100%;width: 320px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img title="https://image.ipaiban.com/upload-ueditor-image-20180627-1530029388314035035.jpg" class="" data-ratio="1" data-type="jpeg" data-w="1280" src="/upload/49126aae7a67399241ae1fc5cfc94372.jpg" style="display: inline;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 160px !important;visibility: visible !important;"> </section> <section class="" style="max-width: 100%;width: 320px;text-align: center;border-top: 2px solid rgb(253, 208, 39);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section class="" style="max-width: 100%;background: rgb(253, 208, 39);display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-right: 0.5em;max-width: 100%;width: 0px;height: 0px;border-top: 1.6em solid transparent;border-left: 0.5em solid rgb(255, 255, 255);float: left;display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"></section> <section style="max-width: 100%;width: auto;color: rgb(255, 255, 255);line-height: 1em;font-size: 0.87em;display: inline-block;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">长按二维码 关注我们</span></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> </section> </section> </section> </section> <p><br></p> <p><br></p>