-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
843 lines (616 loc) · 63.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.8.0">
<meta charset="utf-8">
<title>Homocysteine</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:type" content="website">
<meta property="og:title" content="Homocysteine">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="Homocysteine">
<meta property="og:locale" content="default">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Homocysteine">
<link rel="alternate" href="/atom.xml" title="Homocysteine" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/style.css">
</head>
</html>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">Homocysteine</a>
</h1>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-Java-I-O" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/07/02/Java-I-O/" class="article-date">
<time datetime="2020-07-02T13:35:12.000Z" itemprop="datePublished">2020-07-02</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/07/02/Java-I-O/">Java-I/O</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#BIO<br>InputStream、OutputStream(基于字节流,读取二进制文件)文件流、数据流、对象流<br>Reader、Writer(基于字符流,读取文本文件)</p>
<p>传统I/O是阻塞式的,当我们调用reader或者writer的时候,再有数据可以读取前,线程都是被阻塞的<br>NIO可以在等待数据时,让线程不阻塞,继续做其他的事情</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/07/02/Java-I-O/" data-id="ckc4v5z1s000a7wwzjeig0pyu" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-Android提升" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/07/01/Android提升/" class="article-date">
<time datetime="2020-07-01T01:34:18.000Z" itemprop="datePublished">2020-07-01</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/07/01/Android提升/">Android提升</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#Handler</p>
<ol>
<li>在非ui线程中更新ui会抛出calledFromWrongThreadException</li>
<li>Android为了线程安全,并不允许非ui线程去更新ui</li>
<li>handler是一套用来更新ui、处理消息的机制</li>
<li>所有activity生命周期的函数都是通过handler去发送消息的,根据不同的message做不同的分支处理</li>
<li><p>不遵循handler就无法更新ui,Android已经封装好了消息的创建、传递、处理机制<br>关键点:更新ui、处理消息(发送/接收)</p>
</li>
<li><p>我们在创建Handler时,它会和一个默认的线程绑定,在这个默认的线程中会有一个MessageQueue</p>
</li>
<li>ui线程会创建一个looper</li>
</ol>
<p>#Handler用法</p>
<ol>
<li>ui线程创建handler实例,重写handlerMessage方法,在该方法中更新ui;在子线程中创建Message方法,用handler对象去sendMessage</li>
<li>在ui线程中创建Hanlder实例,在子线程中用handler.post(new Runnable)的方式,在run方法去更新ui<br>ps:接口和抽象类是不能进行实例化的,实际上是一种内部类的简写。java创建了一个实现Runnable接口的无名内部类</li>
<li>利用post.delayed方法在子线程中更新ui线程(Runnable,时间),实现一个倒计时的界面;自动切换页面;定时更新图片<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">MyRunnable myRunnable = new <span class="function"><span class="title">MyRunnable</span></span>(){</span><br><span class="line"> @Override</span><br><span class="line"> public void <span class="function"><span class="title">run</span></span>(){</span><br><span class="line"> index++;</span><br><span class="line"> index=index%3;</span><br><span class="line"> imageView.setImageResource(images[index]);</span><br><span class="line"> handler.postDelayed(myRunnable,time);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">在onCreate()中</span><br><span class="line">handler.postDelayed(Runnable,time);</span><br><span class="line"></span><br><span class="line">Message message = new Message();</span><br><span class="line">或者 Message message = handler.obtainMessage();//查看是否有空的message可复用,如果没有,则new出一个新的</span><br><span class="line">message.arg1=88;</span><br><span class="line">message.obj=student;</span><br><span class="line">handle.sendMessage(message);</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>#Handler原理</p>
<ol>
<li>作用:更新ui、处理消息</li>
<li>目的:解决多线程并发问题</li>
<li>线程安全问题:临界资源+多线程操作<br>在不加锁的情况下,多个线程更新ui会导致界面错乱<br>在加锁处理的情况下,将导致程序性能下降</li>
<li>所以使用Handler机制,所有更新ui的操作,都在主线程的消息队列中进行轮询处理</li>
</ol>
<p>#handler、Looper和MessageQueue的关系</p>
<ol>
<li>Looper的内部包含一个MessageQueue,用来存储消息,在UI线程中</li>
<li>Handler在构造时会和Looper进行关联</li>
<li>Handler负责发送Message(sendMessage)给MessageQueue</li>
<li>Looper从MessageQueue中取出待处理的消息,回发给Handler,执行handleMessage的方法</li>
<li>Looper接收到Handler发送的消息,并把消息回发给Handler(handleMessage)</li>
</ol>
<p>#ActivityThread</p>
<ol>
<li>在ActivityThread中创建Activity,以及调用回调方法,默认创建一个线程(main线程、ui线程)</li>
<li>在ui线程中会创建looper,looper会创建messageQueue</li>
</ol>
<p>#自定义控件</p>
<ol>
<li>目的:为了达到特别的显示效果、特色功能<br>步骤1:在attrs.xml中定义声明<br>步骤2:在layout xml中使用<br>步骤3:编写继承自已有控件的Java类,内部编写控件逻辑</li>
</ol>
<p>#布局优化<br>Activity->fragment</p>
<ol>
<li>include优化标签<br>在一个布局中引入另一个布局,方便布局文件统一风格,减少开发和维护时的工作量(引入公共部分,统一的导航栏、广告栏,类似于import)</li>
<li>merge<br>减少布局嵌套层次,提高布局加载效率,是include的辅助扩展<br>将引入布局的根节点改成merge标签,减少布局的嵌套</li>
<li>viewstub<br>用viewstub引入一个布局,只有加载该布局时,才占用资源,不可见的控件是不会绘制出来的<br>不可见的情况下,是不会加载这个资源的,适合用于报告网络异常状况<br>不可见,不加载</li>
</ol>
<p>#内存优化<br>内存泄漏:申请的内存没有正确被回收,导致这部分内存自身无法使用,别的程序也无法使用。如果不加以控制,程序所占用的内存将会越来越大,最终导致死机。<br>原因:</p>
<ol>
<li>Java Native Interface,C/C++编写</li>
<li>调用来外部服务</li>
</ol>
<p>Bitmap对象要及时recycle<br>注册了Android系统的服务,要及时注销。LocationManager、PowerManager</p>
<p>#View的绘制过程</p>
<ol>
<li><p>测量尺寸<br>重写onMeasure<br>View测量自身,决定自身所占范围<br>由mode和值确定<br>三种MODE:<br>EXACTLY:明确规定<br>AT_MOST: 至多不能超过某个值<br>UNSPECIFIED:没有限制</p>
</li>
<li><p>确定View位置<br>重写onLayout,决定子View的位置<br>定义类似于RelativeLayout、LinearLayout的显示规则</p>
</li>
<li><p>绘制View<br>重写onDraw,绘制出内容区域</p>
</li>
</ol>
<p>#Retrofit</p>
<ol>
<li>一个网络请求库,以okHttp框架作为httpclient</li>
<li>通过注解简化网络请求 GET PUT</li>
<li>网络请求转化成Interface的形式</li>
<li>在接口中编写请求方法</li>
<li>使用时创建Retrofit对象,执行请求方法,获得返回对象</li>
</ol>
<p>#多进程 VS 多线程<br>王牌金句:进程是资源分配的最小单位,线程是CPU调度的最小单位</p>
<ol>
<li>多进程鲁棒性更高,线程挂了进程也挂了</li>
<li><p>多进程可以进行并行多核的计算(python)</p>
</li>
<li><p>数据共享方面:多线程利于数据的共享</p>
</li>
<li><p>切换:多线程更快,线程没有独立的内存地址,不需要进行内存地址的转换</p>
</li>
<li><p>需求,推送进程</p>
</li>
</ol>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/07/01/Android提升/" data-id="ckc4v5z1i00057wwzmlt3z5he" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-KMP算法" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/30/KMP算法/" class="article-date">
<time datetime="2020-06-30T09:21:57.000Z" itemprop="datePublished">2020-06-30</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/30/KMP算法/">KMP算法</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#算法本质流程<br>在主串和子串匹配的过程中,如果发现又不匹配的字符,则去检查字串已经匹配过的部分。<br>如果已经匹配过的部分存在公共前后缀,则从前缀后面的那一个字符开始接下来的匹配<br>如果不存在公共前后缀,则从头开始</p>
<p>#算法流程</p>
<ol>
<li>构建next数组<br>next[0]肯定为0;<br>从索引1开始到最后一个,如果相等的话,next[j]值就在上一个基础上+1<br>如果不等的话,next[j]的值就变成和next[j-1]作为索引的元素去比较</li>
</ol>
<p>创建一个和char数组p长度一样的int类型next数组<br>初始化两个指针,next[0]<br>循环硬背流,条件是数组长度减一,内部条件是k初值或jk元素相等<br>相等则移动指针,用k作为当前next[j]的值<br>不相等则用next[k]的值来作为新的k值<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">int k=-1,j=0;</span><br><span class="line">next[0]=-1;</span><br><span class="line"><span class="keyword">while</span>(p<p.length-1){</span><br><span class="line"> <span class="keyword">if</span>(k==-1||p[k]==p[j]){</span><br><span class="line"> k++;</span><br><span class="line"> j++;</span><br><span class="line"> next[j]=k;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"> k = next[k];</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">return</span> next</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>利用next数组进行匹配<br>i,j初始化都为0。i是源串指针,j是模式指针<br>最外层循环时两个串都不越界<br>内部条件是j==-1或者对应字符相等<br>这样就移动两个指针<br>否则,将j指针更新为next[j]值</p>
<p>结束部分是如果j(模式串指针)等于模式传长度,则返回两个指针之差<br>否则返回-1<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(i<pattern.length && j<source.length){</span><br><span class="line"> <span class="keyword">if</span>(j==-1||pattern[j]==<span class="built_in">source</span>[i]){</span><br><span class="line"> i++;</span><br><span class="line"> j++</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"> j=next[j];</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(j==pattern.length){</span><br><span class="line"> <span class="built_in">return</span> i-j;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">else</span>{</span><br><span class="line"> <span class="built_in">return</span> -1</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>String对象快速转成char[]数组<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">char[] array = str.toCharArray();</span><br></pre></td></tr></table></figure></p>
<p>String类型的indexOf这个函数可以完全取代KMP</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/30/KMP算法/" data-id="ckc4v5z1x000d7wwzjuk16y87" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-Java常用类库" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/28/Java常用类库/" class="article-date">
<time datetime="2020-06-28T09:34:56.000Z" itemprop="datePublished">2020-06-28</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/28/Java常用类库/">Java常用类库</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#Java中的排序<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">int[] arr={3,2,1};</span><br><span class="line">Arrays.sort(arr);</span><br></pre></td></tr></table></figure></p>
<p>转String:String.valueOf()<br>转Integer:Integer.parseInt()<br>Math.random返回一个[0,1)之间的double值</p>
<p>#优先队列<br>插入的元素会自动排序,非常适合于找到第k小的数字<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Queue<Integer> queue = new PriorityQueue<>();</span><br><span class="line">//加入(O1,O2)->O2-O1表示从大往小排</span><br><span class="line">Queue<Integer> queue = new PriorityQueue<>((O1,O2)->O2-O1)</span><br><span class="line">queue.add()</span><br><span class="line">queue.poll()</span><br><span class="line">queue.peek()</span><br><span class="line">queue.size()</span><br></pre></td></tr></table></figure></p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/28/Java常用类库/" data-id="ckc4v5z1u000b7wwzamdg6x8w" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-Android总结" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/28/Android总结/" class="article-date">
<time datetime="2020-06-28T09:34:37.000Z" itemprop="datePublished">2020-06-28</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/28/Android总结/">Android总结</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/28/Android总结/" data-id="ckc4v5z1c00037wwzdr2r7g4t" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-Java-GC" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/28/Java-GC/" class="article-date">
<time datetime="2020-06-28T09:34:26.000Z" itemprop="datePublished">2020-06-28</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/28/Java-GC/">Java GC</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/28/Java-GC/" data-id="ckc4v5z1q00097wwzurzm0bim" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-java-thread" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/27/java-thread/" class="article-date">
<time datetime="2020-06-27T07:24:33.000Z" itemprop="datePublished">2020-06-27</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/27/java-thread/">java-thread</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#线程与进程的由来</p>
<ol>
<li>串行:需要长时间等待用户输入</li>
<li>批处理:将用户指令集中成任务清单,批量串行处理,但是无法并行(等待I/O操作的过程中,还是无法让出CPU资源)</li>
<li>多进程:进程独占内存空间,保存各自运行状态,相互之间不干扰,且可以互相切换,为并发处理提供可能。能够够在多个进程之间切换时间片。</li>
</ol>
<p>后来人们对实时性有了要求。一个进程可能具有很多的子任务,而进程只能一个个地去执行这些子任务。而往往子任务之间不存在顺序上的依赖,可以并发执行,所以将CPU切分成更细的时间片去执行任务。</p>
<p>同一个进程中的线程共享进程内的资源,相互切换更加快速,因为不需要页目录改变内存地址</p>
<p>#金句:进程是资源分配的最小单位,线程是CPU调度的最小单位</p>
<ol>
<li>与进程相关的资源,都被记录在了PCB中</li>
<li>进程是抢占处理机的调度单位,有自己的内存地址空间;线程属于某个进程,与进程内的其它线程共享进程的内存地址空间</li>
<li>线程由堆栈寄存器、程序计数器、TCB构成</li>
</ol>
<p>#线程与进程的区别</p>
<ol>
<li>线程不能看做独立的应用,进程可以看作是独立的应用</li>
<li>进程有独立的地址空间,相互不影响,线程只是进程的不同执行路径(某个线程挂掉,进程也挂掉)</li>
<li>线程有自己的堆栈、局部变量,但是线程之间没有单独的地址空间。所以多进程程序比多线程程序健壮。</li>
<li>进程切换比线程切花开销大。对于需要同时进行,又要共享某些变量的并发操作,只能用线程。</li>
</ol>
<p>#Java中的进程和线程<br>Java对操作系统中的进程和线程进行了进一步的封装</p>
<ol>
<li>运行一个Java程序产生一个进程,进程中至少包含一个线程</li>
<li>每个进程对应一个JVM实例</li>
<li>Java采用单线程编程模型,程序会自动创建主线程。但JVM中并不是只有主线程一个线程,比如还有GC线程</li>
<li>一个程序是一个可执行的文件,一个进程是一个程序运行中的实例</li>
</ol>
<p>#run vs start</p>
<ol>
<li>用Thread对象调用run还是在主线程中执行,用Thread对象调用start则是在子线程中执行</li>
<li>start会创建一个新的线程去执行run方法;run是直接对普通方法的调用,还是在主线程中执行</li>
</ol>
<p>#Thread VS Runnable</p>
<ol>
<li>Thread是一个实现了Runnable接口的类;Runnable接口是一个接口,里面只有一个抽象的run方法</li>
<li><p>使用Thread创建线程</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Thread t1 = new <span class="function"><span class="title">Thread</span></span>(){</span><br><span class="line"> @Override</span><br><span class="line"> public void <span class="function"><span class="title">run</span></span>(){</span><br><span class="line"> ...</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">MyThread t2 = new MyThread();</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用Runnable接口构造线程</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">MyRunnable r1 = new MyRunnable();</span><br><span class="line">Thread t1 = new Thread(r1);</span><br></pre></td></tr></table></figure>
</li>
<li><p>Java单一集成,为了提升可扩展性,尽量使用接口的方式创建线程,将业务逻辑封装在run中</p>
</li>
<li>Thread本身就是一个实现了Runnable接口的类,类本身还包含了一些多线程的配套特性</li>
<li>给run方法传参的方式:通过类中的其它数据域,如构造函数、属性等<br>ps:在main中能够使用自身非静态成员时,可以通过在main中创建对象去引用,没必要都去使用static</li>
</ol>
<p>Thread类的方法:sleep(类)、join(Thread对象)</p>
<p>#处理线程的返回值</p>
<ol>
<li>主线程等待发<br>用一个whie循环+线程sleep的方式不断地去等待子线程完成返回值,无法做到精准控制</li>
<li>使用Thread类的join“阻塞当前线程”,以等待子线程执行完毕<br>比主线程等待法精确一些,但无法做到更精准</li>
<li>通过Callable方法实现:FutureTask or 线程池<br>FutureTask中的isDone方法可以判断call方法有没有执行完成实现return<br>FutureTask中的get方法可以在有限时间内等待call方法传来的返回值</li>
</ol>
<p>线程池<br>原理类似,通过future类的两个方法isDone和get去判断和等待返回值<br>使用线程池能够实现多个callable对象的提交,并实现统一管理</p>
<p>ps:public static void main的由来<br>Java中的方法一般都需要创建一个对象,然后用对象去调用;但是主方法是交给JVM直接去调用的,是交给JVM的执行入口,所以需要使用static</p>
<p>#Java线程的状态</p>
<ol>
<li>新建New:创建了线程但是并没有利用start启动的状态</li>
<li>运行Runnable:包括了操作系统中的Ready和Running两个状态</li>
<li>无限期等待Waiting:不会被分配CPU执行时间,需要显示唤醒,否则无限等待<br>e.g. Object.wait()使用默认参数时、Thread.join使用默认参数时,都会造成无限等待</li>
<li>限期等待Timed Waiting:在一定时间后会由系统自动唤醒<br>e.g.带参的wait和join方法、sleep</li>
<li>阻塞Blocked:等待获取排它锁(在有其它线程放弃锁时会发生),等锁状态。不同于等待状态,等待状态并不是因为获取不到锁而导致的。</li>
<li>终止Terminated:线程结束执行</li>
</ol>
<p>#sleep VS wait</p>
<ol>
<li>sleep是Thread类的方法;wait是Object类都有的方法</li>
<li>sleep方法可以在任何地方使用;wait只能在sychronized块或者sychronized方法中使用(获取锁了才能去释放锁)</li>
<li>Thread.sleep只是让出CPU,不会导致锁行为改变</li>
<li>wait不仅让出CPU,而且会释放锁<br>定义对象锁<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">final Object lock = new Object();</span><br><span class="line">sychronized{</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>无限等待的wait要用notify或者notifyAll()去唤醒</p>
<h1 id="notify-VS-notifyALL"><a href="#notify-VS-notifyALL" class="headerlink" title="notify VS notifyALL"></a>notify VS notifyALL</h1><p>前置知识:锁池EntryList、等待池WaitList</p>
<ol>
<li>锁池:没有抢到锁的线程在锁池中等待锁的释放</li>
<li>等待池:锁的拥有者在用wait方法释放锁后,会进入到等待池中,但是不会参与到锁的竞争中</li>
<li>notifyAll会让所有处于等待池的线程全部进入到锁池中去一起竞争锁</li>
<li>notify只会随机选取一个处于等待池中的锁进入到锁池中去竞争锁</li>
</ol>
<p>#sychronized<br>表明必须获得同步锁,才能执行内部的逻辑</p>
<p>#volatile<br>当有多个线程修改volatile变量时,一旦A线程修改了变量,其它的线程都能立即看到改动</p>
<p>#yield</p>
<ol>
<li>yield函数可以使当前线程给线程调度器一个暗示,表示当前线程愿意让出当前的CPU资源。但是决定权在线程调度器,线程可能会忽略掉这个暗示。</li>
<li>和sleep都是Thread的方法</li>
<li>yield对锁的行为不会产生影响,不会让锁</li>
</ol>
<p>#interrupt<br>中断线程的方式,类似于yield,只是给线程一个中断的暗示</p>
<ol>
<li>对于阻塞状态的线程,使用interrupt方法可以让它立刻终止,并抛出interruptException</li>
<li>对于正常运行状态的线程,只是将线程的中断标志设置为true。</li>
</ol>
<p>#线程安全问题原因</p>
<ol>
<li>存在共享数据</li>
<li>存在多条线程共同操作这些数据<br>解决方法:统一时刻有且只有一个线程在操作共享数据,其它线程需要等待</li>
</ol>
<p>#互斥锁特性<br>原子性:同一时间只允许一个线程进行操作<br>可见性:保证共享数据的变化可以被其它数据看到<br>synchronize保证了原子性和可见性</p>
<p>#synchronized获取对象锁</p>
<ol>
<li>同步代码块,以this指针或者类实例对象作为参数</li>
<li>同步非静态方法,锁是当前对象的实例对象</li>
</ol>
<p>#sychronized获取类锁(制约同一个类的不同实例)</p>
<ol>
<li>同步代码块,以类对象作为参数</li>
<li><p>同步静态方法<br>#Reentrantlock(再入锁)</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ReetrantLock lock = new ReetrantLock();</span><br><span class="line">lock.lock();</span><br><span class="line"></span><br><span class="line">lock.unlock();</span><br></pre></td></tr></table></figure>
</li>
<li><p>本质:sychronized是关键字,ReetrantLock是一个类(有方法、有属性、可以扩展)</p>
</li>
<li><p>释放锁的方式<br>sychronized会在它执行的部分执行完毕后自动释放锁<br>ReentrantLock使用lock()加锁,使用unlock()释放锁,</p>
</li>
<li><p>精密度<br>控制得更加精确,<br>Reetrantlock还可以对等待锁的时间进行控制</p>
</li>
<li><p>公平非公平<br>sychronized使用的是非公平锁,抢占顺序不一定,有运气成分<br>Reetrantlock可以在构造函数中设置true参数,来得到公平锁。公平锁可以把所有先交给等待时间最久的线程。</p>
</li>
</ol>
<p>ReetrantLock将所转变成了可控的对象</p>
<p>#线程池</p>
<ol>
<li>问题:服务器接收大量的并发请求,没有线程池的情况下,线程需要频繁的创建和销毁,造成大量的开销。</li>
<li>作用:线程池能够帮助我们重复利用线程,去完成新的任务</li>
<li>使用Executors创建线程池</li>
<li>几种类型的线程池<br>newFixedThreadPool(int) n-n<br>指定线程数量的线程池<br>newCachedThreadPool 0-Integer.MAX_VALUE<br>缓存线程,长时间不用就遗弃。这样能在高峰时实现服用,闲置时不占用资源</li>
</ol>
<p>将任务分发给线程池中的线程</p>
<p>#Callable<br>Callable弥补了Runnable无法返回结果的短板</p>
<p>多进程和多线程都可以实现并行</p>
<p>HashMap并不是线程安全的</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/27/java-thread/" data-id="ckc4v5z2o000u7wwz7mb9v4g2" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-每日一题" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/27/每日一题/" class="article-date">
<time datetime="2020-06-27T05:38:03.000Z" itemprop="datePublished">2020-06-27</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/27/每日一题/">每日一题</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#最小未出现的正整数</p>
<ol>
<li>创建一个和当前数组相同的数组</li>
<li>使用for+while+swap实现一个换座位的算法</li>
<li>第一个人与它应该做的座位的人交换位置,然后重复操作</li>
<li>对之后的每个座位执行同样的操作</li>
<li>如果前面几个人刚好是前面的几个正整数的话,应该正好“对号入座”。即nums[i]应该在nums[nums[i]-1]这个位置上</li>
<li>如果不是,则有人的值与索引值不一致<br>巧妙利用了索引与正整数的对应关系<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">public int firstMissingPositive(int[] nums) {</span><br><span class="line"> int temp = 0;</span><br><span class="line"> <span class="keyword">for</span>(int i=0;i<nums.length;i++){</span><br><span class="line"> <span class="keyword">while</span>(nums[i]>0 && nums[i]<=nums.length && nums[i] != nums[nums[i]-1]){</span><br><span class="line"> //交换nums[i]和nums[nums[i-1]]</span><br><span class="line"> swap(nums,i,nums[i]-1);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(int i=0;i<nums.length;i++){</span><br><span class="line"> <span class="keyword">if</span>(nums[i]!=i+1){</span><br><span class="line"> <span class="built_in">return</span> i+1;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //此时说明数组中正好是正整数的前几位</span><br><span class="line"> <span class="built_in">return</span> nums.length+1;</span><br><span class="line"> }</span><br><span class="line"> void swap(int[] nums,int i,int j){</span><br><span class="line"> int temp = 0;</span><br><span class="line"> temp = nums[i];</span><br><span class="line"> nums[i] = nums[j];</span><br><span class="line"> nums[j] = temp;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>#209最短子数组</p>
<ol>
<li>使用left和i两个指针控制</li>
<li>i不断向右延伸,当满足条件时,记录下当前的长度,然后试着从左边缩减<br>本题关键:连续、最短 (适合双指针滑动窗口)<br>不重复(适合Hashset)<br>Java获取int类最大值的方式:Integer.MAX_VALUE 即2^31-1<br>Java获取int类最小值的方式:Integer.MIN_VALUE 即-2^31<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">public int minSubArrayLen(int s, int[] nums) {</span><br><span class="line"> int sum = 0;</span><br><span class="line"> int left = 0;</span><br><span class="line"> int ans = Integer.MAX_VALUE;</span><br><span class="line"> <span class="keyword">for</span>(int i=0;i<nums.length;i++){</span><br><span class="line"> sum+=nums[i];</span><br><span class="line"> <span class="keyword">while</span>(sum>=s){</span><br><span class="line"> ans = Math.min(ans,i-left+1);</span><br><span class="line"> sum -= nums[left];</span><br><span class="line"> left++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(ans == Integer.MAX_VALUE){</span><br><span class="line"> <span class="built_in">return</span> 0;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"> <span class="built_in">return</span> ans;</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>#用两个栈来模拟队列</p>
<ol>
<li>插入时向stack1中插入</li>
<li>删除时从先判断一下stack是否为空</li>
<li>若stack2为空,则将stack1中的元素弹出再顺序入stack2</li>
<li>若stack2不为空,则直接将stack2的栈顶弹出<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">class CQueue {</span><br><span class="line"></span><br><span class="line"> private Stack<Integer> stack1 = new Stack<Integer>();</span><br><span class="line"> private Stack<Integer> stack2 = new Stack<Integer>();</span><br><span class="line"> public <span class="function"><span class="title">CQueue</span></span>() {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public void appendTail(int value) {</span><br><span class="line"> stack1.push(value);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public int <span class="function"><span class="title">deleteHead</span></span>() {</span><br><span class="line"> <span class="keyword">if</span>(stack1.empty() && stack2.empty()){</span><br><span class="line"> <span class="built_in">return</span> -1;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(stack2.empty()){</span><br><span class="line"> <span class="keyword">while</span>(!stack1.empty()){</span><br><span class="line"> stack2.push(stack1.pop());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">return</span> stack2.pop();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>Java Stack<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">创建:Stack<Integer> stack = new Stack<Integer>();</span><br><span class="line">empty()、pop()、peek()、push()</span><br></pre></td></tr></table></figure></p>
<p>#求二维数组的连通子图</p>
<ol>
<li>创建一个足够大的数组</li>
<li>使用一部分的空间填写数据</li>
<li>不要顶格写,防止越界</li>
<li>从map[i][j]==1处开始,不断向上下左右四个方向递归调用,dfs函数的参数是当前这一步的index,在递归调用时注意将原本的格子置为0<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">public class PoolNum {</span><br><span class="line"></span><br><span class="line"> static int[][] map = new int[100][100];</span><br><span class="line"> //深度优先搜索</span><br><span class="line"> static void dfs(int i,int j){</span><br><span class="line"> <span class="keyword">if</span>(map[i+1][j]==1){</span><br><span class="line"> map[i+1][j]=0;</span><br><span class="line"> dfs(i+1,j);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(map[i][j+1]==1){</span><br><span class="line"> map[i][j+1]=0;</span><br><span class="line"> dfs(i,j+1);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(map[i-1][j]==1){</span><br><span class="line"> map[i-1][j]=0;</span><br><span class="line"> dfs(i-1,j);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(map[i][j-1]==1){</span><br><span class="line"> map[i][j-1]=0;</span><br><span class="line"> dfs(i,j-1);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> Scanner scanner = new Scanner(System.in);</span><br><span class="line"> int t = scanner.nextInt();</span><br><span class="line"> int count = 0;</span><br><span class="line"> <span class="keyword">for</span>(int i=0;i<t;i++){</span><br><span class="line"> //行数</span><br><span class="line"> int m = scanner.nextInt();</span><br><span class="line"> //列数</span><br><span class="line"> int n = scanner.nextInt();</span><br><span class="line"> <span class="keyword">for</span>(int j = 1;j<m+1;j++){</span><br><span class="line"> <span class="keyword">for</span>(int k=1;k<n+1;k++){</span><br><span class="line"> map[j][k]=scanner.nextInt();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(int j = 1;j<m+1;j++){</span><br><span class="line"> <span class="keyword">for</span>(int k=1;k<n+1;k++){</span><br><span class="line"> <span class="keyword">if</span>(map[j][k]==1){</span><br><span class="line"> count++;</span><br><span class="line"> map[j][k]=0;</span><br><span class="line"> dfs(j,k);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> System.out.println(count);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>创建hashMap的方式<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Map<K,V> map = new HashMap<K,V>();</span><br></pre></td></tr></table></figure></p>
<p>hashMap的put既管更新也管添加<br>遍历打印HashMap的方式<br>for(K key:map.keySet()){<br> System.out.println(key+” “+map.get(key));<br>}</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/27/每日一题/" data-id="ckc4v5z2u00117wwz0rm9kyh1" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-Android开发屏幕显示" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/26/Android开发屏幕显示/" class="article-date">
<time datetime="2020-06-26T12:08:40.000Z" itemprop="datePublished">2020-06-26</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/26/Android开发屏幕显示/">Android开发屏幕显示</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#像素<br>常用的像素单位:px、dp、sp</p>
<ol>
<li>px与物理设备的像素密度有关,同样的屏幕尺寸,像素密度越高,屏幕越清晰</li>
<li>dp与物理设备无关,只与屏幕有关。当density=1时,dp与px是1比1关系</li>
<li>sp与dp类似,专门用于字体大小。sp设置的字体大小可以随系统调整</li>
<li>在xml文件中使用的像素单位是dp、sp</li>
<li>有的函数的参数使用的单位是px,可以用density变量实现px和dp的互换</li>
<li>通过DisplayMetrics对象可以获得屏幕的宽度和高度,以及像素密度</li>
</ol>
<p>#颜色</p>
<ol>
<li>可以使用6位16进制数或者8位16进制数(带透明度)两种方式。代码中0x开头,xml文件中#开头。值越高越亮,值越低越暗。</li>
<li>在Colors.xml中定义颜色,代码中R.color.引用;xml文件使用@color/引用</li>
<li>FF的alpha值表示完全不透明</li>
</ol>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/26/Android开发屏幕显示/" data-id="ckc4v5z1a00027wwz2sn0mw6u" class="article-share-link">Share</a>
</footer>
</div>
</article>
<article id="post-树" class="article article-type-post" itemscope="" itemprop="blogPost">
<div class="article-meta">
<a href="/2020/06/26/树/" class="article-date">
<time datetime="2020-06-26T01:54:28.000Z" itemprop="datePublished">2020-06-26</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2020/06/26/树/">树</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>#树的递归定义</p>
<ol>
<li>有且只有一个结点没有父结点</li>
<li>除根以外,其它结点有且仅有一个父结点</li>
<li>每个结点都构成一个以它为根的子树</li>
</ol>
<p>ps:前中后指的是根的位置<br>前中后搜索都属于深度优先搜索</p>
<p>#112判断路经总和</p>
<ol>
<li>采用前序遍历的方式</li>
<li>前序遍历的操作部分改成判断叶子节点是否等于最后相减的值</li>
<li>参数除了树节点外还有一个sum值,雁过拔毛法</li>
<li>在使用树节点遍历时,判断结点为空的处理是必须要有的</li>
<li>Java中虽然没有引用,但是可以用属性(全局变量)来实现相同的效果<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">class Solution {</span><br><span class="line"> boolean ans = <span class="literal">false</span>;</span><br><span class="line"> public boolean hasPathSum(TreeNode root, int sum) {</span><br><span class="line"> <span class="keyword">if</span>(root == null){</span><br><span class="line"> <span class="built_in">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> preorder(root,sum);</span><br><span class="line"> <span class="built_in">return</span> ans;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> void preorder(TreeNode root,int sum){</span><br><span class="line"> <span class="keyword">if</span>(root == null){</span><br><span class="line"> <span class="built_in">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(root.left==null && root.right==null && root.val == sum){</span><br><span class="line"> ans = <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> preorder(root.left,sum-root.val);</span><br><span class="line"> preorder(root.right,sum-root.val);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>#113 判断路经总和升级版<br>需要返回的不是true或者false,而是返回一个结果的集合(使用List实现)</p>
<ol>
<li>先入栈,加值</li>
<li><p>叶子节点判断条件,满足则加入最终的结果集,注意要创建一个副本去加入,否则会是空集</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List<Integer> temp = new ArrayList<>(path);</span><br></pre></td></tr></table></figure>
</li>
<li><p>再出栈,减值</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">class Solution {</span><br><span class="line"> int currSum = 0;</span><br><span class="line"> public List<List<Integer>> pathSum(TreeNode root, int sum) {</span><br><span class="line"> //存储结果集</span><br><span class="line"> List<List<Integer>> res = new ArrayList<>();</span><br><span class="line"> //存储单一结果</span><br><span class="line"> List<Integer> path = new ArrayList<>();</span><br><span class="line"> <span class="keyword">if</span>(root == null){</span><br><span class="line"> <span class="built_in">return</span> res;</span><br><span class="line"> }</span><br><span class="line"> preorder(root,sum,path,res);</span><br><span class="line"> <span class="built_in">return</span> res;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> void preorder(TreeNode root,int sum,List<Integer> path,List<List<Integer>> res){</span><br><span class="line"> <span class="keyword">if</span>(root == null){</span><br><span class="line"> <span class="built_in">return</span>;</span><br><span class="line"> }</span><br><span class="line"> currSum += root.val;</span><br><span class="line"> path.add(root.val);</span><br><span class="line"> <span class="keyword">if</span>(root.left==null && root.right==null && currSum == sum ){</span><br><span class="line"> List<Integer> temp = new ArrayList<>(path);</span><br><span class="line"> res.add(temp);</span><br><span class="line"> }</span><br><span class="line"> preorder(root.left,sum,path,res);</span><br><span class="line"> preorder(root.right,sum,path,res);</span><br><span class="line"> </span><br><span class="line"> currSum -= root.val;</span><br><span class="line"> path.remove(path.size()-1);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>ps:ArrayList的部分操作,这几个也是collections体系种类库的共有操作</p>
<ol>
<li>add从后向前加入</li>
<li>get得到指定索引元素</li>
<li>set替换指定索引元素</li>
<li>remove可以按元素删除,也可以按索引删除</li>
</ol>
<p>#树的最近公共祖先</p>
<ol>
<li>找到从根到两个结点的两条路径</li>
<li>将两条路径的结点存储到List中</li>
<li>从后向前比较第一个相同的结点</li>
<li>在深度优先搜索的基础上,前序部分操作为入栈,比较返回;后序部分为出栈</li>
<li>深度搜索基本框架:判断空树->前序操作(入栈)->满足条件->递归调用->后续操作(出栈)</li>
<li>new ArrayList<>(res)可以创建一个结果的副本<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">class Solution {</span><br><span class="line"> List<TreeNode> path = new ArrayList<>();</span><br><span class="line"> List<TreeNode> res;</span><br><span class="line"> boolean isFinished;</span><br><span class="line"> public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {</span><br><span class="line"> <span class="keyword">if</span>(root == null){</span><br><span class="line"> <span class="built_in">return</span> null;</span><br><span class="line"> }</span><br><span class="line"> preorder(root,p);</span><br><span class="line"> isFinished = <span class="literal">false</span>;</span><br><span class="line"> List<TreeNode> list1 = new ArrayList<>(res);</span><br><span class="line"> preorder(root,q);</span><br><span class="line"> List<TreeNode> list2 = new ArrayList<>(res);</span><br><span class="line"> <span class="keyword">for</span>(int i = Math.min(list1.size(),list2.size())-1;i>=0;i--){</span><br><span class="line"> <span class="keyword">if</span>(list1.get(i) == list2.get(i)){</span><br><span class="line"> <span class="built_in">return</span> list1.get(i);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">return</span> null; </span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> void preorder(TreeNode root,TreeNode search){</span><br><span class="line"> //空树判断+结束条件</span><br><span class="line"> <span class="keyword">if</span>(root == null||isFinished == <span class="literal">true</span>){</span><br><span class="line"> <span class="built_in">return</span>;</span><br><span class="line"> }</span><br><span class="line"> //前序操作</span><br><span class="line"> path.add(root);</span><br><span class="line"> <span class="keyword">if</span>(root == search){</span><br><span class="line"> isFinished = <span class="literal">true</span>;</span><br><span class="line"> res = new ArrayList<>(path);</span><br><span class="line"> }</span><br><span class="line"> //递归左右子树</span><br><span class="line"> preorder(root.left,search);</span><br><span class="line"> preorder(root.right,search);</span><br><span class="line"> //后续操作</span><br><span class="line"> path.remove(path.size()-1);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li>
</ol>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2020/06/26/树/" data-id="ckc4v5z2t00107wwz0fbb41vl" class="article-share-link">Share</a>
</footer>
</div>
</article>
<nav id="page-nav">
<span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><a class="page-number" href="/page/4/">4</a><a class="extend next" rel="next" href="/page/2/">Next »</a>
</nav>
</section>
<aside id="sidebar">
<div class="widget-wrap">
<h3 class="widget-title">Archives</h3>
<div class="widget">
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/07/">July 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/06/">June 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/02/">February 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">June 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/05/">May 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/03/">March 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/01/">January 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/12/">December 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/11/">November 2018</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Recent Posts</h3>
<div class="widget">
<ul>
<li>
<a href="/2020/07/02/Java-I-O/">Java-I/O</a>
</li>
<li>
<a href="/2020/07/01/Android提升/">Android提升</a>
</li>
<li>
<a href="/2020/06/30/KMP算法/">KMP算法</a>
</li>
<li>
<a href="/2020/06/28/Java常用类库/">Java常用类库</a>
</li>
<li>
<a href="/2020/06/28/Android总结/">Android总结</a>
</li>
</ul>
</div>
</div>
</aside>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info" class="inner">
© 2020 John Doe<br>
Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
</nav>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script src="/js/script.js"></script>
</div>
</body>
</html>