Help
RSS
API
Feed
Maltego
Contact
Domain > lyloou.com
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2016-02-12
112.175.238.66
(
ClassC
)
2026-02-11
185.199.108.153
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyConnection: keep-aliveContent-Length: 162Server: GitHub.comContent-Type: text/htmlLocation: https://lyloou.com/X-GitHub-Request-Id: 68A6:18B8AC:65334AF:70E42C9:698C3322Accept-Ranges: bytesAge: 0Date: Wed, 11 Feb 2026 07:43:31 GMTVia: 1.1 varnishX-Served-By: cache-bfi-kbfi7400021-BFIX-Cache: MISSX-Cache-Hits: 0X-Timer: S1770795811.382859,VS0,VE87Vary: Accept-EncodingX-Fastly-Request-ID: 1c3c0fb8d9edb5dcd9eb7a2ddb3b4186aa0a8af3 html>head>title>301 Moved Permanently/title>/head>body>center>h1>301 Moved Permanently/h1>/center>hr>center>nginx/center>/body>/html>
Port 443
HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 228833Server: GitHub.comContent-Type: text/html; charsetutf-8Last-Modified: Sun, 14 May 2023 07:47:57 GMTAccess-Control-Allow-Origin: *ETag: 6460922d-37de1expires: Wed, 11 Feb 2026 07:53:31 GMTCache-Control: max-age600x-proxy-cache: MISSX-GitHub-Request-Id: D80E:26DE27:67153DD:6FCB3B4:698C3323Accept-Ranges: bytesAge: 0Date: Wed, 11 Feb 2026 07:43:31 GMTVia: 1.1 varnishX-Served-By: cache-bfi-kbfi7400108-BFIX-Cache: MISSX-Cache-Hits: 0X-Timer: S1770795812.517540,VS0,VE107Vary: Accept-EncodingX-Fastly-Request-ID: 205269ecd2ae736ca9225166133b1442d0147231 !DOCTYPE html>html langzh-CN>head> meta charsetUTF-8>meta nameviewport contentwidthdevice-width>meta nametheme-color content#222>meta namegenerator contentHexo 5.4.2> link relapple-touch-icon sizes180x180 href/images/apple-touch-icon-next.png> link relicon typeimage/png sizes32x32 href/favicon.ico> link relicon typeimage/png sizes16x16 href/favicon.ico> link relmask-icon href/images/logo.svg color#222>link relstylesheet href/css/main.css>link relstylesheet hrefhttps://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css integritysha256-HtsXJanqjKTc8vVQjO4YMhiqFoXkfBsjBWcX91T1jr8 crossoriginanonymous> link relstylesheet hrefhttps://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css integritysha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE crossoriginanonymous>script classnext-config data-namemain typeapplication/json>{hostname:lyloou.com,root:/,images:/images,scheme:Mist,darkmode:false,version:8.16.0,exturl:false,sidebar:{position:left,display:post,padding:18,offset:12},copycode:{enable:true,style:default},bookmark:{enable:false,color:#222,save:auto},mediumzoom:false,lazyload:false,pangu:false,comments:{style:tabs,active:null,storage:true,lazyload:false,nav:null},stickytabs:false,motion:{enable:true,async:false,transition:{menu_item:fadeInDown,post_block:fadeIn,post_header:fadeInDown,post_body:fadeInDown,coll_header:fadeInLeft,sidebar:fadeInUp}},prism:false,i18n:{placeholder:搜索...,empty:没有找到任何搜索结果:${query},hits_time:找到 ${hits} 个搜索结果(用时 ${time} 毫秒),hits:找到 ${hits} 个搜索结果},path:/search.xml,localsearch:{enable:true,trigger:auto,top_n_per_article:1,unescape:false,preload:false}}/script>script src/js/config.js>/script> meta namedescription content/* Better than last best */>meta propertyog:type contentwebsite>meta propertyog:title contentlyloou>meta propertyog:url contenthttps://lyloou.com/index.html>meta propertyog:site_name contentlyloou>meta propertyog:description content/* Better than last best */>meta propertyog:locale contentzh_CN>meta propertyarticle:author contentlyloou>meta nametwitter:card contentsummary>link relcanonical hrefhttps://lyloou.com/>script classnext-config data-namepage typeapplication/json>{sidebar:,isHome:true,isPost:false,lang:zh-CN,comments:,permalink:,path:index.html,title:}/script>script classnext-config data-namecalendar typeapplication/json>/script>title>lyloou/title> script classnext-config data-namegoogle_analytics typeapplication/json>{tracking_id:UA-80542932-1,only_pageview:true}/script> script src/js/third-party/analytics/google-analytics.js>/script> noscript> link relstylesheet href/css/noscript.css> /noscript>/head>body itemscope itemtypehttp://schema.org/WebPage classuse-motion> div classheadband>/div> main classmain> div classcolumn> header classheader itemscope itemtypehttp://schema.org/WPHeader>div classsite-brand-container> div classsite-nav-toggle> div classtoggle aria-label切换导航栏 rolebutton> span classtoggle-line>/span> span classtoggle-line>/span> span classtoggle-line>/span> /div> /div> div classsite-meta> a href/ classbrand relstart> i classlogo-line>/i> h1 classsite-title>lyloou/h1> i classlogo-line>/i> /a> /div> div classsite-nav-right> div classtoggle popup-trigger aria-label搜索 rolebutton> i classfa fa-search fa-fw fa-lg>/i> /div> /div>/div>nav classsite-nav> ul classmain-menu menu>li classmenu-item menu-item-home>a href/ relsection>i classhome fa-fw>/i>首页/a>/li>li classmenu-item menu-item-about>a href/about/ relsection>i classuser fa-fw>/i>关于/a>/li>li classmenu-item menu-item-tags>a href/tags/ relsection>i classtags fa-fw>/i>标签/a>/li>li classmenu-item menu-item-archives>a href/archives/ relsection>i classarchive fa-fw>/i>归档/a>/li> li classmenu-item menu-item-search> a rolebutton classpopup-trigger>i classfa fa-search fa-fw>/i>搜索 /a> /li> /ul>/nav> div classsearch-pop-overlay> div classpopup search-popup>div classsearch-header> span classsearch-icon> i classfa fa-search>/i> /span> div classsearch-input-container> input autocompleteoff autocapitalizeoff maxlength80 placeholder搜索... spellcheckfalse typesearch classsearch-input> /div> span classpopup-btn-close rolebutton> i classfa fa-times-circle>/i> /span>/div>div classsearch-result-container no-result> div classsearch-result-icon> i classfa fa-spinner fa-pulse fa-5x>/i> /div>/div> /div> /div>/header> aside classsidebar> div classsidebar-inner sidebar-overview-active> ul classsidebar-nav> li classsidebar-nav-toc> 文章目录 /li> li classsidebar-nav-overview> 站点概览 /li> /ul> div classsidebar-panel-container> !--noindex--> div classpost-toc-wrap sidebar-panel> /div> !--/noindex--> div classsite-overview-wrap sidebar-panel> div classsite-author animated itempropauthor itemscope itemtypehttp://schema.org/Person> img classsite-author-image itempropimage altlyloou src/assets/images/avatar.png> p classsite-author-name itempropname>lyloou/p> div classsite-description itempropdescription>/* Better than last best *//div>/div>div classsite-state-wrap animated> nav classsite-state> div classsite-state-item site-state-posts> a href/archives/> span classsite-state-item-count>312/span> span classsite-state-item-name>日志/span> /a> /div> div classsite-state-item site-state-tags> a href/tags/> span classsite-state-item-count>56/span> span classsite-state-item-name>标签/span>/a> /div> /nav>/div> div classlinks-of-author animated> span classlinks-of-author-item> a hrefhttps://github.com/lyloou titleGitHub → https://github.com/lyloou relnoopener me target_blank>i classgithub fa-fw>/i>GitHub/a> /span> span classlinks-of-author-item> a hrefmailto:lyloou6@gmail.com titleE-Mail → mailto:lyloou6@gmail.com relnoopener me target_blank>i classenvelope fa-fw>/i>E-Mail/a> /span> span classlinks-of-author-item> a hrefhttps://weibo.com/lyloou titleWeibo → https://weibo.com/lyloou relnoopener me target_blank>i classweibo fa-fw>/i>Weibo/a> /span> span classlinks-of-author-item> a hrefhttps://blog.csdn.net/ly1414725328 titleCSDN → https://blog.csdn.net/ly1414725328 relnoopener me target_blank>i classcsdn fa-fw>/i>CSDN/a> /span> /div> div classcc-license animated itemproplicense> a hrefhttps://creativecommons.org/licenses/by-nc-sa/4.0/ classcc-opacity relnoopener target_blank>img srchttps://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg altCreative Commons>/a> /div> /div> /div> /div> div classpjax> /div> /aside> /div> div classmain-inner index posts-expand> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/java/%E8%8E%B7%E5%8F%96%E6%9C%89%E6%95%88%E7%9A%84%E5%BC%82%E5%B8%B8%E8%B0%83%E7%94%A8%E5%A0%86%E6%A0%88%E4%BF%A1%E6%81%AF/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/java/%E8%8E%B7%E5%8F%96%E6%9C%89%E6%95%88%E7%9A%84%E5%BC%82%E5%B8%B8%E8%B0%83%E7%94%A8%E5%A0%86%E6%A0%88%E4%BF%A1%E6%81%AF/ classpost-title-link itempropurl>【Java】获取有效的异常调用堆栈信息/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2023-03-17 15:39:37 itempropdateCreated datePublished datetime2023-03-17T15:39:37+08:00>2023-03-17/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> p>项目中,可能会遇到虽然知道发生了异常,但是不知道异常是什么,由于调用栈信息不全,从日志上看不出具体问题;主要原因是异常调用栈太深,导致异常信息被截断。/p>p>下面这个方法可以获取根异常,将中间的非主要异常过滤掉。/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>/pre>/td>td classcode>pre>span classline>span classcomment>/** /span>/span>br>span classline>span classcomment> * 获取根异常,防止调用链太长,导致有效信息被截断 /span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> Throwable span classtitle function_>getRootThrowable/span>span classparams>(Throwable e)/span> { /span>br>span classline> span classkeyword>if/span> (Objects.isNull(e)) { /span>br>span classline> span classkeyword>return/span> span classliteral>null/span>; /span>br>span classline> } /span>br>span classline> /span>br>span classline> span classtype>Throwable/span> span classvariable>lastCause/span> span classoperator>/span> e; /span>br>span classline> span classtype>Throwable/span> span classvariable>currentCause/span> span classoperator>/span> e.getCause(); /span>br>span classline> span classkeyword>while/span> (Objects.nonNull(currentCause)) { /span>br>span classline> lastCause currentCause; /span>br>span classline> currentCause currentCause.getCause(); /span>br>span classline> } /span>br>span classline> /span>br>span classline> span classkeyword>return/span> lastCause; /span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure>p>示例/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>/pre>/td>td classcode>pre>span classline>span classmeta>@Slf4j/span> /span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>ThrowableTestDemo/span> { /span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> { /span>br>span classline> test(); /span>br>span classline> } /span>br>span classline> /span>br>span classline> span classkeyword>private/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>test/span>span classparams>()/span> { /span>br>span classline> span classkeyword>try/span> { /span>br>span classline> span classkeyword>try/span> { /span>br>span classline> span classkeyword>try/span> { /span>br>span classline> span classkeyword>try/span> { /span>br>span classline> span classkeyword>try/span> { /span>br>span classline> span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>1/span> / span classnumber>0/span>; /span>br>span classline> } span classkeyword>catch/span> (Exception e) { /span>br>span classline> span classkeyword>throw/span> span classkeyword>new/span> span classtitle class_>RuntimeException/span>(e); /span>br>span classline> } /span>br>span classline> } span classkeyword>catch/span> (Exception e) { /span>br>span classline> span classkeyword>throw/span> span classkeyword>new/span> span classtitle class_>RuntimeException/span>(e); /span>br>span classline> } /span>br>span classline> } span classkeyword>catch/span> (Exception e) { /span>br>span classline> span classkeyword>throw/span> span classkeyword>new/span> span classtitle class_>RuntimeException/span>(e); /span>br>span classline> } /span>br>span classline> } span classkeyword>catch/span> (Exception e) { /span>br>span classline> span classkeyword>throw/span> span classkeyword>new/span> span classtitle class_>RuntimeException/span>(e); /span>br>span classline> } /span>br>span classline> } span classkeyword>catch/span> (Exception e) { /span>br>span classline> log.warn(span classstring>"处理前:"/span>, e); /span>br>span classline> System.out.println(span classstring>">"/span>); /span>br>span classline> log.warn(span classstring>"处理后:"/span>, getRootThrowable(e)); /span>br>span classline> } /span>br>span classline> }/span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure>figure classhighlight stylus>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>/pre>/td>td classcode>pre>span classline>span classnumber>10/span>:span classnumber>38/span>:span classnumber>13.122/span> span classselector-attr>main/span> WARN comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span> - 处理前:/span>br>span classline>javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.ArithmeticException/span>: / by zero/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.test/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>36/span>)/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.main/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>15/span>)/span>br>span classline>Caused by: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.ArithmeticException/span>: / by zero/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.test/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>33/span>)/span>br>span classline> ... span classnumber>1/span> common frames omitted/span>br>span classline>Caused by: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.ArithmeticException/span>: / by zero/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.test/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>30/span>)/span>br>span classline> ... span classnumber>1/span> common frames omitted/span>br>span classline>Caused by: javaspan classselector-class>.lang/span>span classselector-class>.RuntimeException/span>: javaspan classselector-class>.lang/span>span classselector-class>.ArithmeticException/span>: / by zero/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.test/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>27/span>)/span>br>span classline> ... span classnumber>1/span> common frames omitted/span>br>span classline>Caused by: javaspan classselector-class>.lang/span>span classselector-class>.ArithmeticException/span>: / by zero/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.test/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>25/span>)/span>br>span classline> ... span classnumber>1/span> common frames omitted/span>br>span classline> /span>br>span classline>>/span>br>span classline>span classnumber>10/span>:span classnumber>38/span>:span classnumber>13.124/span> span classselector-attr>main/span> WARN comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span> - 处理后:/span>br>span classline>javaspan classselector-class>.lang/span>span classselector-class>.ArithmeticException/span>: / by zero/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.test/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>25/span>)/span>br>span classline> at comspan classselector-class>.coocaa/span>span classselector-class>.media/span>span classselector-class>.sync/span>span classselector-class>.ThrowableTestDemo/span>span classselector-class>.main/span>(ThrowableTestDemospan classselector-class>.java/span>:span classnumber>15/span>)/span>br>/pre>/td>/tr>/table>/figure> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/java/%E5%9F%BA%E4%BA%8E%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8%E7%9A%84%E6%9E%84%E5%BB%BA%E5%99%A8%E6%A8%A1%E5%BC%8F%E8%BF%90%E7%94%A8/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/java/%E5%9F%BA%E4%BA%8E%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8%E7%9A%84%E6%9E%84%E5%BB%BA%E5%99%A8%E6%A8%A1%E5%BC%8F%E8%BF%90%E7%94%A8/ classpost-title-link itempropurl>【Java】基于方法引用的构建器模式运用/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-12-07 17:39:37 itempropdateCreated datePublished datetime2022-12-07T17:39:37+08:00>2022-12-07/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> h2 id思考>a href#思考 classheaderlink title思考>/a>思考/h2>p>封装一个 set 对象构建器,利用类的 set 引用方法(不局限 set 开头的方法)来设值,便于点式调用。/p>h2 id测试>a href#测试 classheaderlink title测试>/a>测试/h2>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>/pre>/td>td classcode>pre>span classline>/span>br>span classline>span classkeyword>import/span> cn.hutool.core.bean.BeanUtil;/span>br>span classline>span classkeyword>import/span> lombok.Data;/span>br>span classline>/span>br>span classline>span classmeta>@Data/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>User/span> {/span>br>span classline> span classkeyword>private/span> String name;/span>br>span classline> span classkeyword>private/span> Integer age;/span>br>span classline> span classkeyword>private/span> String sex;/span>br>span classline> span classkeyword>private/span> String email;/span>br>span classline>/span>br>span classline> span classkeyword>private/span> String other;/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>appendOther/span>span classparams>(String other)/span> {/span>br>span classline> span classbuilt_in>this/span>.other other;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classcomment>// 方法1,普通语法(推荐)/span>/span>br>span classline> span classtype>User/span> span classvariable>user1/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>User/span>();/span>br>span classline> user1.setName(span classstring>"Jojo"/span>);/span>br>span classline> user1.setAge(span classnumber>18/span>);/span>br>span classline> user1.setSex(span classstring>"女"/span>);/span>br>span classline> user1.setEmail(span classstring>"JoJo@example.com"/span>);/span>br>span classline> user1.appendOther(span classstring>"其他数据"/span>);/span>br>span classline> System.out.println(user1);/span>br>span classline>/span>br>span classline> span classcomment>// 方法2,双括号语法(本质是匿名函数。不推荐使用,可能引起内层泄露)/span>/span>br>span classline> span classtype>User/span> span classvariable>user2/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>User/span>() {{/span>br>span classline> setName(span classstring>"Jojo"/span>);/span>br>span classline> setAge(span classnumber>18/span>);/span>br>span classline> setSex(span classstring>"女"/span>);/span>br>span classline> setEmail(span classstring>"JoJo@example.com"/span>);/span>br>span classline> appendOther(span classstring>"其他数据"/span>);/span>br>span classline> }};/span>br>span classline> System.out.println(user2);/span>br>span classline>/span>br>span classline> span classcomment>// 方法3:set 构建器(推荐)/span>/span>br>span classline> span classkeyword>final/span> span classtype>User/span> span classvariable>user3/span> span classoperator>/span> SetBuilder.of(span classkeyword>new/span> span classtitle class_>User/span>())/span>br>span classline> .set(User::setName, span classstring>"JoJo"/span>)/span>br>span classline> .set(User::setAge, span classnumber>18/span>)/span>br>span classline> .set(User::setSex, span classstring>"女"/span>)/span>br>span classline> .set(User::setEmail, span classstring>"JoJo@example.com"/span>)/span>br>span classline> .set(User::appendOther, span classstring>"其他数据"/span>)/span>br>span classline> .build();/span>br>span classline> System.out.println(user3);/span>br>span classline>/span>br>span classline> span classcomment>// 方法4:反射设值/span>/span>br>span classline> span classkeyword>final/span> span classtype>User/span> span classvariable>user4/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>User/span>();/span>br>span classline> BeanUtil.setFieldValue(user4, span classstring>"name"/span>, span classstring>"JoJo"/span>);/span>br>span classline> BeanUtil.setFieldValue(user4, span classstring>"age"/span>, span classnumber>18/span>);/span>br>span classline> BeanUtil.setFieldValue(user4, span classstring>"sex"/span>, span classstring>"女"/span>);/span>br>span classline> BeanUtil.setFieldValue(user4, span classstring>"email"/span>, span classstring>"JoJo@example.com"/span>);/span>br>span classline> BeanUtil.setFieldValue(user4, span classstring>"other"/span>, span classstring>"其他数据"/span>);/span>br>span classline> System.out.println(user4);/span>br>span classline> }/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 打印:/span>/span>br>span classline>span classcomment> User(nameJojo, age18, sex女, emailJoJo@example.com, other其他数据)/span>/span>br>span classline>span classcomment> User(nameJojo, age18, sex女, emailJoJo@example.com, other其他数据)/span>/span>br>span classline>span classcomment> User(nameJoJo, age18, sex女, emailJoJo@example.com, other其他数据)/span>/span>br>span classline>span classcomment> User(nameJoJo, age18, sex女, emailJoJo@example.com, other其他数据)/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure>h2 id源码>a href#源码 classheaderlink title源码>/a>源码/h2>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>/pre>/td>td classcode>pre>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 封装一个set构建器,基于对象的 set 引用方法来设值/span>/span>br>span classline>span classcomment> * <p>/span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> <T> 指定对象泛型/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>SetBuilder/span><T> {/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> T object;/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> <T> SetBuilder<T> span classtitle function_>of/span>span classparams>(T object)/span> {/span>br>span classline> span classkeyword>return/span> span classkeyword>new/span> span classtitle class_>SetBuilder/span><>(object);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 构造函数/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> object 对象/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> span classtitle function_>SetBuilder/span>span classparams>(T object)/span> {/span>br>span classline> span classbuilt_in>this/span>.object object;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 链式调用/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> setter set引用方法/span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> value 要设置的属性值/span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> <V> 对象泛型/span>/span>br>span classline>span classcomment> * span classdoctag>@return/span> builder,可链式调用/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> <V> SetBuilder<T> span classtitle function_>set/span>span classparams>(Setter<T, V> setter, V value)/span> {/span>br>span classline> setter.set(object, value);/span>br>span classline> span classkeyword>return/span> span classbuilt_in>this/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 构建/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@return/span> 构建后对象/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> T span classtitle function_>build/span>span classparams>()/span> {/span>br>span classline> span classkeyword>return/span> object;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classmeta>@FunctionalInterface/span>/span>br>span classline> span classkeyword>public/span> span classkeyword>interface/span> span classtitle class_>Setter/span><T, V> {/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 调用set方法/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> t 实体对象/span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> value 实体对象属性值/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>void/span> span classtitle function_>set/span>span classparams>(T t, V value)/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/java-concurrent/%E5%9F%BA%E4%BA%8E%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E7%8B%AC%E7%AB%8B%E4%BB%BB%E5%8A%A1%E5%B9%B6%E5%8F%91%E6%89%A7%E8%A1%8C%E5%99%A8/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/java-concurrent/%E5%9F%BA%E4%BA%8E%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E7%8B%AC%E7%AB%8B%E4%BB%BB%E5%8A%A1%E5%B9%B6%E5%8F%91%E6%89%A7%E8%A1%8C%E5%99%A8/ classpost-title-link itempropurl>【Java】基于线程池的独立任务并发执行器/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-06-11 09:40:42 itempropdateCreated datePublished datetime2022-06-11T09:40:42+08:00>2022-06-11/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> h4 id目的:>a href#目的: classheaderlink title目的:>/a>目的:/h4>p>对于多个独立的任务,可以以并发的方式执行任务,以提高 CPU 利用率,提高处理效率。/p>h4 id思路>a href#思路 classheaderlink title思路>/a>思路/h4>p>在一个线程池中,开启指定数量的线程,每个线程从任务队列中获取任务执行。/p>p>执行的过程中,判断当前线程是否在执行任务的状态,如果没有执行任务,取一条任务执行,如果正在执行,则跳过,下轮再判断。/p>p>在所有任务执行完后,关闭线程池。/p>p>需要注意的是数据结构的选择,须选择并发类的数据结构,不然可能出现阻塞,死锁等情况。/p>p>(具体逻辑参考源码)/p>h4 id示例>a href#示例 classheaderlink title示例>/a>示例/h4>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>/pre>/td>td classcode>pre>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 并发执行器示例/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>ConcurrentExecutorTest/span> {/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 测试/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>0/span>; i < span classnumber>100/span>; i++) {/span>br>span classline> test();/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>private/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>test/span>span classparams>()/span> {/span>br>span classline> Map<String, String> paramMap span classkeyword>new/span> span classtitle class_>LinkedHashMap/span><>();/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>0/span>; i < span classnumber>10/span>; i++) {/span>br>span classline> paramMap.put(span classstring>"key:"/span> + i, span classstring>"value:"/span> + i);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>final/span> ConcurrentExecutor<String, String, Integer> executor span classkeyword>new/span> span classtitle class_>ConcurrentExecutor/span><>(span classnumber>5/span>, paramMap,/span>br>span classline> (k, v) -> {/span>br>span classline> ThreadUtil.sleep(span classnumber>10/span>);/span>br>span classline> System.out.println(Thread.currentThread().getName() + span classstring>"-"/span> + v);/span>br>span classline> span classkeyword>final/span> span classtype>int/span> span classvariable>abs/span> span classoperator>/span> Math.abs(Objects.hash(v));/span>br>span classline> span classkeyword>if/span> (abs % span classnumber>3/span> span classnumber>0/span>) {/span>br>span classline> span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>1/span> / span classnumber>0/span>;/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> abs;/span>br>span classline> });/span>br>span classline> executor.execute();/span>br>span classline> System.out.println(span classstring>"success result: "/span> + executor.getSuccessResultMap());/span>br>span classline> System.out.println(span classstring>"error result: "/span> + executor.getErrorResultMap());/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>p>测试结果/p>figure classhighlight ini>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>/pre>/td>td classcode>pre>span classline>pool-1-thread-1-value:0/span>br>span classline>pool-1-thread-2-value:1/span>br>span classline>pool-1-thread-4-value:3/span>br>span classline>pool-1-thread-3-value:2/span>br>span classline>pool-1-thread-3-value:8/span>br>span classline>pool-1-thread-1-value:5/span>br>span classline>pool-1-thread-5-value:4/span>br>span classline>pool-1-thread-2-value:6/span>br>span classline>pool-1-thread-4-value:7/span>br>span classline>pool-1-thread-3-value:9/span>br>span classline>success result: {key:span classattr>2/span>span classnumber>231604360/span>, key:span classnumber>0/span>span classnumber>231604358/span>, key:span classnumber>6/span>span classnumber>231604364/span>, key:span classnumber>5/span>span classnumber>231604363/span>, key:span classnumber>3/span>span classnumber>231604361/span>, key:span classnumber>9/span>span classnumber>231604367/span>, key:span classnumber>8/span>span classnumber>231604366/span>}/span>br>span classline>error result: {key:span classattr>1/span>java.lang.ArithmeticException: / by zero, key:span classnumber>4/span>java.lang.ArithmeticException: / by zero, key:span classnumber>7/span>java.lang.ArithmeticException: / by zero}/span>br>/pre>/td>/tr>/table>/figure>h4 id源码(方案-1)>a href#源码(方案-1) classheaderlink title源码(方案 1)>/a>源码(方案 1)/h4>p>基于自定义的 queue 实现/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>span classline>70/span>br>span classline>71/span>br>span classline>72/span>br>span classline>73/span>br>span classline>74/span>br>span classline>75/span>br>span classline>76/span>br>span classline>77/span>br>span classline>78/span>br>span classline>79/span>br>span classline>80/span>br>span classline>81/span>br>span classline>82/span>br>span classline>83/span>br>span classline>84/span>br>span classline>85/span>br>span classline>86/span>br>span classline>87/span>br>span classline>88/span>br>span classline>89/span>br>span classline>90/span>br>span classline>91/span>br>span classline>92/span>br>span classline>93/span>br>span classline>94/span>br>span classline>95/span>br>span classline>96/span>br>span classline>97/span>br>span classline>98/span>br>span classline>99/span>br>span classline>100/span>br>span classline>101/span>br>span classline>102/span>br>span classline>103/span>br>span classline>104/span>br>span classline>105/span>br>span classline>106/span>br>span classline>107/span>br>span classline>108/span>br>span classline>109/span>br>span classline>110/span>br>span classline>111/span>br>span classline>112/span>br>span classline>113/span>br>span classline>114/span>br>span classline>115/span>br>span classline>116/span>br>span classline>117/span>br>span classline>118/span>br>span classline>119/span>br>span classline>120/span>br>span classline>121/span>br>span classline>122/span>br>span classline>123/span>br>span classline>124/span>br>span classline>125/span>br>span classline>126/span>br>span classline>127/span>br>span classline>128/span>br>span classline>129/span>br>span classline>130/span>br>span classline>131/span>br>span classline>132/span>br>span classline>133/span>br>span classline>134/span>br>span classline>135/span>br>span classline>136/span>br>span classline>137/span>br>span classline>138/span>br>span classline>139/span>br>span classline>140/span>br>span classline>141/span>br>span classline>142/span>br>span classline>143/span>br>span classline>144/span>br>span classline>145/span>br>span classline>146/span>br>span classline>147/span>br>span classline>148/span>br>span classline>149/span>br>span classline>150/span>br>span classline>151/span>br>span classline>152/span>br>/pre>/td>td classcode>pre>span classline>/span>br>span classline>span classkeyword>import/span> cn.hutool.core.collection.CollUtil;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.collection.ConcurrentHashSet;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.lang.Assert;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.thread.ThreadUtil;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.util.BooleanUtil;/span>br>span classline>/span>br>span classline>span classkeyword>import/span> java.util.*;/span>br>span classline>span classkeyword>import/span> java.util.concurrent.ConcurrentHashMap;/span>br>span classline>span classkeyword>import/span> java.util.concurrent.ConcurrentLinkedQueue;/span>br>span classline>span classkeyword>import/span> java.util.concurrent.ExecutorService;/span>br>span classline>span classkeyword>import/span> java.util.function.BiFunction;/span>br>span classline>/span>br>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 并发执行器/span>/span>br>span classline>span classcomment> * <p>/span>/span>br>span classline>span classcomment> * 适用场景:每个任务是独立的,不耦合的/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@author/span> lilou/span>/span>br>span classline>span classcomment> * span classdoctag>@since/span> 2022/6/9 9:05/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>ConcurrentExecutor/span><K, V, R> {/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 任务参数映射(K:key的类型,V:值的类型)/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<K, V> paramMap;/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 成功的任务结果映射(R:结果类型)/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<K, R> successResultMap;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 失败的任务结果映射/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<K, Throwable> errorResultMap;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 当前运行中的key集合/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Set<K> runningKeySet;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 候选任务key队列/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Queue<K> candidateKeyQueue;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 同时运行的最大线程数量/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> span classtype>int/span> maxThreadNum;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 执行器/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> ExecutorService executorService;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 具体任务策略/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> BiFunction<K, V, R> biFunction;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 当前index线程的运行状态,可依据此状态,判断是否立刻从任务参数中获取任务执行/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<Integer, Boolean> currentIndexThreadRunningStatusMap;/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classtitle function_>ConcurrentExecutor/span>span classparams>(span classtype>int/span> maxThreadNum, Map<K, V> paramMap, BiFunction<K, V, R> biFunction)/span> {/span>br>span classline> Assert.notNull(paramMap, span classstring>"paramMap不可为空"/span>);/span>br>span classline> Assert.isTrue(maxThreadNum > span classnumber>0/span>, span classstring>"maxThreadNum不可小于1"/span>);/span>br>span classline>/span>br>span classline> span classkeyword>final/span> span classtype>int/span> span classvariable>paramSize/span> span classoperator>/span> paramMap.size();/span>br>span classline> span classbuilt_in>this/span>.maxThreadNum Math.min(maxThreadNum, paramSize);/span>br>span classline> span classcomment>// tips: 须转换成同步类的map数据结构,如果错误地使用 this.paramMap paramMap; 且外部使用了HashMap 或 LinkedHashMap,多测试几遍会发现,偶尔会陷入了阻塞/span>/span>br>span classline> span classbuilt_in>this/span>.paramMap Collections.synchronizedMap(paramMap);/span>br>span classline> span classbuilt_in>this/span>.candidateKeyQueue span classkeyword>new/span> span classtitle class_>ConcurrentLinkedQueue/span><>(paramMap.keySet());/span>br>span classline> span classbuilt_in>this/span>.runningKeySet span classkeyword>new/span> span classtitle class_>ConcurrentHashSet/span><>(paramSize);/span>br>span classline> span classbuilt_in>this/span>.biFunction biFunction;/span>br>span classline> span classbuilt_in>this/span>.executorService ThreadUtil.newExecutor(span classbuilt_in>this/span>.maxThreadNum, span classbuilt_in>this/span>.maxThreadNum, Integer.MAX_VALUE);/span>br>span classline> span classbuilt_in>this/span>.currentIndexThreadRunningStatusMap span classkeyword>new/span> span classtitle class_>ConcurrentHashMap/span><>(span classbuilt_in>this/span>.maxThreadNum);/span>br>span classline> span classbuilt_in>this/span>.successResultMap span classkeyword>new/span> span classtitle class_>ConcurrentHashMap/span><>(span classbuilt_in>this/span>.paramMap.size());/span>br>span classline> span classbuilt_in>this/span>.errorResultMap span classkeyword>new/span> span classtitle class_>ConcurrentHashMap/span><>();/span>br>span classline> }/span>br>span classline>/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>execute/span>span classparams>()/span> {/span>br>span classline> span classkeyword>while/span> (CollUtil.isNotEmpty(paramMap)) {/span>br>span classline>/span>br>span classline> span classcomment>// 最多同时有 maxRunningThreadNumber 同时消费 taskMap 中的数据/span>/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>0/span>; i < span classbuilt_in>this/span>.maxThreadNum; i++) {/span>br>span classline> span classtype>int/span> span classvariable>currentIndex/span> span classoperator>/span> i;/span>br>span classline>/span>br>span classline> span classcomment>// 当前线程上次还未执行完,暂时跳过/span>/span>br>span classline> span classkeyword>final/span> span classtype>Boolean/span> span classvariable>isRunning/span> span classoperator>/span> currentIndexThreadRunningStatusMap.getOrDefault(currentIndex, span classliteral>false/span>);/span>br>span classline> span classkeyword>if/span> (BooleanUtil.isTrue(isRunning)) {/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 选择一个候选key/span>/span>br>span classline> span classkeyword>final/span> span classtype>K/span> span classvariable>candidateKey/span> span classoperator>/span> pickCandidateKey();/span>br>span classline> span classcomment>// 当前没有对应key的任务/span>/span>br>span classline> span classkeyword>if/span> (Objects.isNull(candidateKey)) {/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 在线程池中运行任务/span>/span>br>span classline> executorService.submit(() -> {/span>br>span classline> span classkeyword>try/span> {/span>br>span classline> currentIndexThreadRunningStatusMap.put(currentIndex, span classliteral>true/span>);/span>br>span classline> span classkeyword>final/span> span classtype>V/span> span classvariable>data/span> span classoperator>/span> paramMap.get(candidateKey);/span>br>span classline>/span>br>span classline> span classcomment>// 开始执行任务/span>/span>br>span classline> span classkeyword>final/span> span classtype>R/span> span classvariable>result/span> span classoperator>/span> biFunction.apply(candidateKey, data);/span>br>span classline>/span>br>span classline> span classcomment>// 存入正常结果/span>/span>br>span classline> successResultMap.put(candidateKey, result);/span>br>span classline> } span classkeyword>catch/span> (Exception e) {/span>br>span classline> span classcomment>// 存入异常结果/span>/span>br>span classline> errorResultMap.put(candidateKey, e);/span>br>span classline> } span classkeyword>finally/span> {/span>br>span classline> paramMap.remove(candidateKey);/span>br>span classline> candidateKeyQueue.remove(candidateKey);/span>br>span classline> currentIndexThreadRunningStatusMap.remove(currentIndex);/span>br>span classline> }/span>br>span classline> });/span>br>span classline> }/span>br>span classline> }/span>br>span classline> executorService.shutdown();/span>br>span classline> }/span>br>span classline>/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 从候选任务key队列中选择一个任务key/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> K span classtitle function_>pickCandidateKey/span>span classparams>()/span> {/span>br>span classline> span classkeyword>for/span> (K candidateKey : candidateKeyQueue) {/span>br>span classline> span classkeyword>if/span> (!runningKeySet.contains(candidateKey)) {/span>br>span classline> runningKeySet.add(candidateKey);/span>br>span classline> span classkeyword>return/span> candidateKey;/span>br>span classline> }/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> span classliteral>null/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> Map<K, R> span classtitle function_>getSuccessResultMap/span>span classparams>()/span> {/span>br>span classline> span classkeyword>return/span> successResultMap;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> Map<K, Throwable> span classtitle function_>getErrorResultMap/span>span classparams>()/span> {/span>br>span classline> span classkeyword>return/span> errorResultMap;/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>h2 id源码(方案-2)>a href#源码(方案-2) classheaderlink title源码(方案 2)>/a>源码(方案 2)/h2>p>基于 executorService.invokeAll/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>span classline>70/span>br>span classline>71/span>br>span classline>72/span>br>span classline>73/span>br>span classline>74/span>br>span classline>75/span>br>span classline>76/span>br>span classline>77/span>br>span classline>78/span>br>span classline>79/span>br>span classline>80/span>br>span classline>81/span>br>span classline>82/span>br>span classline>83/span>br>span classline>84/span>br>span classline>85/span>br>span classline>86/span>br>span classline>87/span>br>span classline>88/span>br>span classline>89/span>br>span classline>90/span>br>span classline>91/span>br>span classline>92/span>br>span classline>93/span>br>span classline>94/span>br>span classline>95/span>br>span classline>96/span>br>span classline>97/span>br>span classline>98/span>br>span classline>99/span>br>span classline>100/span>br>span classline>101/span>br>span classline>102/span>br>span classline>103/span>br>span classline>104/span>br>span classline>105/span>br>span classline>106/span>br>span classline>107/span>br>span classline>108/span>br>span classline>109/span>br>span classline>110/span>br>span classline>111/span>br>span classline>112/span>br>span classline>113/span>br>span classline>114/span>br>span classline>115/span>br>span classline>116/span>br>span classline>117/span>br>span classline>118/span>br>span classline>119/span>br>span classline>120/span>br>span classline>121/span>br>span classline>122/span>br>span classline>123/span>br>span classline>124/span>br>span classline>125/span>br>/pre>/td>td classcode>pre>span classline>span classkeyword>package/span> com.lyloou.component.util.concurrent;/span>br>span classline>/span>br>span classline>span classkeyword>import/span> cn.hutool.core.collection.CollUtil;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.date.DateUtil;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.date.TimeInterval;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.lang.Assert;/span>br>span classline>span classkeyword>import/span> cn.hutool.core.thread.ThreadUtil;/span>br>span classline>span classkeyword>import/span> lombok.SneakyThrows;/span>br>span classline>/span>br>span classline>span classkeyword>import/span> java.util.*;/span>br>span classline>span classkeyword>import/span> java.util.concurrent.Callable;/span>br>span classline>span classkeyword>import/span> java.util.concurrent.ConcurrentHashMap;/span>br>span classline>span classkeyword>import/span> java.util.concurrent.ExecutorService;/span>br>span classline>span classkeyword>import/span> java.util.function.BiFunction;/span>br>span classline>/span>br>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 并发执行器/span>/span>br>span classline>span classcomment> * <p>/span>/span>br>span classline>span classcomment> * 适用场景:每个任务是独立的,不耦合的/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@author/span> lilou/span>/span>br>span classline>span classcomment> * span classdoctag>@since/span> 2022/6/9 9:05/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>ConcurrentExecutor2/span><K, V, R> {/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 任务参数映射(K:key的类型,V:值的类型)/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<K, V> paramMap;/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 成功的任务结果映射/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<K, R> successResultMap;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 失败的任务结果映射/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> Map<K, Throwable> errorResultMap;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 执行器/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> ExecutorService executorService;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 具体任务策略/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>private/span> span classkeyword>final/span> BiFunction<K, V, R> biFunction;/span>br>span classline>/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classtitle function_>ConcurrentExecutor2/span>span classparams>(span classtype>int/span> maxThreadNum, Map<K, V> paramMap, BiFunction<K, V, R> biFunction)/span> {/span>br>span classline> Assert.notNull(paramMap, span classstring>"paramMap不可为空"/span>);/span>br>span classline> Assert.isTrue(maxThreadNum > span classnumber>0/span>, span classstring>"maxThreadNum不可小于1"/span>);/span>br>span classline>/span>br>span classline> span classcomment>// 同时运行的最大线程数量/span>/span>br>span classline> span classtype>int/span> span classvariable>maxThreadNum1/span> span classoperator>/span> Math.min(maxThreadNum, paramMap.size());/span>br>span classline> span classcomment>// tips: 如果错误地使用 this.paramMap paramMap; 多测试几遍会发现,偶尔会陷入了阻塞/span>/span>br>span classline> span classbuilt_in>this/span>.paramMap Collections.synchronizedMap(paramMap);/span>br>span classline> span classbuilt_in>this/span>.biFunction biFunction;/span>br>span classline> span classbuilt_in>this/span>.executorService ThreadUtil.newExecutor(maxThreadNum1, maxThreadNum1, Integer.MAX_VALUE);/span>br>span classline> span classbuilt_in>this/span>.successResultMap span classkeyword>new/span> span classtitle class_>ConcurrentHashMap/span><>(span classbuilt_in>this/span>.paramMap.size());/span>br>span classline> span classbuilt_in>this/span>.errorResultMap span classkeyword>new/span> span classtitle class_>ConcurrentHashMap/span><>();/span>br>span classline> }/span>br>span classline>/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>execute/span>span classparams>()/span> span classkeyword>throws/span> InterruptedException {/span>br>span classline> span classkeyword>while/span> (CollUtil.isNotEmpty(paramMap)) {/span>br>span classline> List<Callable<R>> callableList span classkeyword>new/span> span classtitle class_>ArrayList/span><>();/span>br>span classline> paramMap.forEach((k, v) -> callableList.add(() -> {/span>br>span classline> span classkeyword>try/span> {/span>br>span classline> span classkeyword>final/span> span classtype>R/span> span classvariable>result/span> span classoperator>/span> biFunction.apply(k, v);/span>br>span classline> successResultMap.put(k, result);/span>br>span classline> } span classkeyword>catch/span> (Exception e) {/span>br>span classline> errorResultMap.put(k, e);/span>br>span classline> } span classkeyword>finally/span> {/span>br>span classline> paramMap.remove(k);/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> span classliteral>null/span>;/span>br>span classline> }));/span>br>span classline> span classcomment>// 在线程池中运行任务/span>/span>br>span classline> executorService.invokeAll(callableList);/span>br>span classline> executorService.shutdown();/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> Map<K, R> span classtitle function_>getSuccessResultMap/span>span classparams>()/span> {/span>br>span classline> span classkeyword>return/span> successResultMap;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> Map<K, Throwable> span classtitle function_>getErrorResultMap/span>span classparams>()/span> {/span>br>span classline> span classkeyword>return/span> errorResultMap;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 测试/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> span classkeyword>throws/span> InterruptedException {/span>br>span classline> span classkeyword>final/span> span classtype>TimeInterval/span> span classvariable>timer/span> span classoperator>/span> DateUtil.timer();/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>0/span>; i < span classnumber>100/span>; i++) {/span>br>span classline> test();/span>br>span classline> }/span>br>span classline> System.out.println(timer.intervalMs());/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>private/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>test/span>span classparams>()/span> span classkeyword>throws/span> InterruptedException {/span>br>span classline> Map<String, String> paramMap span classkeyword>new/span> span classtitle class_>LinkedHashMap/span><>();/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>0/span>; i < span classnumber>10/span>; i++) {/span>br>span classline> paramMap.put(span classstring>"key:"/span> + i, span classstring>"value:"/span> + i);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>final/span> ConcurrentExecutor2<String, String, Integer> executor span classkeyword>new/span> span classtitle class_>ConcurrentExecutor2/span><>(span classnumber>5/span>, paramMap,/span>br>span classline> (k, v) -> {/span>br>span classline> ThreadUtil.sleep(span classnumber>10/span>);/span>br>span classline> System.out.println(Thread.currentThread().getName() + span classstring>"-"/span> + v);/span>br>span classline> span classkeyword>final/span> span classtype>int/span> span classvariable>abs/span> span classoperator>/span> Math.abs(Objects.hash(v));/span>br>span classline> span classkeyword>if/span> (abs % span classnumber>3/span> span classnumber>0/span>) {/span>br>span classline> span classtype>int/span> span classvariable>i/span> span classoperator>/span> span classnumber>1/span> / span classnumber>0/span>;/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> abs;/span>br>span classline> });/span>br>span classline> executor.execute();/span>br>span classline> System.out.println(span classstring>"success result: "/span> + executor.getSuccessResultMap());/span>br>span classline> System.out.println(span classstring>"error result: "/span> + executor.getErrorResultMap());/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/linux/ftp/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/linux/ftp/ classpost-title-link itempropurl>Ftp/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-05-26 09:56:53 itempropdateCreated datePublished datetime2022-05-26T09:56:53+08:00>2022-05-26/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> p>a target_blank relnoopener hrefhttps://hostadvice.com/how-to/how-to-install-and-configure-vsftpd-on-ubuntu-18-04/>How to Install and Configure vsftpd on Ubuntu 18.04 | HostAdvice/a>/p>p>a target_blank relnoopener hrefhttps://blog.csdn.net/soslinken/article/details/79304076>ubuntu 使用vsftpd 创建FTP服务(用户名密码登录,限制列出目录)_迦蓝叶的博客-CSDN博客_ubuntu vsftpd添加用户/a>/p> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/java/Equable/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/java/Equable/ classpost-title-link itempropurl>【Java】通过 Getter 方法引用,来比较两个对象是否相等/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-04-09 18:52:50 itempropdateCreated datePublished datetime2022-04-09T18:52:50+08:00>2022-04-09/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> h4 id背景>a href#背景 classheaderlink title背景>/a>背景/h4>p>编写代码时,会经常需要编写两个对象是否相等的逻辑,一般会有如下做法/p>ol>li>直接写在业务代码中;/li>li>单独写个方法,业务代码中调用;/li>li>重写 equals 方法;/li>/ol>p>上面这些做法,都比较复杂,如果属性太多或复杂点(如果是 list 和 map 就更复杂了),就需要编写更多的判断逻辑代码了。/p>h4 id想法>a href#想法 classheaderlink title想法>/a>想法/h4>p>如果能只需要提供比较的方法引用列表,有个地方能自动方法引用取值,并比较就好了。/p>h4 id思路-1>a href#思路-1 classheaderlink title思路 1>/a>思路 1/h4>ol>li>在 java8 中可以使用方法引用,如:People::getName;/li>li>可以将所有要比较的 Getter 保存到列表中;/li>li>在 比较的时候,根据 方法引用获取具体的值进行比较;/li>li>全部比较都相等了,就认为是相等的。/li>/ol>h4 id思路-2>a href#思路-2 classheaderlink title思路 2>/a>思路 2/h4>ol>li>思路 1 适用于需要比较的字段少时,有一种情况是,需要比较的字段多,只想排除掉少量字段/li>li>通过注解来忽略指定的字段/li>li>获取全部字段,过滤掉忽略的字段,通过反射比较字段对应的值。/li>/ol>h4 id举个例子-1-改造前>a href#举个例子-1-改造前 classheaderlink title举个例子 1(改造前)>/a>举个例子 1(改造前)/h4>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>/pre>/td>td classcode>pre>span classline>span classmeta>@Getter/span>/span>br>span classline>span classmeta>@Setter/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>EqualDemo/span> span classkeyword>implements/span> span classtitle class_>Equable/span> {/span>br>span classline>/span>br>span classline> span classkeyword>private/span> Integer id;/span>br>span classline> span classkeyword>private/span> Integer age;/span>br>span classline> span classkeyword>private/span> String username;/span>br>span classline> span classkeyword>private/span> Date createTime;/span>br>span classline> span classkeyword>private/span> Date updateTime;/span>br>span classline> span classkeyword>private/span> List<EqualDemo> list;/span>br>span classline> span classkeyword>private/span> Map<String, EqualDemo> map;/span>br>span classline>/span>br>span classline> span classmeta>@Override/span>/span>br>span classline> span classkeyword>public/span> span classtype>boolean/span> span classtitle function_>equals/span>span classparams>(Object obj)/span> {/span>br>span classline> span classkeyword>if/span> (obj span classkeyword>instanceof/span> EqualDemo) {/span>br>span classline> span classkeyword>if/span> (!Objects.equals(((EqualDemo) obj).getId(), span classbuilt_in>this/span>.getId())) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (!Objects.equals(((EqualDemo) obj).getAge(), span classbuilt_in>this/span>.getAge())) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (!Objects.equals(((EqualDemo) obj).getUsername(), span classbuilt_in>this/span>.getUsername())) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline> span classkeyword>final/span> List<EqualDemo> list1 ((EqualDemo) obj).getList();/span>br>span classline> span classkeyword>final/span> List<EqualDemo> list2 span classbuilt_in>this/span>.getList();/span>br>span classline> span classcomment>// todo 比较 list1 和 list2/span>/span>br>span classline>/span>br>span classline> span classkeyword>final/span> Map<String, EqualDemo> map1 ((EqualDemo) obj).getMap();/span>br>span classline> span classkeyword>final/span> Map<String, EqualDemo> map2 span classbuilt_in>this/span>.getMap();/span>br>span classline> span classcomment>// todo 比较 map1 和 map2/span>/span>br>span classline>/span>br>span classline>/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> Objects.equals(span classbuilt_in>this/span>, obj);/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>span classline>span classcomment>// 使用/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>EqualDemoTest/span> {/span>br>span classline> span classmeta>@Test/span>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>testSimpleTrue/span>span classparams>()/span> {/span>br>span classline> span classkeyword>final/span> span classtype>EqualDemo/span> span classvariable>s1/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>EqualDemo/span>();/span>br>span classline> s1.setId(span classnumber>1/span>);/span>br>span classline> s1.setUsername(span classstring>"bob"/span>);/span>br>span classline>/span>br>span classline> span classkeyword>final/span> span classtype>EqualDemo/span> span classvariable>s2/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>EqualDemo/span>();/span>br>span classline> s2.setId(span classnumber>1/span>);/span>br>span classline> s2.setUsername(span classstring>"bob"/span>);/span>br>span classline>/span>br>span classline> span classcomment>// // s1 和 s2 相等/span>/span>br>span classline> span classkeyword>assert/span> s1.equals(s2);/span>br>span classline> }/span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure>h4 id举个例子-2-改造后-指定需要比较的字段的-Getter-方法引用>a href#举个例子-2-改造后-指定需要比较的字段的-Getter-方法引用 classheaderlink title举个例子 2(改造后-指定需要比较的字段的 Getter 方法引用)>/a>举个例子 2(改造后-指定需要比较的字段的 Getter 方法引用)/h4>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>/pre>/td>td classcode>pre>span classline>span classmeta>@Getter/span>/span>br>span classline>span classmeta>@Setter/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>OnlyEqualDemo/span> span classkeyword>implements/span> span classtitle class_>Equable/span> {/span>br>span classline>/span>br>span classline> span classkeyword>private/span> Integer id;/span>br>span classline>/span>br>span classline> span classkeyword>private/span> Integer age;/span>br>span classline>/span>br>span classline> span classkeyword>private/span> String username;/span>br>span classline> span classkeyword>private/span> Date createTime;/span>br>span classline> span classkeyword>private/span> Date updateTime;/span>br>span classline> span classkeyword>private/span> List<OnlyEqualDemo> list;/span>br>span classline> span classkeyword>private/span> Map<String, OnlyEqualDemo> map;/span>br>span classline>/span>br>span classline>/span>br>span classline> span classmeta>@SuppressWarnings("unchecked")/span>/span>br>span classline> span classmeta>@Override/span>/span>br>span classline> span classkeyword>public/span> List<EqualGetter<OnlyEqualDemo>> span classtitle function_>listOnlyEqualsToGetter/span>span classparams>()/span> {/span>br>span classline> span classkeyword>final/span> EqualGetter<OnlyEqualDemo> getId OnlyEqualDemo::getId;/span>br>span classline> span classkeyword>return/span> Arrays.asList(/span>br>span classline> getId,/span>br>span classline> OnlyEqualDemo::getAge,/span>br>span classline> OnlyEqualDemo::getUsername,/span>br>span classline> OnlyEqualDemo::getList,/span>br>span classline> OnlyEqualDemo::getMap/span>br>span classline> );/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>span classline>/span>br>span classline>span classcomment>// 使用/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>OnlyEqualDemoTest/span> {/span>br>span classline>/span>br>span classline>/span>br>span classline> span classmeta>@Test/span>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>testSimpleTrue/span>span classparams>()/span> {/span>br>span classline> span classkeyword>final/span> span classtype>OnlyEqualDemo/span> span classvariable>s1/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>OnlyEqualDemo/span>();/span>br>span classline> s1.setId(span classnumber>1/span>);/span>br>span classline> s1.setUsername(span classstring>"bob"/span>);/span>br>span classline>/span>br>span classline> span classkeyword>final/span> span classtype>OnlyEqualDemo/span> span classvariable>s2/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>OnlyEqualDemo/span>();/span>br>span classline> s2.setId(span classnumber>1/span>);/span>br>span classline> s2.setUsername(span classstring>"bob"/span>);/span>br>span classline>/span>br>span classline> span classcomment>// // s1 和 s2 相等/span>/span>br>span classline> span classkeyword>assert/span> s1.onlyEqualsTo(s2);/span>br>span classline> }/span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure>h4 id举个例子-3-改造后-排除少量字段>a href#举个例子-3-改造后-排除少量字段 classheaderlink title举个例子 3(改造后-排除少量字段)>/a>举个例子 3(改造后-排除少量字段)/h4>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>/pre>/td>td classcode>pre>span classline>span classmeta>@Getter/span>/span>br>span classline>span classmeta>@Setter/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>IgnoreEqualDemo/span> span classkeyword>implements/span> span classtitle class_>Equable/span> {/span>br>span classline>/span>br>span classline> span classkeyword>private/span> Integer id;/span>br>span classline>/span>br>span classline> span classmeta>@EqualIgnored/span>/span>br>span classline> span classkeyword>private/span> Integer age;/span>br>span classline>/span>br>span classline> span classkeyword>private/span> String username;/span>br>span classline>/span>br>span classline> span classmeta>@EqualIgnored/span>/span>br>span classline> span classkeyword>private/span> Date createTime;/span>br>span classline>/span>br>span classline> span classmeta>@EqualIgnored/span>/span>br>span classline> span classkeyword>private/span> Date updateTime;/span>br>span classline>/span>br>span classline> span classkeyword>private/span> List<IgnoreEqualDemo> list;/span>br>span classline> span classkeyword>private/span> Map<String, IgnoreEqualDemo> map;/span>br>span classline>}/span>br>span classline>/span>br>span classline>span classcomment>// 使用/span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>IgnoreEqualDemoTest/span> {/span>br>span classline>/span>br>span classline>/span>br>span classline> span classmeta>@Test/span>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>testSimpleTrue/span>span classparams>()/span> {/span>br>span classline> span classkeyword>final/span> span classtype>IgnoreEqualDemo/span> span classvariable>s1/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>IgnoreEqualDemo/span>();/span>br>span classline> s1.setId(span classnumber>1/span>);/span>br>span classline> s1.setUsername(span classstring>"bob"/span>);/span>br>span classline> s1.setCreateTime(span classkeyword>new/span> span classtitle class_>Date/span>());/span>br>span classline>/span>br>span classline> span classkeyword>final/span> span classtype>IgnoreEqualDemo/span> span classvariable>s2/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>IgnoreEqualDemo/span>();/span>br>span classline> s2.setId(span classnumber>1/span>);/span>br>span classline> s2.setUsername(span classstring>"bob"/span>);/span>br>span classline>/span>br>span classline> span classcomment>// // s1 和 s2 相等/span>/span>br>span classline> span classkeyword>assert/span> s1.ignoreEqualsTo(s2);/span>br>span classline> }/span>br>span classline>}/span>br>/pre>/td>/tr>/table>/figure>p>这样就简洁很多了,由于 ignoreEqualsTo 和 onlyEqualsTo 方法是 Equable 接口中的默认方法,具体逻辑全封装起来了(包括 object, collection 和 map 的处理),不需要重写就可以直接使用,具体实现看下面的源码。/p>h4 id源码>a href#源码 classheaderlink title源码>/a>源码/h4>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>span classline>70/span>br>span classline>71/span>br>span classline>72/span>br>span classline>73/span>br>span classline>74/span>br>span classline>75/span>br>span classline>76/span>br>span classline>77/span>br>span classline>78/span>br>span classline>79/span>br>span classline>80/span>br>span classline>81/span>br>span classline>82/span>br>span classline>83/span>br>span classline>84/span>br>span classline>85/span>br>span classline>86/span>br>span classline>87/span>br>span classline>88/span>br>span classline>89/span>br>span classline>90/span>br>span classline>91/span>br>span classline>92/span>br>span classline>93/span>br>span classline>94/span>br>span classline>95/span>br>span classline>96/span>br>span classline>97/span>br>span classline>98/span>br>span classline>99/span>br>span classline>100/span>br>span classline>101/span>br>span classline>102/span>br>span classline>103/span>br>span classline>104/span>br>span classline>105/span>br>span classline>106/span>br>span classline>107/span>br>span classline>108/span>br>span classline>109/span>br>span classline>110/span>br>span classline>111/span>br>span classline>112/span>br>span classline>113/span>br>span classline>114/span>br>span classline>115/span>br>span classline>116/span>br>span classline>117/span>br>span classline>118/span>br>span classline>119/span>br>span classline>120/span>br>span classline>121/span>br>span classline>122/span>br>span classline>123/span>br>span classline>124/span>br>span classline>125/span>br>span classline>126/span>br>span classline>127/span>br>span classline>128/span>br>span classline>129/span>br>span classline>130/span>br>span classline>131/span>br>span classline>132/span>br>span classline>133/span>br>span classline>134/span>br>span classline>135/span>br>span classline>136/span>br>span classline>137/span>br>span classline>138/span>br>span classline>139/span>br>span classline>140/span>br>span classline>141/span>br>span classline>142/span>br>span classline>143/span>br>span classline>144/span>br>span classline>145/span>br>span classline>146/span>br>span classline>147/span>br>span classline>148/span>br>span classline>149/span>br>span classline>150/span>br>span classline>151/span>br>span classline>152/span>br>span classline>153/span>br>span classline>154/span>br>span classline>155/span>br>span classline>156/span>br>span classline>157/span>br>span classline>158/span>br>span classline>159/span>br>span classline>160/span>br>span classline>161/span>br>span classline>162/span>br>span classline>163/span>br>span classline>164/span>br>span classline>165/span>br>span classline>166/span>br>span classline>167/span>br>span classline>168/span>br>span classline>169/span>br>span classline>170/span>br>span classline>171/span>br>span classline>172/span>br>span classline>173/span>br>span classline>174/span>br>span classline>175/span>br>span classline>176/span>br>span classline>177/span>br>span classline>178/span>br>span classline>179/span>br>span classline>180/span>br>span classline>181/span>br>span classline>182/span>br>span classline>183/span>br>span classline>184/span>br>span classline>185/span>br>span classline>186/span>br>span classline>187/span>br>span classline>188/span>br>span classline>189/span>br>span classline>190/span>br>span classline>191/span>br>span classline>192/span>br>span classline>193/span>br>span classline>194/span>br>span classline>195/span>br>span classline>196/span>br>span classline>197/span>br>span classline>198/span>br>span classline>199/span>br>span classline>200/span>br>span classline>201/span>br>span classline>202/span>br>span classline>203/span>br>span classline>204/span>br>span classline>205/span>br>span classline>206/span>br>span classline>207/span>br>span classline>208/span>br>span classline>209/span>br>span classline>210/span>br>span classline>211/span>br>span classline>212/span>br>span classline>213/span>br>span classline>214/span>br>span classline>215/span>br>span classline>216/span>br>span classline>217/span>br>span classline>218/span>br>span classline>219/span>br>span classline>220/span>br>/pre>/td>td classcode>pre>span classline>/span>br>span classline>span classkeyword>import/span> lombok.SneakyThrows;/span>br>span classline>/span>br>span classline>span classkeyword>import/span> java.beans.PropertyDescriptor;/span>br>span classline>span classkeyword>import/span> java.io.Serializable;/span>br>span classline>span classkeyword>import/span> java.lang.reflect.Field;/span>br>span classline>span classkeyword>import/span> java.lang.reflect.Method;/span>br>span classline>span classkeyword>import/span> java.util.*;/span>br>span classline>span classkeyword>import/span> java.util.function.BiFunction;/span>br>span classline>span classkeyword>import/span> java.util.stream.Collectors;/span>br>span classline>/span>br>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 比较两个对象是否相等/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@author/span> lilou/span>/span>br>span classline>span classcomment> * span classdoctag>@date/span> 2022/4/9 9:30/span>/span>br>span classline>span classcomment> * <p>/span>/span>br>span classline>span classcomment> * span classdoctag>@see/span> Equable#onlyEqualsTo(Equable) 方法1:通过 Getter方法引用 来指定需要比较的字段(场景:字段总量多,但是只需要比较少量字段时)/span>/span>br>span classline>span classcomment> * span classdoctag>@see/span> Equable#ignoreEqualsTo(Equable) 方法2:通过忽略注解({span classdoctag>@code/span> EqualIgnored})来指定忽略比较的字段,未标识的字段会全部参与比较(场景:字段总量多,但是只需要排除少量字段时)/span>/span>br>span classline>span classcomment> * 注意:onlyEqualsTo 和 ignoreEqualsTo 不要混用/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>interface/span> span classtitle class_>Equable/span> span classkeyword>extends/span> span classtitle class_>Serializable/span> {/span>br>span classline> span classtype>long/span> span classvariable>serialVersionUID/span> span classoperator>/span> span classnumber>1L/span>;/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 使用方法引用来比较,只比较指定的 Getter 方法引用。/span>/span>br>span classline>span classcomment> * 使用此方法:重写 listOnlyEqualsToGetter 方法,指定需要比较的字段的Getter方法引用/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> other 另一个 model/span>/span>br>span classline>span classcomment> * span classdoctag>@return/span> 结果/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>default/span> span classtype>boolean/span> span classtitle function_>onlyEqualsTo/span>span classparams>(Equable other)/span> {/span>br>span classline> span classkeyword>final/span> List<EqualGetter<Equable>> getterList listOnlyEqualsToGetter();/span>br>span classline>/span>br>span classline> span classcomment>// getter方法引用列表中没有需要比较的 getter,直接比较对象/span>/span>br>span classline> span classkeyword>if/span> (getterList span classliteral>null/span> || getterList.isEmpty()) {/span>br>span classline> span classkeyword>return/span> Objects.equals(other, span classbuilt_in>this/span>);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 列表有值,计算两个对象在列表中 getter 值,并比较是否相等/span>/span>br>span classline> span classkeyword>for/span> (EqualGetter<Equable> equalGetter : getterList) {/span>br>span classline> span classtype>Object/span> span classvariable>o1/span> span classoperator>/span> equalGetter.apply(span classbuilt_in>this/span>);/span>br>span classline> span classtype>Object/span> span classvariable>o2/span> span classoperator>/span> equalGetter.apply(other);/span>br>span classline>/span>br>span classline> span classcomment>// 对于属性中也有实现了 Equable 接口的,递归调用/span>/span>br>span classline> span classkeyword>if/span> (o1 span classkeyword>instanceof/span> Equable && o2 span classkeyword>instanceof/span> Equable) span classkeyword>return/span> ((Equable) o1).onlyEqualsTo((Equable) o2);/span>br>span classline>/span>br>span classline> span classcomment>// equalTo collection/span>/span>br>span classline> span classkeyword>if/span> (o1 span classkeyword>instanceof/span> Collection && o2 span classkeyword>instanceof/span> Collection) {/span>br>span classline> span classcomment>// 判断不相等/span>/span>br>span classline> span classkeyword>if/span> (notEqualsCollection((Collection<?>) o1, (Collection<?>) o2, Equable::onlyEqualsTo)) span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline>/span>br>span classline> span classcomment>// 列表已经判断完了,开始下一个属性/span>/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// equalTo map/span>/span>br>span classline> span classkeyword>if/span> (o1 span classkeyword>instanceof/span> Map && o2 span classkeyword>instanceof/span> Map) {/span>br>span classline> span classkeyword>if/span> (notEqualsMap((Map<?, ?>) o1, (Map<?, ?>) o2, Equable::onlyEqualsTo)) span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> span classcomment>// 列表已经判断完了,开始下一个属性/span>/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (!Objects.equals(o1, o2)) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>default/span> span classtype>boolean/span> span classtitle function_>notEqualsMap/span>span classparams>(Map<?, ?> o1, Map<?, ?> o2, BiFunction<Equable, Equable, Boolean> biFunc)/span> {/span>br>span classline> span classcomment>// 比较 key/span>/span>br>span classline> span classkeyword>final/span> Collection<?> set1 o1.keySet();/span>br>span classline> span classkeyword>final/span> Collection<?> set2 o2.keySet();/span>br>span classline> span classkeyword>if/span> (notEqualsCollection(set1, set2, biFunc)) span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline>/span>br>span classline> span classcomment>// 比较 value/span>/span>br>span classline> span classkeyword>final/span> Collection<?> values1 o1.values();/span>br>span classline> span classkeyword>final/span> Collection<?> values2 o2.values();/span>br>span classline> span classkeyword>return/span> notEqualsCollection(values1, values2, biFunc);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 判断 collection 是否不相等/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> o1 第一个 collection/span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> o2 第二个 collection/span>/span>br>span classline>span classcomment> * span classdoctag>@return/span> 是否不相等/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>default/span> span classtype>boolean/span> span classtitle function_>notEqualsCollection/span>span classparams>(Collection<?> o1, Collection<?> o2, BiFunction<Equable, Equable, Boolean> biFunc)/span> {/span>br>span classline> span classkeyword>if/span> (Objects.isNull(o1) && Objects.isNull(o2)) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (Objects.isNull(o1) || Objects.isNull(o2)) {/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (o1.isEmpty() && o2.isEmpty()) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (o1.size() ! o2.size()) {/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 根据 hashCode 来排序/span>/span>br>span classline> o1 o1.stream().sorted(Comparator.comparingInt(Object::hashCode)).collect(Collectors.toList());/span>br>span classline> o2 o2.stream().sorted(Comparator.comparingInt(Object::hashCode)).collect(Collectors.toList());/span>br>span classline>/span>br>span classline>/span>br>span classline> span classcomment>// 逐个比较/span>/span>br>span classline> span classkeyword>final/span> Iterator<?> iterator1 o1.iterator();/span>br>span classline> span classkeyword>final/span> Iterator<?> iterator2 o2.iterator();/span>br>span classline> span classkeyword>while/span> (iterator1.hasNext() && iterator2.hasNext()) {/span>br>span classline> span classkeyword>final/span> span classtype>Object/span> span classvariable>next1/span> span classoperator>/span> iterator1.next();/span>br>span classline> span classkeyword>final/span> span classtype>Object/span> span classvariable>next2/span> span classoperator>/span> iterator2.next();/span>br>span classline> span classkeyword>if/span> (next1 span classkeyword>instanceof/span> Equable && next2 span classkeyword>instanceof/span> Equable) {/span>br>span classline> span classkeyword>if/span> (!biFunc.apply((Equable) next1, (Equable) next2)) {/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline> } span classkeyword>else/span> {/span>br>span classline> span classkeyword>return/span> !Objects.equals(next1, next2);/span>br>span classline> }/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 需重写/span>/span>br>span classline>span classcomment> * <p>/span>/span>br>span classline>span classcomment> * 需要比较的 Getter 方法列表(原理是通过Getter 的 apply 方法得到实际的值,再进行比较)/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> <T> 泛型/span>/span>br>span classline>span classcomment> * span classdoctag>@return/span> getter 方法列表/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>default/span> <T span classkeyword>extends/span> span classtitle class_>Equable/span>> List<EqualGetter<T>> span classtitle function_>listOnlyEqualsToGetter/span>span classparams>()/span> {/span>br>span classline> span classkeyword>return/span> Collections.emptyList();/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * getter方法接口定义/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classmeta>@FunctionalInterface/span>/span>br>span classline> span classkeyword>interface/span> span classtitle class_>EqualGetter/span><T span classkeyword>extends/span> span classtitle class_>Equable/span>> span classkeyword>extends/span> span classtitle class_>Serializable/span> {/span>br>span classline> Object span classtitle function_>apply/span>span classparams>(T source)/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * IgnoreEqual 注解+反射来实现 equal 逻辑/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@param/span> other 另一个 model/span>/span>br>span classline>span classcomment> * span classdoctag>@return/span> 结果/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classmeta>@SneakyThrows/span>/span>br>span classline> span classkeyword>default/span> span classtype>boolean/span> span classtitle function_>ignoreEqualsTo/span>span classparams>(Equable other)/span> {/span>br>span classline> span classkeyword>if/span> (Objects.equals(span classbuilt_in>this/span>, other)) {/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>final/span> Class<? span classkeyword>extends/span> span classtitle class_>Equable/span>> aClass1 span classbuilt_in>this/span>.getClass();/span>br>span classline> span classkeyword>final/span> Class<? span classkeyword>extends/span> span classtitle class_>Equable/span>> aClass2 other.getClass();/span>br>span classline> span classkeyword>if/span> (!Objects.equals(aClass1, aClass2)) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>final/span> Field declaredFields aClass1.getDeclaredFields();/span>br>span classline> span classkeyword>for/span> (Field declaredField : declaredFields) {/span>br>span classline>/span>br>span classline> span classcomment>// 字段是否被标记忽略/span>/span>br>span classline> span classkeyword>final/span> span classtype>EqualIgnored/span> span classvariable>isIgnored/span> span classoperator>/span> declaredField.getAnnotation(EqualIgnored.class);/span>br>span classline> span classkeyword>if/span> (Objects.nonNull(isIgnored)) {/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>final/span> span classtype>PropertyDescriptor/span> span classvariable>propertyDescriptor/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>PropertyDescriptor/span>(declaredField.getName(), aClass1);/span>br>span classline> span classkeyword>final/span> span classtype>Method/span> span classvariable>readMethod/span> span classoperator>/span> propertyDescriptor.getReadMethod();/span>br>span classline>/span>br>span classline> span classkeyword>final/span> span classtype>Object/span> span classvariable>o1/span> span classoperator>/span> readMethod.invoke(span classbuilt_in>this/span>);/span>br>span classline> span classkeyword>final/span> span classtype>Object/span> span classvariable>o2/span> span classoperator>/span> readMethod.invoke(other);/span>br>span classline>/span>br>span classline> span classcomment>// 对于属性中也有实现了 Equable 接口的,递归调用/span>/span>br>span classline> span classkeyword>if/span> (o1 span classkeyword>instanceof/span> Equable && o2 span classkeyword>instanceof/span> Equable) span classkeyword>return/span> ((Equable) o1).ignoreEqualsTo((Equable) o2);/span>br>span classline>/span>br>span classline> span classcomment>// equalTo collection/span>/span>br>span classline> span classkeyword>if/span> (o1 span classkeyword>instanceof/span> Collection && o2 span classkeyword>instanceof/span> Collection) {/span>br>span classline> span classcomment>// 判断不相等/span>/span>br>span classline> span classkeyword>if/span> (notEqualsCollection((Collection<?>) o1, (Collection<?>) o2, Equable::ignoreEqualsTo)) span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline>/span>br>span classline> span classcomment>// 列表已经判断完了,开始下一个属性/span>/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// equalTo map/span>/span>br>span classline> span classkeyword>if/span> (o1 span classkeyword>instanceof/span> Map && o2 span classkeyword>instanceof/span> Map) {/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (notEqualsMap((Map<?, ?>) o1, (Map<?, ?>) o2, Equable::ignoreEqualsTo)) span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline>/span>br>span classline> span classcomment>// 列表已经判断完了,开始下一个属性/span>/span>br>span classline> span classkeyword>continue/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>if/span> (!Objects.equals(o1, o2)) {/span>br>span classline> span classkeyword>return/span> span classliteral>false/span>;/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>return/span> span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline>}/span>br>span classline>/span>br>span classline>/span>br>span classline>span classmeta>@Target({ElementType.FIELD})/span>/span>br>span classline>span classmeta>@Retention(RetentionPolicy.RUNTIME)/span>/span>br>span classline>span classmeta>@Documented/span>/span>br>span classline>span classkeyword>public/span> span classmeta>@interface/span> EqualIgnored {/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>h4 id单元测试>a href#单元测试 classheaderlink title单元测试>/a>单元测试/h4>p>strong>方法 1:/strong>/p>p>a target_blank relnoopener hrefhttps://github.com/lyloou/component/blob/master/component-dto/src/test/java/com/lyloou/component/dto/OnlyEqualDemoTest.java>https://github.com/lyloou/component/blob/master/component-dto/src/test/java/com/lyloou/component/dto/OnlyEqualDemoTest.java/a>br>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/Equable_20220410103323_2022-04-10-10-33-24.png altEquable_20220410103323_2022-04-10-10-33-24>/p>p>strong>方法 2:/strong>/p>p>a target_blank relnoopener hrefhttps://github.com/lyloou/component/blob/master/component-dto/src/test/java/com/lyloou/component/dto/IgnoreEqualDemoTest.java>https://github.com/lyloou/component/blob/master/component-dto/src/test/java/com/lyloou/component/dto/IgnoreEqualDemoTest.java/a>br>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/Equable_20220410103408_2022-04-10-10-34-09.png altEquable_20220410103408_2022-04-10-10-34-09>/p>h2 id参考资源>a href#参考资源 classheaderlink title参考资源>/a>参考资源/h2>ul>li>a target_blank relnoopener hrefhttps://github.com/lyloou/component/blob/master/component-dto/src/main/java/com/lyloou/component/dto/Equable.java>https://github.com/lyloou/component/blob/master/component-dto/src/main/java/com/lyloou/component/dto/Equable.java/a>/li>li>a target_blank relnoopener hrefhttps://github.com/lyloou/component/blob/master/component-dto/src/main/java/com/lyloou/component/dto/field/FieldUtil.java>https://github.com/lyloou/component/blob/master/component-dto/src/main/java/com/lyloou/component/dto/field/FieldUtil.java/a>/li>/ul> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/%E7%BD%91%E7%BB%9C/vpc/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/%E7%BD%91%E7%BB%9C/vpc/ classpost-title-link itempropurl>【网络】Vpc专有网络/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-02-15 09:12:02 itempropdateCreated datePublished datetime2022-02-15T09:12:02+08:00>2022-02-15/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> p>a target_blank relnoopener hrefhttps://developer.aliyun.com/article/58516>阿里云网络系列之经典网络和专有网络-阿里云开发者社区/a>br>a target_blank relnoopener hrefhttps://coolshell.me/articles/public-network-working-tutorial.html>科普一下公有云的网络 – 酷 壳 – CoolShell 3F/a>/p> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/linux/frps/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/linux/frps/ classpost-title-link itempropurl>【Linux】frps内网穿透软件/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-02-08 21:04:14 itempropdateCreated datePublished datetime2022-02-08T21:04:14+08:00>2022-02-08/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> p>frps 是一个优秀的内网穿透软件。/p>p>frps 下载安装:a target_blank relnoopener hrefhttps://github.com/fatedier/frp/releases>https://github.com/fatedier/frp/releases/a>/p>p>strong>服务端:/strong> code>./frps -c ./frps.ini/code>/p>p>frps.ini/p>figure classhighlight ini>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>/pre>/td>td classcode>pre>span classline>span classsection>common/span>/span>br>span classline>span classattr>bind_addr/span> span classnumber>0.0/span>.span classnumber>0.0/span>/span>br>span classline>span classattr>bind_port/span> span classnumber>7000/span>/span>br>span classline>/span>br>span classline>span classattr>bind_udp_port/span> span classnumber>7001/span>/span>br>span classline>/span>br>span classline>span classattr>dashboard_port/span> span classnumber>7500/span>/span>br>span classline>span classattr>dashboard_user/span> admin/span>br>span classline>span classattr>dashboard_pwd/span> admin/span>br>span classline>/span>br>span classline>span classattr>vhost_http_port/span> span classnumber>2780/span>/span>br>span classline>span classattr>subdomain_host/span> frps.example.com/span>br>/pre>/td>/tr>/table>/figure>p>strong>客户端:/strong> code>./frpc -c ./frpc.ini/code>/p>p>frpc.ini/p>figure classhighlight ini>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>/pre>/td>td classcode>pre>span classline>span classsection>common/span>/span>br>span classline>span classattr>server_addr/span> xx.xx.xx.xx/span>br>span classline>span classattr>server_port/span> span classnumber>7000/span>/span>br>span classline>span classattr>admin_addr/span> span classnumber>127.0/span>.span classnumber>0.1/span>/span>br>span classline>span classattr>admin_port/span> span classnumber>7400/span>/span>br>span classline>/span>br>span classline>span classsection>ssh/span>/span>br>span classline>span classattr>type/span> tcp/span>br>span classline>span classattr>local_ip/span> span classnumber>127.0/span>.span classnumber>0.1/span>/span>br>span classline>span classattr>local_port/span> span classnumber>22/span>/span>br>span classline>span classattr>remote_port/span> span classnumber>7022/span>/span>br>span classline>/span>br>span classline>span classsection>web/span>/span>br>span classline>span classattr>type/span> http/span>br>span classline>span classattr>local_port/span> span classnumber>2780/span>/span>br>span classline>span classattr>subdomain/span> span classliteral>off/span>ice/span>br>/pre>/td>/tr>/table>/figure>p>访问服务器端的 dashboard 查看统计信息: code>http://frps.example.com:7500//code>/p>p>访问内网 ssh: code>ssh -oPort7022 test@x.x.x.x/code>br>通过浏览器访问内网机器: code>http://office.frps.example.com:2780//code>/p>h2 id配置自动启动>a href#配置自动启动 classheaderlink title配置自动启动>/a>配置自动启动/h2>p>安装 supervisor/p>figure classhighlight sh>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>/pre>/td>td classcode>pre>span classline>apt install supervisor/span>br>span classline>/span>br>span classline>span classcomment># 查看 supervisor 状态/span>/span>br>span classline>service supervisor status/span>br>/pre>/td>/tr>/table>/figure>p>添加 frps 配置:code>vi /etc/supervisor/conf.d/frps.conf/code>/p>figure classhighlight sh>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>/pre>/td>td classcode>pre>span classline>program:frps/span>br>span classline>span classbuilt_in>command/span>/root/c/frp/frps -c /root/c/frp/frps.ini/span>br>span classline>autostartspan classliteral>true/span>/span>br>span classline>autorestartspan classliteral>true/span>/span>br>/pre>/td>/tr>/table>/figure>p>可以依次运行下面操作加载 新加入的 frps/p>figure classhighlight sh>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>/pre>/td>td classcode>pre>span classline>span classcomment># 告诉 supervisor 新加了配置/span>/span>br>span classline>supervisorctl reread/span>br>span classline>/span>br>span classline>span classcomment># 让 supervisor 启动 frps/span>/span>br>span classline>supervisorctl update/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>p>输入 supervisorctl 查看 frps 是否已运行/p>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/img/202202082113352.png alt202202082113352>/p>p>start 和 stop frpsbr>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/img/202202082114908.png alt202202082114908>/p>p>设置 supervisor 开机启动/p>figure classhighlight sh>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>/pre>/td>td classcode>pre>span classline>systemctl span classbuilt_in>enable/span> supervisor.service/span>br>span classline>systemctl daemon-reload/span>br>/pre>/td>/tr>/table>/figure>p>为 supervisor 添加 dashboard,通过 9001 来访问:/p>p>code>vi /etc/supervisor/supervisord.conf/code> 添加下面代码/p>figure classhighlight sh>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>/pre>/td>td classcode>pre>span classline>inet_http_server/span>br>span classline>port*:9001/span>br>span classline>usernameadmin/span>br>span classline>passwordadmin/span>br>/pre>/td>/tr>/table>/figure>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/img/202202082135628.png alt202202082135628>/p>h2 id参考资料>a href#参考资料 classheaderlink title参考资料>/a>参考资料/h2>p>a target_blank relnoopener hrefhttps://github.com/fatedier/frp>https://github.com/fatedier/frp/a>/p>p>a target_blank relnoopener hrefhttps://www.jianshu.com/p/219553bfeca9>通过 frp 实现访问内网 ssh 与 http 简明教程 - 简书/a>/p>p>a target_blank relnoopener hrefhttps://www.atlantic.net/vps-hosting/how-to-install-and-configure-supervisor-on-ubuntu-20-04/>How to Install and Configure Supervisor on Ubuntu 20.04 | Atlantic.Net/a>/p>figure classhighlight ini>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>/pre>/td>td classcode>pre>span classline>span classsection>program:nginx/span>/span>br>span classline>span classattr>command/span>/usr/sbin/nginx -g span classstring>"daemon off;"/span>/span>br>span classline>span classattr>autostart/span>span classliteral>true/span>/span>br>span classline>span classattr>autorestart/span>span classliteral>true/span>/span>br>span classline>span classattr>startretries/span>span classnumber>5/span>/span>br>span classline>span classattr>numprocs/span>span classnumber>1/span>/span>br>span classline>span classattr>startsecs/span>span classnumber>0/span>/span>br>span classline>span classattr>process_name/span>%(program_name)s_%(process_num)span classnumber>02/span>d/span>br>span classline>span classattr>stderr_logfile/span>/var/log/supervisor/%(program_name)s_stderr.log/span>br>span classline>span classattr>stderr_logfile_maxbytes/span>span classnumber>10/span>MB/span>br>span classline>span classattr>stdout_logfile/span>/var/log/supervisor/%(program_name)s_stdout.log/span>br>span classline>span classattr>stdout_logfile_maxbytes/span>span classnumber>10/span>MB/span>br>/pre>/td>/tr>/table>/figure>p>a target_blank relnoopener hrefhttps://www.92ez.com/?actionshow&id23484>使用 supervisor 设置服务端 frp 开机启动 - 一只猿 - 前端攻城尸 | 安全研究员 | 硬件控 | 业余极客 | 开源拥护者/a>/p>p>a target_blank relnoopener hrefhttps://www.bookstack.cn/read/frp/README_zh.md>frp - 《frp 中文文档》 - 书栈网 · BookStack/a>/p> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/windows/win11/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/windows/win11/ classpost-title-link itempropurl>【Windows】win11相关/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-02-03 18:32:15 itempropdateCreated datePublished datetime2022-02-03T18:32:15+08:00>2022-02-03/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> h2 id桌面>a href#桌面 classheaderlink title桌面>/a>桌面/h2>h2 id关闭弹性滚动>a href#关闭弹性滚动 classheaderlink title关闭弹性滚动>/a>关闭弹性滚动/h2>p>进入:code>edge://flags//code>/p>p>disable code>Microsoft Edge scrolling personality/code>/p>h2 id恢复-win10-桌面右键菜单>a href#恢复-win10-桌面右键菜单 classheaderlink title恢复 win10 桌面右键菜单>/a>恢复 win10 桌面右键菜单/h2>p>a target_blank relnoopener hrefhttps://blog.csdn.net/admans/article/details/121302883>Win11 恢复 Win10 经典右键菜单 亲测有效_admans 的专栏-CSDN 博客_win11 换回 win10 右键/a>/p>p>管理员权限运行/p>figure classhighlight bat>table>tr>td classgutter>pre>span classline>1/span>br>/pre>/td>td classcode>pre>span classline>reg.exe add "HKCU\Software\Classes\CLSID\{span classnumber>86/span>ca1aa0-span classnumber>34/span>aa-span classnumber>4/span>e8b-a509-span classnumber>50/span>c905bae2a2}\InprocServer32" /f /ve/span>br>/pre>/td>/tr>/table>/figure>p>重启资源管理器:br>code>taskkill /f /im explorer.exe&&explorer.exe/code>/p>blockquote>p>a target_blank relnoopener hrefhttps://zhidao.baidu.com/question/1365850274792601979.html?qblrelate_question_2>cmd /c taskkill /f /im explorer.exe&&explorer.exe 这命令什么意思_百度知道/a>/p>/blockquote>p>恢复 win11/p>figure classhighlight bat>table>tr>td classgutter>pre>span classline>1/span>br>/pre>/td>td classcode>pre>span classline>reg.exe delete "HKCU\Software\Classes\CLSID\{span classnumber>86/span>ca1aa0-span classnumber>34/span>aa-span classnumber>4/span>e8b-a509-span classnumber>50/span>c905bae2a2}\InprocServer32" /va /f/span>br>/pre>/td>/tr>/table>/figure>p>其它方案:startAllback 软件/p> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/%E7%AE%97%E6%B3%95/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/%E7%AE%97%E6%B3%95/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91/ classpost-title-link itempropurl>【算法】从上到下打印二叉树/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-01-24 18:55:50 itempropdateCreated datePublished datetime2022-01-24T18:55:50+08:00>2022-01-24/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> h2 id剑指-Offer-第-32-题-从上到下打印二叉树>a href#剑指-Offer-第-32-题-从上到下打印二叉树 classheaderlink title剑指 Offer 第 32 题-从上到下打印二叉树>/a>剑指 Offer 第 32 题-从上到下打印二叉树/h2>p>描述/p>p>输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回 true ,否则返回 false 。假设输入的数组的任意两个数字都互不相同。br>数据范围: 节点数量 0≤n≤1000 ,节点上的值满足 1≤val≤10^5,保证节点上的值各不相同/p>p>要求:空间复杂度 O(n) ,时间时间复杂度 O(n^2)/p>p>提示:/p>p>1.二叉搜索树是指父亲节点大于左子树中的全部节点,但是小于右子树中的全部节点的树。/p>p>2.该题我们约定空树不是二叉搜索树/p>p>3.后序遍历是指按照 “左子树-右子树-根节点” 的顺序遍历/p>p>4.参考下面的二叉搜索树,示例 1br>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91_20220124175723_2022-01-24-17-57-24.png altjz32-从上到下打印二叉树_20220124175723_2022-01-24-17-57-24>/p>h2 id方法-1>a href#方法-1 classheaderlink title方法 1>/a>方法 1/h2>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91_20220124175628_2022-01-24-17-56-29.png altjz32-从上到下打印二叉树_20220124175628_2022-01-24-17-56-29>/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>/pre>/td>td classcode>pre>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 从上往下/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@author/span> lilou/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>Jz32/span> {/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classkeyword>final/span> span classtype>Jz32/span> span classvariable>jz/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>Jz32/span>();/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>root/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>8/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node10/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>10/span>);/span>br>span classline> root.left span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>6/span>);/span>br>span classline> root.right node10;/span>br>span classline> node10.left span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>1/span>);/span>br>span classline> node10.right span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>2/span>);/span>br>span classline> System.out.println(jz.PrintFromTopToBottom(root));/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> ArrayList<Integer> span classtitle function_>PrintFromTopToBottom/span>span classparams>(TreeNode root)/span> {/span>br>span classline> span classkeyword>if/span> (root span classliteral>null/span>) {/span>br>span classline> span classkeyword>return/span> span classkeyword>new/span> span classtitle class_>ArrayList/span><>();/span>br>span classline> }/span>br>span classline> span classkeyword>final/span> ArrayList<Integer> list span classkeyword>new/span> span classtitle class_>ArrayList/span><>();/span>br>span classline> Queue<TreeNode> queue span classkeyword>new/span> span classtitle class_>LinkedList/span><>();/span>br>span classline> queue.offer(root);/span>br>span classline>/span>br>span classline> span classkeyword>while/span> (!queue.isEmpty()) {/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node/span> span classoperator>/span> queue.poll();/span>br>span classline> list.add(node.val);/span>br>span classline> span classkeyword>if/span> (node.left ! span classliteral>null/span>) {/span>br>span classline> queue.offer(node.left);/span>br>span classline> }/span>br>span classline> span classkeyword>if/span> (node.right ! span classliteral>null/span>) {/span>br>span classline> queue.offer(node.right);/span>br>span classline> }/span>br>span classline> }/span>br>span classline> span classkeyword>return/span> list;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>class/span> span classtitle class_>TreeNode/span> {/span>br>span classline> span classtype>int/span> span classvariable>val/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline> span classtype>TreeNode/span> span classvariable>left/span> span classoperator>/span> span classliteral>null/span>;/span>br>span classline> span classtype>TreeNode/span> span classvariable>right/span> span classoperator>/span> span classliteral>null/span>;/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classtitle function_>TreeNode/span>span classparams>(span classtype>int/span> val)/span> {/span>br>span classline> span classbuilt_in>this/span>.val val;/span>br>span classline>/span>br>span classline> }/span>br>span classline>/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>h2 id扩展-按层次打印>a href#扩展-按层次打印 classheaderlink title扩展-按层次打印>/a>扩展-按层次打印/h2>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91_20220124175928_2022-01-24-17-59-28.png altjz32-从上到下打印二叉树_20220124175928_2022-01-24-17-59-28>/p>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91_20220124175801_2022-01-24-17-58-01.png altjz32-从上到下打印二叉树_20220124175801_2022-01-24-17-58-01>/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>/pre>/td>td classcode>pre>span classline>span classkeyword>package/span> algorithm.jzoffer;/span>br>span classline>/span>br>span classline>span classkeyword>import/span> java.util.LinkedList;/span>br>span classline>span classkeyword>import/span> java.util.Queue;/span>br>span classline>/span>br>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 按层次打印/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@author/span> lilou/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>Jz32_3/span> {/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classkeyword>final/span> span classtype>Jz32_3/span> span classvariable>jz/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>Jz32_3/span>();/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>root/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>8/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node10/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>10/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node6/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>6/span>);/span>br>span classline> root.left node6;/span>br>span classline> root.right node10;/span>br>span classline> node10.left span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>1/span>);/span>br>span classline> node10.right span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>2/span>);/span>br>span classline> node6.left span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>7/span>);/span>br>span classline> node6.right span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>11/span>);/span>br>span classline>/span>br>span classline> jz.PrintFromTopToBottom(root);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>PrintFromTopToBottom/span>span classparams>(TreeNode root)/span> {/span>br>span classline> span classkeyword>if/span> (root span classliteral>null/span>) {/span>br>span classline> span classkeyword>return/span>;/span>br>span classline> }/span>br>span classline> Queue<TreeNode> queue span classkeyword>new/span> span classtitle class_>LinkedList/span><>();/span>br>span classline> queue.offer(root);/span>br>span classline> span classtype>int/span> span classvariable>toBePrint/span> span classoperator>/span> span classnumber>1/span>;/span>br>span classline> span classtype>int/span> span classvariable>nextLevel/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline>/span>br>span classline> span classkeyword>while/span> (!queue.isEmpty()) {/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node/span> span classoperator>/span> queue.poll();/span>br>span classline> System.out.printf(span classstring>"%s\t"/span>, node.val);/span>br>span classline> span classkeyword>if/span> (node.left ! span classliteral>null/span>) {/span>br>span classline> queue.offer(node.left);/span>br>span classline> nextLevel++;/span>br>span classline> }/span>br>span classline> span classkeyword>if/span> (node.right ! span classliteral>null/span>) {/span>br>span classline> queue.offer(node.right);/span>br>span classline> nextLevel++;/span>br>span classline> }/span>br>span classline> toBePrint--;/span>br>span classline> span classkeyword>if/span> (toBePrint span classnumber>0/span>) {/span>br>span classline> System.out.println();/span>br>span classline> toBePrint nextLevel;/span>br>span classline> nextLevel span classnumber>0/span>;/span>br>span classline> }/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>class/span> span classtitle class_>TreeNode/span> {/span>br>span classline> span classtype>int/span> span classvariable>val/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline> span classtype>TreeNode/span> span classvariable>left/span> span classoperator>/span> span classliteral>null/span>;/span>br>span classline> span classtype>TreeNode/span> span classvariable>right/span> span classoperator>/span> span classliteral>null/span>;/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classtitle function_>TreeNode/span>span classparams>(span classtype>int/span> val)/span> {/span>br>span classline> span classbuilt_in>this/span>.val val;/span>br>span classline>/span>br>span classline> }/span>br>span classline>/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>h2 id扩展-按「之」字打印>a href#扩展-按「之」字打印 classheaderlink title扩展-按「之」字打印>/a>扩展-按「之」字打印/h2>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91_20220124175912_2022-01-24-17-59-13.png altjz32-从上到下打印二叉树_20220124175912_2022-01-24-17-59-13>br>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz32-%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91_20220124175849_2022-01-24-17-58-49.png altjz32-从上到下打印二叉树_20220124175849_2022-01-24-17-58-49>/p>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>span classline>70/span>br>span classline>71/span>br>span classline>72/span>br>span classline>73/span>br>span classline>74/span>br>span classline>75/span>br>span classline>76/span>br>span classline>77/span>br>span classline>78/span>br>span classline>79/span>br>span classline>80/span>br>span classline>81/span>br>span classline>82/span>br>span classline>83/span>br>span classline>84/span>br>span classline>85/span>br>span classline>86/span>br>span classline>87/span>br>span classline>88/span>br>span classline>89/span>br>span classline>90/span>br>span classline>91/span>br>span classline>92/span>br>span classline>93/span>br>span classline>94/span>br>span classline>95/span>br>span classline>96/span>br>/pre>/td>td classcode>pre>span classline>span classkeyword>package/span> algorithm.jzoffer;/span>br>span classline>/span>br>span classline>span classkeyword>import/span> java.util.Stack;/span>br>span classline>/span>br>span classline>span classcomment>/**/span>/span>br>span classline>span classcomment> * 按之字打印/span>/span>br>span classline>span classcomment> */span>/span>br>span classline>span classcomment> * span classdoctag>@author/span> lilou/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>Jz32_4/span> {/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classkeyword>final/span> span classtype>Jz32_4/span> span classvariable>jz/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>Jz32_4/span>();/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node1/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>1/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node2/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>2/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node3/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>3/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node4/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>4/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node5/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>5/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node6/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>6/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node7/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>7/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node8/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>8/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node9/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>9/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node10/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>10/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node11/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>11/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node12/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>12/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node13/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>13/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node14/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>14/span>);/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node15/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>TreeNode/span>(span classnumber>15/span>);/span>br>span classline> node1.left node2;/span>br>span classline> node1.right node3;/span>br>span classline> node2.left node4;/span>br>span classline> node2.right node5;/span>br>span classline> node3.left node6;/span>br>span classline> node3.right node7;/span>br>span classline> node4.left node8;/span>br>span classline> node4.right node9;/span>br>span classline> node5.left node10;/span>br>span classline> node5.right node11;/span>br>span classline> node6.left node12;/span>br>span classline> node6.right node13;/span>br>span classline> node7.left node14;/span>br>span classline> node7.right node15;/span>br>span classline>/span>br>span classline> jz.PrintFromTopToBottom(node1);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>void/span> span classtitle function_>PrintFromTopToBottom/span>span classparams>(TreeNode root)/span> {/span>br>span classline> span classkeyword>if/span> (root span classliteral>null/span>) {/span>br>span classline> span classkeyword>return/span>;/span>br>span classline> }/span>br>span classline> Stack<TreeNode> stack1 span classkeyword>new/span> span classtitle class_>Stack/span><>();/span>br>span classline> Stack<TreeNode> stack2 span classkeyword>new/span> span classtitle class_>Stack/span><>();/span>br>span classline> stack1.push(root);/span>br>span classline>/span>br>span classline> span classkeyword>while/span> (!stack1.isEmpty() || !stack2.isEmpty()) {/span>br>span classline> span classkeyword>while/span> (!stack1.isEmpty()) {/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node/span> span classoperator>/span> stack1.pop();/span>br>span classline> System.out.printf(span classstring>"%s\t"/span>, node.val);/span>br>span classline> span classkeyword>if/span> (node.left ! span classliteral>null/span>) {/span>br>span classline> stack2.push(node.left);/span>br>span classline> }/span>br>span classline> span classkeyword>if/span> (node.right ! span classliteral>null/span>) {/span>br>span classline> stack2.push(node.right);/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 下一层/span>/span>br>span classline> System.out.println();/span>br>span classline> span classkeyword>while/span> (!stack2.isEmpty()) {/span>br>span classline> span classkeyword>final/span> span classtype>TreeNode/span> span classvariable>node/span> span classoperator>/span> stack2.pop();/span>br>span classline> System.out.printf(span classstring>"%s\t"/span>, node.val);/span>br>span classline> span classkeyword>if/span> (node.right ! span classliteral>null/span>) {/span>br>span classline> stack1.push(node.right);/span>br>span classline> }/span>br>span classline> span classkeyword>if/span> (node.left ! span classliteral>null/span>) {/span>br>span classline> stack1.push(node.left);/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> System.out.println();/span>br>span classline> }/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>class/span> span classtitle class_>TreeNode/span> {/span>br>span classline> span classtype>int/span> span classvariable>val/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline> span classtype>TreeNode/span> span classvariable>left/span> span classoperator>/span> span classliteral>null/span>;/span>br>span classline> span classtype>TreeNode/span> span classvariable>right/span> span classoperator>/span> span classliteral>null/span>;/span>br>span classline>/span>br>span classline> span classkeyword>public/span> span classtitle function_>TreeNode/span>span classparams>(span classtype>int/span> val)/span> {/span>br>span classline> span classbuilt_in>this/span>.val val;/span>br>span classline>/span>br>span classline> }/span>br>span classline>/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> div classpost-block> article itemscope itemtypehttp://schema.org/Article classpost-content lang> link itempropmainEntityOfPage hrefhttps://lyloou.com/%E7%AE%97%E6%B3%95/jz29-%E9%A1%BA%E6%97%B6%E9%92%88%E6%89%93%E5%8D%B0%E7%9F%A9%E9%98%B5/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropimage content/assets/images/avatar.png> meta itempropname contentlyloou> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname contentlyloou> meta itempropdescription content/* Better than last best */> /span> span hidden itemproppost itemscope itemtypehttp://schema.org/CreativeWork> meta itempropname contentundefined | lyloou> meta itempropdescription content> /span> header classpost-header> h2 classpost-title itempropname headline> a href/%E7%AE%97%E6%B3%95/jz29-%E9%A1%BA%E6%97%B6%E9%92%88%E6%89%93%E5%8D%B0%E7%9F%A9%E9%98%B5/ classpost-title-link itempropurl>【算法】顺时针打印矩阵/a> /h2> div classpost-meta-container> div classpost-meta> span classpost-meta-item> span classpost-meta-item-icon> i classfar fa-calendar>/i> /span> span classpost-meta-item-text>发表于/span> time title创建时间:2022-01-21 17:05:58 itempropdateCreated datePublished datetime2022-01-21T17:05:58+08:00>2022-01-21/time> /span> /div> /div> /header> div classpost-body itemproparticleBody> h2 id剑指-Offer-第-23-题-链表中环的入口结点>a href#剑指-Offer-第-23-题-链表中环的入口结点 classheaderlink title剑指 Offer 第 23 题-链表中环的入口结点>/a>a target_blank relnoopener hrefhttps://www.nowcoder.com/practice/9b4c81a02cd34f76be2659fa0d54342a>剑指 Offer 第 23 题-链表中环的入口结点/a>/h2>p>描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下 4 X 4 矩阵:/p>figure classhighlight inform7>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>/pre>/td>td classcode>pre>span classline>span classcomment>span classcomment>1,2,3,4/span>,/span>/span>br>span classline>span classcomment>span classcomment>5,6,7,8/span>,/span>/span>br>span classline>span classcomment>span classcomment>9,10,11,12/span>,/span>/span>br>span classline>span classcomment>span classcomment>13,14,15,16/span>/span>/span>br>/pre>/td>/tr>/table>/figure>p>则依次打印出数字/p>p>1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10/p>p>数据范围:/p>p>0 < matrix.length < 100/p>p>0 < matrixi.length < 100/p>p>例如:/p>p>img srchttps://cdn.jsdelivr.net/gh/lyloou/img/jz29-%E9%A1%BA%E6%97%B6%E9%92%88%E6%89%93%E5%8D%B0%E7%9F%A9%E9%98%B5_20220121170748_2022-01-21-17-07-49.png altjz29-顺时针打印矩阵_20220121170748_2022-01-21-17-07-49>/p>h2 id方法-1>a href#方法-1 classheaderlink title方法 1>/a>方法 1/h2>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>span classline>70/span>br>span classline>71/span>br>span classline>72/span>br>span classline>73/span>br>span classline>74/span>br>span classline>75/span>br>span classline>76/span>br>span classline>77/span>br>span classline>78/span>br>span classline>79/span>br>span classline>80/span>br>/pre>/td>td classcode>pre>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>Jz29_2/span> {/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classkeyword>final/span> span classtype>Jz29_3_1/span> span classvariable>jz/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>Jz29_3_1/span>();/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>, span classnumber>2/span>, span classnumber>3/span>, span classnumber>1/span>},/span>br>span classline> {span classnumber>4/span>, span classnumber>5/span>, span classnumber>6/span>, span classnumber>1/span>},/span>br>span classline> {span classnumber>4/span>, span classnumber>5/span>, span classnumber>6/span>, span classnumber>1/span>},/span>br>span classline> }));/span>br>span classline>/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>}, {span classnumber>2/span>}, {span classnumber>3/span>}, {span classnumber>4/span>}, {span classnumber>5/span>}/span>br>span classline> }));/span>br>span classline>/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>, span classnumber>2/span>, span classnumber>3/span>, span classnumber>4/span>, span classnumber>5/span>}/span>br>span classline> }));/span>br>span classline>/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>, span classnumber>2/span>, span classnumber>3/span>, span classnumber>4/span>},/span>br>span classline> {span classnumber>5/span>, span classnumber>6/span>, span classnumber>7/span>, span classnumber>8/span>},/span>br>span classline> {span classnumber>9/span>, span classnumber>10/span>, span classnumber>11/span>, span classnumber>12/span>},/span>br>span classline> {span classnumber>13/span>, span classnumber>14/span>, span classnumber>15/span>, span classnumber>16/span>}/span>br>span classline> }));/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 对于只有一行或只有一列时,会重复/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> ArrayList<Integer> span classtitle function_>printMatrix/span>span classparams>(span classtype>int/span> matrix)/span> {/span>br>span classline> span classcomment>// 为空的情况/span>/span>br>span classline> span classkeyword>if/span> (matrix span classliteral>null/span> || matrix.length span classnumber>0/span>) {/span>br>span classline> span classkeyword>return/span> span classkeyword>new/span> span classtitle class_>ArrayList/span><>();/span>br>span classline> }/span>br>span classline>/span>br>span classline> ArrayList<Integer> list span classkeyword>new/span> span classtitle class_>ArrayList/span><>(matrix.length * matrixspan classnumber>0/span>.length);/span>br>span classline> span classtype>int/span> span classvariable>minX/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline> span classtype>int/span> span classvariable>maxX/span> span classoperator>/span> matrix.length - span classnumber>1/span>;/span>br>span classline> span classtype>int/span> span classvariable>minY/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline> span classtype>int/span> span classvariable>maxY/span> span classoperator>/span> matrixspan classnumber>0/span>.length - span classnumber>1/span>;/span>br>span classline>/span>br>span classline> span classtype>int/span> x, y;/span>br>span classline> span classkeyword>while/span> (minX < maxX && minY < maxY) {/span>br>span classline> span classcomment>// 用两个标识来判断本轮是否有下移或左移/span>/span>br>span classline> span classtype>boolean/span> span classvariable>down/span> span classoperator>/span> span classliteral>false/span>;/span>br>span classline> span classtype>boolean/span> span classvariable>left/span> span classoperator>/span> span classliteral>false/span>;/span>br>span classline>/span>br>span classline> span classcomment>// 从左上角开始/span>/span>br>span classline> span classcomment>// 向右/span>/span>br>span classline> span classkeyword>for/span> (x minX, y minY; y < maxY; y++) {/span>br>span classline> list.add(matrixxy);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 向下/span>/span>br>span classline> span classkeyword>for/span> (x minX + span classnumber>1/span>, y maxY; x < maxX; x++) {/span>br>span classline> list.add(matrixxy);/span>br>span classline> down span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 向左,左移之前确认是否有下移,防止重复/span>/span>br>span classline> span classkeyword>for/span> (x maxX, y maxY - span classnumber>1/span>; down && y > minY; y--) {/span>br>span classline> list.add(matrixxy);/span>br>span classline> left span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 向上,上移之前确认是否有左移,防止重复/span>/span>br>span classline> span classkeyword>for/span> (x maxX - span classnumber>1/span>, y minY; left && x > minX; x--) {/span>br>span classline> list.add(matrixxy);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 瘦身一圈/span>/span>br>span classline> minX++;/span>br>span classline> maxX--;/span>br>span classline> minY++;/span>br>span classline> maxY--;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>return/span> list;/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure>h2 id方法-2>a href#方法-2 classheaderlink title方法 2>/a>方法 2/h2>figure classhighlight java>table>tr>td classgutter>pre>span classline>1/span>br>span classline>2/span>br>span classline>3/span>br>span classline>4/span>br>span classline>5/span>br>span classline>6/span>br>span classline>7/span>br>span classline>8/span>br>span classline>9/span>br>span classline>10/span>br>span classline>11/span>br>span classline>12/span>br>span classline>13/span>br>span classline>14/span>br>span classline>15/span>br>span classline>16/span>br>span classline>17/span>br>span classline>18/span>br>span classline>19/span>br>span classline>20/span>br>span classline>21/span>br>span classline>22/span>br>span classline>23/span>br>span classline>24/span>br>span classline>25/span>br>span classline>26/span>br>span classline>27/span>br>span classline>28/span>br>span classline>29/span>br>span classline>30/span>br>span classline>31/span>br>span classline>32/span>br>span classline>33/span>br>span classline>34/span>br>span classline>35/span>br>span classline>36/span>br>span classline>37/span>br>span classline>38/span>br>span classline>39/span>br>span classline>40/span>br>span classline>41/span>br>span classline>42/span>br>span classline>43/span>br>span classline>44/span>br>span classline>45/span>br>span classline>46/span>br>span classline>47/span>br>span classline>48/span>br>span classline>49/span>br>span classline>50/span>br>span classline>51/span>br>span classline>52/span>br>span classline>53/span>br>span classline>54/span>br>span classline>55/span>br>span classline>56/span>br>span classline>57/span>br>span classline>58/span>br>span classline>59/span>br>span classline>60/span>br>span classline>61/span>br>span classline>62/span>br>span classline>63/span>br>span classline>64/span>br>span classline>65/span>br>span classline>66/span>br>span classline>67/span>br>span classline>68/span>br>span classline>69/span>br>span classline>70/span>br>span classline>71/span>br>span classline>72/span>br>span classline>73/span>br>span classline>74/span>br>span classline>75/span>br>span classline>76/span>br>span classline>77/span>br>span classline>78/span>br>span classline>79/span>br>/pre>/td>td classcode>pre>span classline>span classkeyword>public/span> span classkeyword>class/span> span classtitle class_>Jz29_4/span> {/span>br>span classline> span classkeyword>public/span> span classkeyword>static/span> span classkeyword>void/span> span classtitle function_>main/span>span classparams>(String args)/span> {/span>br>span classline> span classkeyword>final/span> span classtype>Jz29_4/span> span classvariable>jz/span> span classoperator>/span> span classkeyword>new/span> span classtitle class_>Jz29_4/span>();/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>, span classnumber>2/span>, span classnumber>3/span>, span classnumber>1/span>},/span>br>span classline> {span classnumber>4/span>, span classnumber>5/span>, span classnumber>6/span>, span classnumber>1/span>},/span>br>span classline> {span classnumber>4/span>, span classnumber>5/span>, span classnumber>6/span>, span classnumber>1/span>},/span>br>span classline> }));/span>br>span classline>/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>}, {span classnumber>2/span>}, {span classnumber>3/span>}, {span classnumber>4/span>}, {span classnumber>5/span>}/span>br>span classline> }));/span>br>span classline>/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>, span classnumber>2/span>, span classnumber>3/span>, span classnumber>4/span>, span classnumber>5/span>}/span>br>span classline> }));/span>br>span classline>/span>br>span classline> System.out.println(jz.printMatrix(span classkeyword>new/span> span classtitle class_>int/span>{/span>br>span classline> {span classnumber>1/span>, span classnumber>2/span>, span classnumber>3/span>, span classnumber>4/span>},/span>br>span classline> {span classnumber>5/span>, span classnumber>6/span>, span classnumber>7/span>, span classnumber>8/span>},/span>br>span classline> {span classnumber>9/span>, span classnumber>10/span>, span classnumber>11/span>, span classnumber>12/span>},/span>br>span classline> {span classnumber>13/span>, span classnumber>14/span>, span classnumber>15/span>, span classnumber>16/span>}/span>br>span classline> }));/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>/**/span>/span>br>span classline>span classcomment> * 起始点从左上角,沿对角线往中间靠/span>/span>br>span classline>span classcomment> *//span>/span>br>span classline> span classkeyword>public/span> ArrayList<Integer> span classtitle function_>printMatrix/span>span classparams>(span classtype>int/span> matrix)/span> {/span>br>span classline> span classcomment>// 为空的情况/span>/span>br>span classline> span classkeyword>if/span> (matrix span classliteral>null/span> || matrix.length span classnumber>0/span>) {/span>br>span classline> span classkeyword>return/span> span classkeyword>new/span> span classtitle class_>ArrayList/span><>();/span>br>span classline> }/span>br>span classline>/span>br>span classline> ArrayList<Integer> list span classkeyword>new/span> span classtitle class_>ArrayList/span><>(matrix.length * matrixspan classnumber>0/span>.length);/span>br>span classline> span classtype>int/span> span classvariable>start/span> span classoperator>/span> span classnumber>0/span>;/span>br>span classline> span classkeyword>while/span> (matrix.length > start * span classnumber>2/span> && matrixspan classnumber>0/span>.length > start * span classnumber>2/span>) {/span>br>span classline> addToList(list, matrix, start);/span>br>span classline> start++;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>return/span> list;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classkeyword>private/span> span classkeyword>void/span> span classtitle function_>addToList/span>span classparams>(ArrayList<Integer> list, span classtype>int/span> matrix, span classtype>int/span> start)/span> {/span>br>span classline>/span>br>span classline> span classcomment>// max row index/span>/span>br>span classline> span classtype>int/span> span classvariable>maxX/span> span classoperator>/span> matrix.length - span classnumber>1/span> - start;/span>br>span classline> span classcomment>// max column index/span>/span>br>span classline> span classtype>int/span> span classvariable>maxY/span> span classoperator>/span> matrixspan classnumber>0/span>.length - span classnumber>1/span> - start;/span>br>span classline>/span>br>span classline> span classtype>boolean/span> span classvariable>down/span> span classoperator>/span> span classliteral>false/span>;/span>br>span classline> span classtype>boolean/span> span classvariable>left/span> span classoperator>/span> span classliteral>false/span>;/span>br>span classline>/span>br>span classline> span classcomment>// 从左向右/span>/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> start; i < maxY; ++i) {/span>br>span classline> list.add(matrixstarti);/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 从上向下/span>/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> start + span classnumber>1/span>; i < maxX; i++) {/span>br>span classline> list.add(matriximaxY);/span>br>span classline> down span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 从右向左/span>/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> maxY - span classnumber>1/span>; down && i > start; i--) {/span>br>span classline> list.add(matrixmaxXi);/span>br>span classline> left span classliteral>true/span>;/span>br>span classline> }/span>br>span classline>/span>br>span classline> span classcomment>// 从下向上/span>/span>br>span classline> span classkeyword>for/span> (span classtype>int/span> span classvariable>i/span> span classoperator>/span> maxX - span classnumber>1/span>; left && i > start + span classnumber>1/span>; i--) {/span>br>span classline> list.add(matrixistart);/span>br>span classline> }/span>br>span classline>/span>br>span classline> }/span>br>span classline>}/span>br>span classline>/span>br>/pre>/td>/tr>/table>/figure> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article>/div> nav classpagination> span classpage-number current>1/span>a classpage-number href/page/2/>2/a>span classspace>…/span>a classpage-number href/page/32/>32/a>a classextend next relnext title下一页 aria-label下一页 href/page/2/>i classfa fa-angle-right>/i>/a> /nav>/div> /main> footer classfooter> div classfooter-inner> div classbeian>a hrefhttps://beian.miit.gov.cn/ relnoopener target_blank>粤ICP备18151128号 /a> /div>div classcopyright> © span itempropcopyrightYear>2023/span> span classwith-love> i classfa fa-heart>/i> /span> span classauthor itempropcopyrightHolder>lyloou/span>/div>div classbusuanzi-count> span classpost-meta-item idbusuanzi_container_site_uv> span classpost-meta-item-icon> i classfa fa-user>/i> /span> span classsite-uv title总访客量> span idbusuanzi_value_site_uv>/span> /span> /span> span classpost-meta-item idbusuanzi_container_site_pv> span classpost-meta-item-icon> i classfa fa-eye>/i> /span> span classsite-pv title总访问量> span idbusuanzi_value_site_pv>/span> /span> /span>/div> div classpowered-by>由 a hrefhttps://hexo.io/ relnoopener target_blank>Hexo/a> & a hrefhttps://theme-next.js.org/mist/ relnoopener target_blank>NexT.Mist/a> 强力驱动 /div> /div> /footer> div classtoggle sidebar-toggle rolebutton> span classtoggle-line>/span> span classtoggle-line>/span> span classtoggle-line>/span> /div> div classsidebar-dimmer>/div> div classback-to-top rolebutton aria-label返回顶部> i classfa fa-arrow-up fa-lg>/i> span>0%/span> /div>noscript> div classnoscript-warning>Theme NexT works best with JavaScript enabled/div>/noscript> script srchttps://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js integritysha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY crossoriginanonymous>/script> script srchttps://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js integritysha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao crossoriginanonymous>/script>script src/js/comments.js>/script>script src/js/utils.js>/script>script src/js/motion.js>/script>script src/js/schemes/muse.js>/script>script src/js/next-boot.js>/script>script src/js/pjax.js>/script> script srchttps://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js integritysha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc crossoriginanonymous>/script>script src/js/third-party/search/local-search.js>/script> script data-pjax async srchttps://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js>/script>script classnext-config data-namegiscus typeapplication/json>{enable:true,repo:lyloou/lyloou.github.io,repo_id:MDEwOlJlcG9zaXRvcnkxMDk1NzkyNzA,category:Announcements,category_id:DIC_kwDOBogMBs4CWdfR,mapping:pathname,reactions_enabled:1,emit_metadata:1,theme:light,lang:zh-CN,input_position:bottom,loading:lazy}/script>script>document.addEventListener(page:loaded, () > { if (!CONFIG.page.comments) return; NexT.utils.loadComments(.giscus-container) .then(() > NexT.utils.getScript(https://giscus.app/client.js, { attributes: { async : true, crossOrigin : anonymous, data-repo : CONFIG.giscus.repo, data-repo-id : CONFIG.giscus.repo_id, data-category : CONFIG.giscus.category, data-category-id : CONFIG.giscus.category_id, data-mapping : CONFIG.giscus.mapping, data-reactions-enabled: CONFIG.giscus.reactions_enabled, data-emit-metadata : CONFIG.giscus.emit_metadata, data-theme : CONFIG.giscus.theme, data-lang : CONFIG.giscus.lang, data-input-position : CONFIG.giscus.input_position, data-loading : CONFIG.giscus.loading }, parentNode: document.querySelector(.giscus-container) }));});/script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]