<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>欲說還休</title><link>https://blog.terryx.com/posts/</link><description>TerryX's Blog</description><generator>Hugo 0.161.1</generator><language>zh-cn</language><managingEditor>TerryX</managingEditor><lastBuildDate>Wed, 21 Mar 2018 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.terryx.com/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>一个好消息一个坏消息</title><link>https://blog.terryx.com/posts/hehe/</link><pubDate>Wed, 21 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/hehe/</guid><description><![CDATA[<p>这段时间发生了两件大事。如上文所说，其一是我去了湾区面了两家公司，一个给了offer；其二是我爱了五年的人对我说，她不想再等我了。</p>
<p>最可怕的事情是我的价值观塌陷了，起码在两周之前我还在想着怎么变强，怎么让自己能在这个陌生的地方有个立足之地，怎么让我心爱的人因为我过上更好的生活。但是她说，“这些都不是我想要的”。我说，“我都走出了最难的一步了，后面还有什么呢？”。可能对她而言，往后就是无尽的等待吧。她不喜欢离开家，不喜欢压力大的生活，她还像小孩子一样把生活看着简单，她也不会懂大人的道理。如果你的压力小，总有人会替你承担压力大的部分。</p>
<p>也许是我错了，我都错了。公司告诉录用我的时候我也没有多开心，但是她说不再等我的时候我心却碎了。我对她是什么呢？OPT完了有H1B，H1B完了有绿卡。这些事情就是一颗颗定时炸弹，永远不可能让我们安心的生活。</p>
<p>我们异地一年多了，我觉得我变了好多，起码变得可以给她我认为好的“未来”。但是她需要的就是温暖，就是“小”日子，是日常的生活。我无法想象她在冷冷的出租屋里，孤单的时候，会不会哭，会不会笑，会不会想我，会不会怨着我。</p>
<p>我有时候也恨美国，这个地方给了我许多，却让我失去了最重要的东西。这些事情对于她可能难以理解吧。</p>
<p>不过我也决定了，我会尽快去找她。因为我知道，</p>
<blockquote>
<p>我已不会再对谁 满怀期待</p>
</blockquote>
]]></description></item><item><title>心态要炸</title><link>https://blog.terryx.com/posts/fck-the-world/</link><pubDate>Sun, 04 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/fck-the-world/</guid><description><![CDATA[<p>我发现给自己打气这种事情是非常傻逼的，你本来就是弱，还要麻醉自己说没事，一切都会好的。还有那些说你肯定没问题的人，在我看来也是傻逼，你怎么知道我肯定没问题。过的很惨的人，要么想听的是你狠狠批我，要么就是想知道你比我过得还惨。优越感对于人来说就是癌变组织，越崇尚他死的就越快，趁早打消这种无趣的想法。还是那句老话，“菜是原罪”。</p>
<p>总听说人生苦短，依我看人生前五十年是领略“苦”，后面就是“短”。我也体会到了为什么说人是要享受忧郁的。因为这样，我才想着下一步做什么，才想着在这写点东西。可能几年前我就该想明白，我还是没有走到那一层，每次都是落后半拍。总想着那个时候要是能想明白就好了，这也说明我现在也还没有想通几年后我才明白的道理。</p>
<p>周一飞去面两家公司，我想还是学习的态度去吧。比我强的人太多了，我只有这样才能不被你们淘汰。</p>
]]></description></item><item><title>Search Problems in Interview</title><link>https://blog.terryx.com/posts/search-interview/</link><pubDate>Fri, 02 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/search-interview/</guid><description>&lt;p>暂时不想写&lt;/p>
</description></item><item><title>K-th Problems in Interview</title><link>https://blog.terryx.com/posts/kth-interview/</link><pubDate>Thu, 01 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/kth-interview/</guid><description><![CDATA[<p>K-th问题是说在给定数据集中，找到排名第k个的数据。通常这个数据集极大是没办法存在内存中，或者遍历一遍数据集的时间代价很高。通常解决这种方法是维护一个k大小的最大堆，这样我们可以一直维护top k个数据。这种方法比较常见且简单，这里我想说得是一般这种K-th类问题是可以通过Binary Search解决。</p>
<h2 id="binary-search">Binary Search</h2>
<p>二分查找，是非常简单的算法。但是这种算法应用非常灵活，首先想一次性写对二分查找并不是一件容易的事情。这里我想简单总结一下二分查找的使用背景。众所周知，最最常见应用二分查找的地方就是对于一个已经排好序的数组中，找到一个我们已知的值的位置。这个问题背后隐藏着什么呢？记得我在初次学习二分查找的时候，看到有人总结说二分查找的应用条件就是这个问题是否可以证明是“单调的”。对于数组查找中，我们可以简化问题为一个函数<code>f</code>，<code>f(index)</code>就是对于查找<code>index</code>的值是否大于等于目标值，这样我们就发现函数<code>f</code>在定义域<code>[0, n)</code>是满足单调性质的，因为必然有个界限让小于的<code>f</code>为false，大于等于的时候是true（当然这个界限也有可能不存在，就是我们没有找到这个值的时候）。再举个例子，我们想找到实数取决一个满足<code>f(x)=y</code>的值，也可以对整个实数区域进行二分，然后求解<code>x</code>，就像解方程一样。</p>
<p>说完了背景，再说说写法。首先是整数的写法：</p>
<p>因为整数的二分会自动去掉小数部分，这就会遇到一个头疼的问题，如果当<code>low = k, high = k + 1</code> 这时候我们做二分，中间值永远是<code>k</code>。如果我们写的代码是<code>while (low &lt; high) {if (f(mid)) { low = mid; } else { high = mid - 1; }}</code> 且这个时候<code>f(mid)</code>为true，那么我们永远也无法跳出这个循环。解决这个问题有两种思路：1. 因为我们停止的条件是<code>low == high</code>所以不妨把循环条件设置为 <code>while (low + 1 &lt; high)</code> 但是这又会引起一个问题，我们需要在最后再double check一下low和high我们需要的答案是什么。 2. 也可以把二分的结果向上取整 <code>mid = (low + high + 1) / 2</code> 这样在遇到这种情况是我们总会选择<code>high</code>。所以在写完二分解法后最好想一下，两个答案的时候程序能不能成功运行出结果。第二个是值域分布的问题，有可能我们的判断函数<code>f(x)</code>永远都是false，这样的结果是我们最后的二分结果也是错的。</p>
<p>下面是实数二分的写法：</p>
<p>这里就不会遇到那个头疼问题，我们只要保证精度就可以了 <code>while (left &lt; high &amp;&amp; Math.abs(left - high) &lt; 1e-5)</code> 但是我不喜欢这么写，会因为精度的问题陷入死循环。我们单纯循环100次就可以把精度控制在小数点后30位。</p>
<h2 id="k-th-with-binary-search">K-th with Binary Search</h2>
<p>这里说一下为什么K-th问题都可以借用二分查找解决。因为K-th问题必然是单调性的，因为我们有函数<code>f(x)=k</code>表示<code>x</code>在数据集中的排序为<code>k</code>，那么比x大的数字，<code>f(x)</code>就会变大，反之亦然，单调性很容易证明。所以我们只要在合理的时间计算出<code>x</code>的排序，就可以二分查找出排序为<code>k</code>的数值。下面我们来看几道题：</p>
<p><a href="https://leetcode.com/problems/find-k-th-smallest-pair-distance/description/">Find K-th Smallest Pair Distance</a> 给了一个数组，让找出两两pair中相差值为k-th小的值。我们可以对数组排序，然后二分这个相差值。然后根据这个值找出有多少个pair比这个值小。这里注意并不是如果比这个值小的元素有<code>k-1</code>个就证明了就是答案，因为我们不知道这个相差值是否真的存在。所以我们要找到答案为<code>k-1</code>且这个值最小的那个。因为这个值是处于一个分界点，比这个值小排序的序号就减少1，就说明了这个差值是存在的。这里我们用sliding window来找到多少个差值比target要小。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">smallestDistancePair</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Arrays</span><span class="p">.</span><span class="na">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Integer</span><span class="p">.</span><span class="na">MAX_VALUE</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">2</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">begin</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">end</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">cnt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">end</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">end</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">begin</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">nums</span><span class="p">.</span><span class="na">length</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">nums</span><span class="o">[</span><span class="n">end</span><span class="o">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">nums</span><span class="o">[</span><span class="n">begin</span><span class="o">]</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">mid</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="n">begin</span><span class="o">++</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">cnt</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="p">(</span><span class="n">end</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">begin</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">cnt</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">low</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><a href="https://leetcode.com/problems/k-th-smallest-prime-fraction/description/">K-th Smallest Prime Fraction</a> 给一个排序好的素数数组，对于 <code>p &lt; q find p / q</code> 找出所有值中第k小的。同样，这里我们对实数值域进行二分，找到多少个分数比当前值小，同样找到这些满足条件中的最小值。我们也可以通过比较巧妙的线性方法的找出所有满足小于查找值的分数个数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="nf">kthSmallestPrimeFraction</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">A</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">K</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">A</span><span class="p">.</span><span class="na">length</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">double</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">A</span><span class="o">[</span><span class="n">0</span><span class="o">]/</span><span class="n">A</span><span class="o">[</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">double</span><span class="w"> </span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">A</span><span class="o">[</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1</span><span class="o">]/</span><span class="n">A</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Set</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HashSet</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">A</span><span class="p">)</span><span class="w"> </span><span class="n">set</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">a</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">itr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">itr</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">100</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">itr</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">double</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">cnt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">j</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">A</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">A</span><span class="o">[</span><span class="n">j</span><span class="o">]</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">					</span><span class="n">cnt</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">j</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">					</span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">cnt</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">K</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">A</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">double</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">round</span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">a</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">p</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">1e</span><span class="o">-</span><span class="n">5</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">set</span><span class="p">.</span><span class="na">contains</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="o">[]</span><span class="p">{(</span><span class="kt">int</span><span class="p">)</span><span class="n">p</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><a href="https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/description/">Kth Smallest Element in a Sorted Matrix</a> 给一个行和列都排序的矩阵，找到其中第k小的。我们二分来查找这个值，然后通过每行进行二分查找来统计多少个值比这个数要小。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">kthSmallest</span><span class="p">(</span><span class="kt">int</span><span class="o">[][]</span><span class="w"> </span><span class="n">matrix</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matrix</span><span class="p">.</span><span class="na">length</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matrix</span><span class="o">[</span><span class="n">0</span><span class="o">][</span><span class="n">0</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matrix</span><span class="o">[</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1</span><span class="o">][</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">2</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="kt">int</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">l</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">h</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="kt">int</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">l</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">2</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">matrix</span><span class="o">[</span><span class="n">i</span><span class="o">][</span><span class="n">m</span><span class="o">]</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">mid</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">					</span><span class="n">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">					</span><span class="n">h</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">matrix</span><span class="o">[</span><span class="n">i</span><span class="o">][</span><span class="n">l</span><span class="o">]</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">mid</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="n">count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">count</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">low</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><a href="https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/description/">Kth Smallest Number in Multiplication Table</a> 和上道题类似，每行换成了等比数列。免去了进行二分查找统计，直接算除法就可以统计数量。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">findKthNumber</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">low</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">high</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">m</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">min</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">i</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">count</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">low</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">high</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mid</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">low</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>]]></description></item><item><title>Binary Search Tree in Interview</title><link>https://blog.terryx.com/posts/bst/</link><pubDate>Sun, 25 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/bst/</guid><description><![CDATA[<p>Binary Search Tree (简称BST) 是最简单的搜索树，很多高级树用法都是以它为基础。因为设计它的算法很多都很巧妙，记得在面试的时候突然遇到一道BST的题卡住了。由于BST的结构特殊，所以有关它的题目都很灵活，想借此机会总结一下。</p>
<h2 id="递归与递推">递归与递推</h2>
<p>众所周知，BST是天生具有递归特性的，因为的BST的任一子树都是BST。所以很多题目都是利用这一性质。比如将BST有序打印出来就可以使用inorder遍历：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">recursive</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">recursive</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">        Do something...
</span></span></span><span class="line"><span class="cl"><span class="cm">        */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">recursive</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>当然也可以通过栈来改写为递推，这里是将未处理的结点存入栈中。这里需要介绍一种<code>pushAll</code>操作。就是将该结点的所有左结点全部压入栈。然后每次取出结点后对右结点进行<code>pushAll</code>操作。<a href="https://leetcode.com/problems/binary-tree-inorder-traversal/">Binary Tree Inorder Traversal</a>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span><span class="w"> </span><span class="nf">inorderTraversal</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">List</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ans</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayList</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Stack</span><span class="o">&lt;</span><span class="n">TreeNode</span><span class="o">&gt;</span><span class="w"> </span><span class="n">stack</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Stack</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">stack</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">root</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">stack</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">stack</span><span class="p">.</span><span class="na">pop</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ans</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="na">val</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="na">right</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">cur</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">stack</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">cur</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">ans</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>了解到这个特性后，我们就可以将BST改写成<code>Iterator</code> - <code>next()</code>取出下一个最小值，<code>hasNext()</code>是否存在结点。<a href="https://leetcode.com/problems/binary-search-tree-iterator/description/">Binary Search Tree Iterator</a>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BSTIterator</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="n">Deque</span><span class="o">&lt;</span><span class="n">TreeNode</span><span class="o">&gt;</span><span class="w"> </span><span class="n">stack</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="nf">BSTIterator</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">stack</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayDeque</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">pushAll</span><span class="p">(</span><span class="n">root</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="cm">/** @return whether we have a next smallest number */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">hasNext</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">!</span><span class="n">stack</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="cm">/** @return the next smallest number */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">next</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">TreeNode</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">stack</span><span class="p">.</span><span class="na">pop</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">pushAll</span><span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="na">right</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">pushAll</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">stack</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">root</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>在Java的<code>Iterator</code>是也可以支持<code>remove()</code>操作 - 删除上一个访问的结点。BST删除结点的操作也可以用递归算法来解决（当然也可用平衡二叉树删除结点进行分类的解法，但是递归的解法更加巧妙）。首先我们找到被删除的结点，然后把它替换成其右子树的最小值<code>m</code>（目的是为了保证删除后的右子树满足比当前结点大）。然后我们再递归删除右子树的<code>m</code>结点。<a href="https://leetcode.com/problems/delete-node-in-a-bst/description/">Delete Node in a BST</a>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="n">TreeNode</span><span class="w"> </span><span class="nf">deleteNode</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">key</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">deleteNode</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">,</span><span class="w"> </span><span class="n">key</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">  </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">key</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">deleteNode</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">,</span><span class="w"> </span><span class="n">key</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">min</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">findMin</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="c1">// copy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">min</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">deleteNode</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">,</span><span class="w"> </span><span class="n">min</span><span class="p">.</span><span class="na">val</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="n">TreeNode</span><span class="w"> </span><span class="nf">findMin</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="na">left</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">cur</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h2 id="查找">查找</h2>
<p>上文中我们知道BST是可以有序输出的，所以很多针对有序数据的算法都可以套在BST上。比如，二分查找，第k大问题，等等。</p>
<p>如果查找的结点存在于BST上，我们很容易可以将它找出。但是如果需要查找的结点不存在与树上，我们希望返回最接近的结点，这种问题该如何解决呢？首先我们要想一个问题，对于一个在BST上的结点，比它大的值可能存在于哪里？应该是<strong>存在于这个结点的右子树或父结点（如果存在）的右子树</strong>。但是这么思考的问题是我们需要跟踪父结点的情况，这个如果不借助其他数据结构存储很难实现。我们不如换一种思路：当访问到结点时，如果值大于target就找保存左子树的最接近target的值，然后取这两个值最接近target的一个；反之就从右子树来找。同样借助递归的特性我们可以解决这个问题。<a href="https://leetcode.com/problems/closest-binary-search-tree-value/description/">Closest Binary Search Tree Value</a></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">closestValue</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="o">-</span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">((</span><span class="kt">double</span><span class="p">)</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">1e</span><span class="o">-</span><span class="n">6</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">((</span><span class="kt">double</span><span class="p">)</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">closestValue</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">target</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">target</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">r</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">((</span><span class="kt">double</span><span class="p">)</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">target</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">closestValue</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">target</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">target</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">r</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>借用这种想法，我们还可以解决类似的问题。比如将BST分成两个BST，一个所有的值小于等于target，另一个大于target。对于当前结点如果小于等于target，其左边子树都是小于等于target，所以将右子树分成的结果的第一部分连接到当前结点的右边；如果大于target，说明右子树都是大于target，需要将左子树的结果的第二部分连入左边。<a href="https://leetcode.com/problems/split-bst/description/">Split BST</a>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="n">TreeNode</span><span class="o">[]</span><span class="w"> </span><span class="nf">splitBST</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">V</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">TreeNode</span><span class="o">[]</span><span class="p">{</span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">TreeNode</span><span class="o">[]</span><span class="w"> </span><span class="n">res</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">V</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">splitBST</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">,</span><span class="w"> </span><span class="n">V</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">res</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">res</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">splitBST</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">,</span><span class="w"> </span><span class="n">V</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">res</span><span class="o">[</span><span class="n">1</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">res</span><span class="o">[</span><span class="n">1</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">res</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>对于第k大的问题，可以通过inorder遍历来解决。<a href="https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/">Kth Smallest Element in a BST</a>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">kthSmallest</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">solve</span><span class="p">(</span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">root</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="o">-</span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">solve</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">left</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">r</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="o">-</span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">r</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">count</span><span class="o">++</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">count</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">root</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">solve</span><span class="p">(</span><span class="n">root</span><span class="p">.</span><span class="na">right</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">r</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>另一种变形是，在BST找到接近target的k个数。这个可以通过inorder来找到，但是这里介绍一种高效的方法借助额外的数据结构来解决。通过栈来存储比target小的结点，另一个栈存储大于等于target的结点。然后用类似two pointer的方法找到接近target的k个数。<a href="https://leetcode.com/problems/closest-binary-search-tree-value-ii/description/">Closest Binary Search Tree Value II</a>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span><span class="w"> </span><span class="nf">closestKValues</span><span class="p">(</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">root</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">target</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Deque</span><span class="o">&lt;</span><span class="n">TreeNode</span><span class="o">&gt;</span><span class="w"> </span><span class="n">greater</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayDeque</span><span class="o">&lt;&gt;</span><span class="p">(),</span><span class="w"> </span><span class="n">less</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayDeque</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">root</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">cur</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="na">val</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">less</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">cur</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="na">right</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">greater</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">cur</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">List</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayList</span><span class="o">&lt;&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">greater</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">()</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">less</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">greater</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">list</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">lessNext</span><span class="p">(</span><span class="n">less</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">less</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">list</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">greaterNext</span><span class="p">(</span><span class="n">greater</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">less</span><span class="p">.</span><span class="na">peek</span><span class="p">().</span><span class="na">val</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">target</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">greater</span><span class="p">.</span><span class="na">peek</span><span class="p">().</span><span class="na">val</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">target</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">list</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">lessNext</span><span class="p">(</span><span class="n">less</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">list</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">greaterNext</span><span class="p">(</span><span class="n">greater</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">k</span><span class="o">--</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">list</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">lessNext</span><span class="p">(</span><span class="n">Deque</span><span class="o">&lt;</span><span class="n">TreeNode</span><span class="o">&gt;</span><span class="w"> </span><span class="n">stack</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">top</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">stack</span><span class="p">.</span><span class="na">pop</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">top</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">top</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">top</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">top</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">stack</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">top</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">top</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">top</span><span class="p">.</span><span class="na">right</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">r</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">greaterNext</span><span class="p">(</span><span class="n">Deque</span><span class="o">&lt;</span><span class="n">TreeNode</span><span class="o">&gt;</span><span class="w"> </span><span class="n">stack</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">TreeNode</span><span class="w"> </span><span class="n">top</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">stack</span><span class="p">.</span><span class="na">pop</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">top</span><span class="p">.</span><span class="na">val</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">top</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">top</span><span class="p">.</span><span class="na">right</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">top</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">stack</span><span class="p">.</span><span class="na">push</span><span class="p">(</span><span class="n">top</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">top</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">top</span><span class="p">.</span><span class="na">left</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="n">r</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>]]></description></item><item><title>新年</title><link>https://blog.terryx.com/posts/new-year/</link><pubDate>Wed, 21 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/new-year/</guid><description><![CDATA[<p>建好了博客回头发现竟然整整一年没有再用过。一直挂着域名续着钱总不能浪费了。其实是2017过得实在是难以形容，今天想更新一些东西结果发现模板也不能用了，改了之后发现格式排版又乱七八糟，索性改了个默认的算了。去年我做了什么呢，想想也是挺多的。从年中把刷题网站做了快500题，挂了几家公司的面试，开始重新学了下操作系统和数据库，跟了一个公开课，顺便提前修完学分毕了业赋闲在家。当然这都是正事。闲事是刀塔2又加了一百多的游戏时间，玩了玩绝地求生，买了别的游戏基本也没怎么碰，去了趟加州，去了趟芝加哥。感觉也没少做事，结果也没有什么，处于回国与继续留下混的心里煎熬，主要是搬砖都没个地方能收留我，英语口语又不好，文化上总觉得是格格不入。总之是，又想回家又舍不得墙外的清净，想着要两边好处。</p>
<p>这几天又重新拾起来以前经常做的算法竞赛，发现自己越来越水。原来是自己很水却不自知，现在是知道了也没法改变，不过倒是觉得心态挺好，完全是学习的感觉，排名随意了。我理解算法竞赛快成了程序员的基本功，肉眼debug与编程的准确性，这些都很重要不是吗？希望能多涨涨rank，虽然连刷题网站我都没法稳定前200，上周出了两个图论题就崩了。现在对于我本科时代狗屁没学懂的结论简直是不能再认同了。</p>
<p>前几天一直有个想法，想把一个公开课的项目用js实现出来。类似与一个Google Map和地铁信息网站的结合吧，希望这段时间能做出来。至于后面的面试，我越来越看开了，爱怎么样就怎么样，要就要不要拉倒。觉得天天跪舔这些公司烦得很，尤其这些social的事情，我又做不好。因为我这样的性格，很难融于这样的环境。可能我也是羡慕也是嫉妒吧，要改变自己很难，要做成超出自己能力的事情更难。</p>
<p>以及，我前几天过了24岁生日。我走到了人生苦短与及时行乐的过渡区域。</p>
]]></description></item><item><title>Hierarchical Data and the Closure Property</title><link>https://blog.terryx.com/posts/sicp-2-2/</link><pubDate>Mon, 02 Jan 2017 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-2-2/</guid><description><![CDATA[<h2 id="section-22--hierarchical-data-and-the-closure-property">Section 2.2  Hierarchical Data and the Closure Property</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 2.17.</strong>  Define a procedure <code>last-pair</code> that returns the list that contains only the last element of a given (nonempty) list:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(last-pair (list 23 72 149 34))
</span></span><span class="line"><span class="cl">(34)
</span></span></code></pre></div><p><strong>Answer 2.17.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (last-pair items)
</span></span><span class="line"><span class="cl">    (if (null? (cdr items))
</span></span><span class="line"><span class="cl">        items
</span></span><span class="line"><span class="cl">        (last-pair (cdr items))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.18.</strong>  Define a procedure <code>reverse</code> that takes a list as argument and returns a list of the same elements in reverse order:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(reverse (list 1 4 9 16 25))
</span></span><span class="line"><span class="cl">(25 16 9 4 1)
</span></span></code></pre></div><p><strong>Answer 2.18.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (reverse items)
</span></span><span class="line"><span class="cl">    (if (null? (cdr items))
</span></span><span class="line"><span class="cl">        items
</span></span><span class="line"><span class="cl">        (append (reverse (cdr items)) (cons (car items) ()))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.19.</strong>  Consider the change-counting program of section 1.2.2. It would be nice to be able to easily change the currency used by the program, so that we could compute the number of ways to change a British pound, for example. As the program is written, the knowledge of the currency is distributed partly into the procedure <code>first-denomination</code> and partly into the procedure <code>count-change</code> (which knows that there are five kinds of U.S. coins). It would be nicer to be able to supply a list of coins to be used for making change.</p>
<p>We want to rewrite the procedure cc so that its second argument is a list of the values of the coins to use rather than an integer specifying which coins to use. We could then have lists that defined each kind of currency:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define us-coins (list 50 25 10 5 1))
</span></span><span class="line"><span class="cl">(define uk-coins (list 100 50 20 10 5 2 1 0.5))
</span></span></code></pre></div><p>We could then call cc as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(cc 100 us-coins)
</span></span><span class="line"><span class="cl">292
</span></span></code></pre></div><p>To do this will require changing the program <code>cc</code> somewhat. It will still have the same form, but it will access its second argument differently, as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cc amount coin-values)
</span></span><span class="line"><span class="cl">  (cond ((= amount 0) 1)
</span></span><span class="line"><span class="cl">        ((or (&lt; amount 0) (no-more? coin-values)) 0)
</span></span><span class="line"><span class="cl">        (else
</span></span><span class="line"><span class="cl">         (+ (cc amount
</span></span><span class="line"><span class="cl">                (except-first-denomination coin-values))
</span></span><span class="line"><span class="cl">            (cc (- amount
</span></span><span class="line"><span class="cl">                   (first-denomination coin-values))
</span></span><span class="line"><span class="cl">                coin-values)))))
</span></span></code></pre></div><p>Define the procedures <code>first-denomination</code>, <code>except-first-denomination</code>, and <code>no-more?</code> in terms of primitive operations on list structures. Does the order of the list <code>coin-values</code> affect the answer produced by <code>cc</code>? Why or why not?</p>
<p><strong>Answer 2.19.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cc amount coin-values)
</span></span><span class="line"><span class="cl">  (cond ((= amount 0) 1)
</span></span><span class="line"><span class="cl">        ((or (&lt; amount 0) (no-more? coin-values)) 0)
</span></span><span class="line"><span class="cl">        (else
</span></span><span class="line"><span class="cl">         (+ (cc amount
</span></span><span class="line"><span class="cl">                (except-first-denomination coin-values))
</span></span><span class="line"><span class="cl">            (cc (- amount
</span></span><span class="line"><span class="cl">                   (first-denomination coin-values))
</span></span><span class="line"><span class="cl">                coin-values)))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (no-more? coin-values)
</span></span><span class="line"><span class="cl">    (null? coin-values)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (except-first-denomination coin-values)
</span></span><span class="line"><span class="cl">    (cdr coin-values)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (first-denomination coin-values)
</span></span><span class="line"><span class="cl">    (car coin-values)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define us-coins (list 50 25 10 5 1))
</span></span><span class="line"><span class="cl">(define uk-coins (list 100 50 20 10 5 2 1 0.5))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(cc 100 us-coins)
</span></span></code></pre></div><p><strong>Exercise 2.20.</strong>  The procedures <code>+</code>, <code>*</code>, and list take arbitrary numbers of arguments. One way to define such procedures is to use define with <em>dotted-tail notation</em>. In a procedure definition, a parameter list that has a dot before the last parameter name indicates that, when the procedure is called, the initial parameters (if any) will have as values the initial arguments, as usual, but the final parameter’s value will be a <em>list</em> of any remaining arguments. For instance, given the definition</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (f x y . z) &lt;body&gt;)
</span></span></code></pre></div><p>the procedure <code>f</code> can be called with two or more arguments. If we evaluate</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(f 1 2 3 4 5 6)
</span></span></code></pre></div><p>then in the body of <code>f</code>, <code>x</code> will be $1$, <code>y</code> will be $2$, and <code>z</code> will be the list <code>(3 4 5 6)</code>. Given the definition</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (g . w) &lt;body&gt;)
</span></span></code></pre></div><p>the procedure <code>g</code> can be called with zero or more arguments. If we evaluate</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(g 1 2 3 4 5 6)
</span></span></code></pre></div><p>then in the body of <code>g</code>, <code>w</code> will be the list <code>(1 2 3 4 5 6)</code>.</p>
<p>Use this notation to write a procedure <code>same-parity</code> that takes one or more integers and returns a list of all the arguments that have the same even-odd parity as the first argument. For example,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(same-parity 1 2 3 4 5 6 7)
</span></span><span class="line"><span class="cl">(1 3 5 7)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(same-parity 2 3 4 5 6 7)
</span></span><span class="line"><span class="cl">(2 4 6)
</span></span></code></pre></div><p><strong>Answer 2.20.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (same-parity first . rest)
</span></span><span class="line"><span class="cl">    (define (filter x)
</span></span><span class="line"><span class="cl">        (if (even? x)
</span></span><span class="line"><span class="cl">            even?
</span></span><span class="line"><span class="cl">            odd?
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (parity f l)
</span></span><span class="line"><span class="cl">        (cond ((null? l) ())
</span></span><span class="line"><span class="cl">              ((f (car l)) (cons (car l) (parity f (cdr l))))
</span></span><span class="line"><span class="cl">              (else (parity f (cdr l)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (parity (filter first) rest)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.21.</strong>  The procedure <code>square-list</code> takes a list of numbers as argument and returns a list of the squares of those numbers.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(square-list (list 1 2 3 4))
</span></span><span class="line"><span class="cl">(1 4 9 16)
</span></span></code></pre></div><p>Here are two different definitions of <code>square-list</code>. Complete both of them by filling in the missing expressions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (if (null? items)
</span></span><span class="line"><span class="cl">      nil
</span></span><span class="line"><span class="cl">      (cons &lt;??&gt; &lt;??&gt;)))
</span></span><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (map &lt;??&gt; &lt;??&gt;))
</span></span></code></pre></div><p><strong>Answer 2.21.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">    (if (null? items)
</span></span><span class="line"><span class="cl">        `()
</span></span><span class="line"><span class="cl">        (cons (square (car items)) (square-list (cdr items)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x) (* x x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square-list-map items)
</span></span><span class="line"><span class="cl">    (map square items)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.22.</strong>  Louis Reasoner tries to rewrite the first <code>square-list</code> procedure of exercise 2.21 so that it evolves an iterative process:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (define (iter things answer)
</span></span><span class="line"><span class="cl">    (if (null? things)
</span></span><span class="line"><span class="cl">        answer
</span></span><span class="line"><span class="cl">        (iter (cdr things) 
</span></span><span class="line"><span class="cl">              (cons (square (car things))
</span></span><span class="line"><span class="cl">                    answer))))
</span></span><span class="line"><span class="cl">  (iter items nil))
</span></span></code></pre></div><p>Unfortunately, defining square-list this way produces the answer list in the reverse order of the one desired. Why?</p>
<p>Louis then tries to fix his bug by interchanging the arguments to <code>cons</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (define (iter things answer)
</span></span><span class="line"><span class="cl">    (if (null? things)
</span></span><span class="line"><span class="cl">        answer
</span></span><span class="line"><span class="cl">        (iter (cdr things)
</span></span><span class="line"><span class="cl">              (cons answer
</span></span><span class="line"><span class="cl">                    (square (car things))))))
</span></span><span class="line"><span class="cl">  (iter items nil))
</span></span></code></pre></div><p>This doesn’t work either. Explain.</p>
<p><strong>Answer 2.22.</strong> The first procedure doesn’t work because it constructs the last item from the front of the list to the answer. The second procedure seems right at first glance, but result is:</p>
<p><code>(square-list (list 1 2 3 4)) ((((() 1) 4) 9) 16)</code></p>
<p>Let’s look the definition of <code>list</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(list &lt;a_1&gt; &lt;a_2&gt; ... &lt;a_n&gt;)
</span></span><span class="line"><span class="cl">(cons &lt;a_1&gt; (cons &lt;a_2&gt; ... (cons &lt;a_n&gt; nil) ... ))
</span></span></code></pre></div><p>And the substitution of the procedure:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(square-list (list 1 2 3 4))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 1 2 3 4) &#39;())
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 2 3 4) (cons &#39;() (square 1)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 3 4) (cons (cons &#39;() 1)
</span></span><span class="line"><span class="cl">                       (square 2)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 4)  (cons (cons (cons &#39;() 1) 4)
</span></span><span class="line"><span class="cl">                      (square 3)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter &#39;() (cons (cons (cons (cons &#39;() 1) 4) 9)
</span></span><span class="line"><span class="cl">                (square 4)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter &#39;() (cons (cons (cons (cons &#39;() 1) 4) 9) 16))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(cons (cons (cons (cons &#39;() 1) 4) 9) 16)
</span></span></code></pre></div><p>Therefore, the structure of answer is wrong.</p>
<p><strong>Exercise 2.23.</strong>  The procedure <code>for-each</code> is similar to <code>map</code>. It takes as arguments a procedure and a list of elements. However, rather than forming a list of the results, <code>for-each</code> just applies the procedure to each of the elements in turn, from left to right. The values returned by applying the procedure to the elements are not used at all – <code>for-each</code> is used with procedures that perform an action, such as printing. For example,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(for-each (lambda (x) (newline) (display x))
</span></span><span class="line"><span class="cl">          (list 57 321 88))
</span></span><span class="line"><span class="cl">57
</span></span><span class="line"><span class="cl">321
</span></span><span class="line"><span class="cl">88
</span></span></code></pre></div><p>The value returned by the call to <code>for-each</code> (not illustrated above) can be something arbitrary, such as true. Give an implementation of <code>for-each</code>.</p>
<p><strong>Answer 2.23.</strong>  I find a feature between <code>cond</code> and <code>if</code> in Lisp. If we want to use <code>if</code> instead of <code>cond</code>, one things should be concerned. Here are definitions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(cond (&lt;predicate&gt; &lt;expression&gt; ...)
</span></span><span class="line"><span class="cl">	  ...
</span></span><span class="line"><span class="cl">	  (else &lt;expression&gt; ..)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(if &lt;predicate&gt;
</span></span><span class="line"><span class="cl">	&lt;consequent&gt;
</span></span><span class="line"><span class="cl">	&lt;alternative&gt;
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p>In <code>cond</code>, one clause has one predicate and several expressions, meanwhile consequent and alternative of <code>if</code> only have one expression for each. Thus, in this exercise we should use <code>cond</code> because <code>(newline)</code> and <code>(display x)</code> are two expressions.</p>
<pre tabindex="0"><code>(define (for-each f l)
    (cond ((null? l) &#39;()) 
          (else (f (car l))
                (for-each f (cdr l)))
    )
)
</code></pre><p><strong>Exercise 2.24.</strong>  Suppose we evaluate the expression <code>(list 1 (list 2 (list 3 4)))</code>. Give the result printed by the interpreter, the corresponding box-and-pointer structure, and the interpretation of this as a tree (as in figure 2.6).</p>
]]></description></item><item><title>Introduction to Data Abstraction</title><link>https://blog.terryx.com/posts/sicp-2-1/</link><pubDate>Sat, 31 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-2-1/</guid><description><![CDATA[<h2 id="section-21--introduction-to-data-abstraction">Section 2.1  Introduction to Data Abstraction</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 2.1.</strong>  Define a better version of <code>make-rat</code> that handles both positive and negative arguments. <code>Make-rat</code> should normalize the sign so that if the rational number is positive, both the numerator and denominator are positive, and if the rational number is negative, only the numerator is negative.</p>
<p><strong>Answer 2.1.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (numer x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (denom x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-rat x)
</span></span><span class="line"><span class="cl">    (newline)
</span></span><span class="line"><span class="cl">    (display (numer x))
</span></span><span class="line"><span class="cl">    (display &#34;/&#34;)
</span></span><span class="line"><span class="cl">    (display (denom x))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-rat n d)
</span></span><span class="line"><span class="cl">    (let ((g ((if (&lt; d 0) - +) (abs (gcd n d)))))
</span></span><span class="line"><span class="cl">        (cons (/ n g) (/ d g))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.2.</strong>  Consider the problem of representing line segments in a plane. Each segment is represented as a pair of points: a starting point and an ending point. Define a constructor <code>make-segment</code> and selectors <code>start-segment</code> and <code>end-segment</code> that define the representation of segments in terms of points. Furthermore, a point can be represented as a pair of numbers: the $x$ coordinate and the $y$ coordinate. Accordingly, specify a constructor <code>make-point</code> and selectors <code>x-point</code> and <code>y-point</code> that define this representation. Finally, using your selectors and constructors, define a procedure <code>midpoint-segment</code> that takes a line segment as argument and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints). To try your procedures, you’ll need a way to print points:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (print-point p)
</span></span><span class="line"><span class="cl">  (newline)
</span></span><span class="line"><span class="cl">  (display &#34;(&#34;)
</span></span><span class="line"><span class="cl">  (display (x-point p))
</span></span><span class="line"><span class="cl">  (display &#34;,&#34;)
</span></span><span class="line"><span class="cl">  (display (y-point p))
</span></span><span class="line"><span class="cl">  (display &#34;)&#34;))
</span></span></code></pre></div><p><strong>Answer 2.2.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (x-point x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (y-point x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-point p)
</span></span><span class="line"><span class="cl">    (newline)
</span></span><span class="line"><span class="cl">    (display &#34;(&#34;)
</span></span><span class="line"><span class="cl">    (display (x-point p))
</span></span><span class="line"><span class="cl">    (display &#34;,&#34;)
</span></span><span class="line"><span class="cl">    (display (y-point p))
</span></span><span class="line"><span class="cl">    (display &#34;)&#34;)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-point x y)
</span></span><span class="line"><span class="cl">    (cons x y)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (start-segment x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (end-segment x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-segment x y)
</span></span><span class="line"><span class="cl">    (cons x y)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (midpoint-segment s)
</span></span><span class="line"><span class="cl">    (define (average a b) (/ (+ a b) 2.0))
</span></span><span class="line"><span class="cl">    (let (
</span></span><span class="line"><span class="cl">            (a (start-segment s))
</span></span><span class="line"><span class="cl">            (b (end-segment s))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (make-point (average (x-point a) (x-point b)) (average (y-point a) (y-point b)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.3.</strong>  Implement a representation for rectangles in a plane. (Hint: You may want to make use of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle. Now implement a different representation for rectangles. Can you design your system with suitable abstraction barriers, so that the same perimeter and area procedures will work using either representation?</p>
<p><strong>Answer 2.3.</strong> Here, it talks about axis-aligned rectangles.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (x-point x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (y-point x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-point p)
</span></span><span class="line"><span class="cl">    (newline)
</span></span><span class="line"><span class="cl">    (display &#34;(&#34;)
</span></span><span class="line"><span class="cl">    (display (x-point p))
</span></span><span class="line"><span class="cl">    (display &#34;,&#34;)
</span></span><span class="line"><span class="cl">    (display (y-point p))
</span></span><span class="line"><span class="cl">    (display &#34;)&#34;)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-point x y)
</span></span><span class="line"><span class="cl">    (cons x y)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-rect p1 p2)
</span></span><span class="line"><span class="cl">    (let (
</span></span><span class="line"><span class="cl">            (x1 (x-point p1))
</span></span><span class="line"><span class="cl">            (x2 (x-point p2))
</span></span><span class="line"><span class="cl">            (y1 (y-point p1))
</span></span><span class="line"><span class="cl">            (y2 (y-point p2))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (cond 
</span></span><span class="line"><span class="cl">            ((and (&lt; x1 x2) (&lt; y1 y2)) (cons p1 p2))
</span></span><span class="line"><span class="cl">            ((and (&gt; x1 x2) (&gt; y1 y2)) (cons p2 p1))
</span></span><span class="line"><span class="cl">            ((and (&lt; x1 x2) (&gt; y1 y2)) (cons (make-point (x1 y2)) (make-point (x2 y1))))
</span></span><span class="line"><span class="cl">            (else (cons (make-point (x2 y1)) (make-point (x1 y2))))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (bottom-left r) (car r))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (top-right r) (cdr r))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-rect r)
</span></span><span class="line"><span class="cl">    (print-point (bottom-left r))
</span></span><span class="line"><span class="cl">    (print-point (top-right r))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (perimeter r)
</span></span><span class="line"><span class="cl">    (let (
</span></span><span class="line"><span class="cl">            (p1 (bottom-left r))
</span></span><span class="line"><span class="cl">            (p2 (top-right r))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (let (
</span></span><span class="line"><span class="cl">                (x1 (x-point p1))
</span></span><span class="line"><span class="cl">                (x2 (x-point p2))
</span></span><span class="line"><span class="cl">                (y1 (y-point p1))
</span></span><span class="line"><span class="cl">                (y2 (y-point p2))
</span></span><span class="line"><span class="cl">              )
</span></span><span class="line"><span class="cl">              (* 2 (+ (- x2 x1) (- y2 y1)))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">    )    
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (area r)
</span></span><span class="line"><span class="cl">     (let (
</span></span><span class="line"><span class="cl">            (p1 (bottom-left r))
</span></span><span class="line"><span class="cl">            (p2 (top-right r))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (let (
</span></span><span class="line"><span class="cl">                (x1 (x-point p1))
</span></span><span class="line"><span class="cl">                (x2 (x-point p2))
</span></span><span class="line"><span class="cl">                (y1 (y-point p1))
</span></span><span class="line"><span class="cl">                (y2 (y-point p2))
</span></span><span class="line"><span class="cl">              )
</span></span><span class="line"><span class="cl">              (* (- x2 x1) (- y2 y1))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">    )    
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define r (make-rect (make-point 1 1)
</span></span><span class="line"><span class="cl">                     (make-point 4 5)))
</span></span></code></pre></div><p><strong>Exercise 2.4.</strong>  Here is an alternative procedural representation of pairs. For this representation, verify that <code>(car (cons x y))</code> yields $x$ for any objects $x$ and $y$.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cons x y)
</span></span><span class="line"><span class="cl">  (lambda (m) (m x y)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (car z)
</span></span><span class="line"><span class="cl">  (z (lambda (p q) p)))
</span></span></code></pre></div><p>What is the corresponding definition of <code>cdr</code>? (Hint: To verify that this works, make use of the substitution model of section 1.1.5.)</p>
<p><strong>Answer 2.4.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cdr z)
</span></span><span class="line"><span class="cl">	(z (lambda (p q) q))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p>Substitution model:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (cdr z)
</span></span><span class="line"><span class="cl">=&gt; (z (lambda (p q) p))
</span></span><span class="line"><span class="cl">=&gt; ((lambda (m) (m x y) (lambda (p q) q)))
</span></span><span class="line"><span class="cl">=&gt; ((lambda (p q) q) x y)
</span></span><span class="line"><span class="cl">=&gt; y
</span></span></code></pre></div><p><strong>Exercise 2.5.</strong>  Show that we can represent pairs of nonnegative integers using only numbers and arithmetic operations if we represent the pair $a$ and $b$ as the integer that is the product $2^a 3^b$. Give the corresponding definitions of the procedures <code>cons</code>, <code>car</code>, and <code>cdr</code>.</p>
<p><strong>Answer 2.5.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cons a b)
</span></span><span class="line"><span class="cl">    (* (expt 2 a) (expt 3 b))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (logb b n) (floor (/ (log n) (log b))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (car x)
</span></span><span class="line"><span class="cl">    (logb 2 (/ x (gcd x (expt 3 (logb 3 x)))))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cdr x)
</span></span><span class="line"><span class="cl">    (logb 3 (/ x (gcd x (expt 2 (logb 2 x)))))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.6.</strong>  In case representing pairs as procedures wasn’t mind-boggling enough, consider that, in a language that can manipulate procedures, we can get by without numbers (at least insofar as nonnegative integers are concerned) by implementing $0$ and the operation of adding $1$ as</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define zero (lambda (f) (lambda (x) x)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (add-1 n)
</span></span><span class="line"><span class="cl">  (lambda (f) (lambda (x) (f ((n f) x)))))
</span></span></code></pre></div><p>This representation is known as <em>Church numerals</em>, after its inventor, Alonzo Church, the logician who invented the $\lambda$ calculus.</p>
<p>Define <code>one</code> and <code>two</code> directly (not in terms of <code>zero</code> and <code>add-1</code>). (Hint: Use substitution to evaluate (<code>add-1 zero</code>)). Give a direct definition of the addition procedure <code>+</code> (not in terms of repeated application of <code>add-1</code>).</p>
<p><strong>Answer 2.6.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (one)
</span></span><span class="line"><span class="cl">=&gt; (add-1 zero)
</span></span><span class="line"><span class="cl">=&gt; (lambda (f) (lambda (x) (f ((zero f) x))))
</span></span></code></pre></div><p><code>zero</code> is a function of one argument, that returns a function of one argument that returns the argument.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; ((zero f) x)
</span></span><span class="line"><span class="cl">=&gt; ((lambda(x) x) x)
</span></span><span class="line"><span class="cl">=&gt; x
</span></span></code></pre></div><p>So, <code>one</code> and <code>two</code> are:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (one)
</span></span><span class="line"><span class="cl">=&gt; (lambda (f) (lambda (x) (f x)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">=&gt; (two)
</span></span><span class="line"><span class="cl">=&gt; (add-1 two)
</span></span><span class="line"><span class="cl">=&gt; (lambda (f) (lambda (x) (f (f x))))
</span></span></code></pre></div><p>Thus,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define one (lambda (f) (lambda (x) (f x))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define two (lambda (f) (lambda (x) (f (f x)))))
</span></span></code></pre></div><p>And <code>add</code> using the same approach in <code>add-1</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (add a b)
</span></span><span class="line"><span class="cl">	(lambda (f)
</span></span><span class="line"><span class="cl">		(lambda (x) (a f) ((b f) x))
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.7.</strong>  Alyssa’s program is incomplete because she has not specified the implementation of the interval abstraction. Here is a definition of the interval constructor:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (make-interval a b) (cons a b))
</span></span></code></pre></div><p>Define selectors <code>upper-bound</code> and <code>lower-bound</code> to complete the implementation.</p>
<p><strong>Answer 2.7.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (upper-bound interval)
</span></span><span class="line"><span class="cl">	(max (car interval) (cdr interval))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (lower-bound interval)
</span></span><span class="line"><span class="cl">	(min (car interval) (cdr interval))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.8.</strong>  Using reasoning analogous to Alyssa’s, describe how the difference of two intervals may be computed. Define a corresponding subtraction procedure, called <code>sub-interval</code>.</p>
<p><strong>Answer 2.8.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sub-interval x y)
</span></span><span class="line"><span class="cl">	(make-interval (- (lower-bound x) (upper-bound y))
</span></span><span class="line"><span class="cl">				   (- (upper-bound x) (lower-bound y)))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.9.</strong>  The <em>width</em> of an interval is half of the difference between its upper and lower bounds. The width is a measure of the uncertainty of the number specified by the interval. For some arithmetic operations the width of the result of combining two intervals is a function only of the widths of the argument intervals, whereas for others the width of the combination is not a function of the widths of the argument intervals. Show that the width of the sum (or difference) of two intervals is a function only of the widths of the intervals being added (or subtracted). Give examples to show that this is not true for multiplication or division.</p>
<p><strong>Answer 2.9.</strong> For multiplication and division, the story is different. If the width of the result was a function of the widths of the inputs, then multiplying different intervals with the same widths should give the same answer. For example, multiplying a width 5 interval with a width 1 interval.</p>
<p><strong>Exercise 2.10.</strong>  Ben Bitdiddle, an expert systems programmer, looks over Alyssa’s shoulder and comments that it is not clear what it means to divide by an interval that spans zero. Modify Alyssa’s code to check for this condition and to signal an error if it occurs.</p>
<p><strong>Answer 2.10.</strong> We should guarantee:</p>
<p>$$
R_p = \frac{1}{1/R_1+1/R_2} = \frac{R_1+R_2}{R_1 R_2}, \text{where } R_1 R_2 \neq 0.
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (div-interval x y)
</span></span><span class="line"><span class="cl">	(if (&gt;= 0 (* (lower-bound y) (upper-bound y)))
</span></span><span class="line"><span class="cl">		(error &#34;Divison 0 error&#34;)
</span></span><span class="line"><span class="cl">		(mul-interval x (make-interval (/ 1 (upper-bound y))
</span></span><span class="line"><span class="cl">							(/ 1 (lower-bound y))
</span></span><span class="line"><span class="cl">						))
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.11.</strong>  In passing, Ben also cryptically comments: “By testing the signs of the endpoints of the intervals, it is possible to break <code>mul-interval</code> into nine cases, only one of which requires more than two multiplications.” Rewrite this procedure using Ben’s suggestion.</p>
<p>After debugging her program, Alyssa shows it to a potential user, who complains that her program solves the wrong problem. He wants a program that can deal with numbers represented as a center value and an additive tolerance; for example, he wants to work with intervals such as $3.5 \pm 0.15$ rather than $[3.35, 3.65]$. Alyssa returns to her desk and fixes this problem by supplying an alternate constructor and alternate selectors:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (make-center-width c w)
</span></span><span class="line"><span class="cl">  (make-interval (- c w) (+ c w)))
</span></span><span class="line"><span class="cl">(define (center i)
</span></span><span class="line"><span class="cl">  (/ (+ (lower-bound i) (upper-bound i)) 2))
</span></span><span class="line"><span class="cl">(define (width i)
</span></span><span class="line"><span class="cl">  (/ (- (upper-bound i) (lower-bound i)) 2))
</span></span></code></pre></div><p>Unfortunately, most of Alyssa’s users are engineers. Real engineering situations usually involve measurements with only a small uncertainty, measured as the ratio of the width of the interval to the midpoint of the interval. Engineers usually specify percentage tolerances on the parameters of devices, as in the resistor specifications given earlier.</p>
]]></description></item><item><title>Formulating Abstractions with Higher-Order Procedures</title><link>https://blog.terryx.com/posts/sicp-1-3/</link><pubDate>Sun, 25 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-1-3/</guid><description><![CDATA[<h2 id="section-13-formulating-abstractions-with-higher-order-procedures">Section 1.3 Formulating Abstractions with Higher-Order Procedures</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>, and Merry Xmas.</p>
<p><strong>Exercise 1.29.</strong>  Simpson’s Rule is a more accurate method of numerical integration than the method illustrated above. Using Simpson’s Rule, the integral of a function $f$ between $a$ and $b$ is approximated as</p>
<p>$$
\frac{h}{3}[y_0+4y_1+2y_2+4y_3+…+2y_{n-2}+4y_{n-1}+y_n]
$$</p>
<p>where $h = (b - a)/n$, for some even integer $n$, and $y_k = f(a + kh)$. (Increasing $n$ increases the accuracy of the approximation.) Define a procedure that takes as arguments $f$, $a$, $b$, and $n$ and returns the value of the integral, computed using Simpson’s Rule. Use your procedure to integrate cube between $0$ and $1$ (with $n = 100$ and $n = 1000$), and compare the results to those of the integral procedure shown above.</p>
<p><strong>Answer 1.29.</strong> The Simpson’s Rule can also be written as follow:</p>
<p>$$
\frac{h}{3}[y_0+4y_1+2y_2+4y_3+…+2y_{n-2}+4y_{n-1}+y_n] = \frac{h}{3}\sum_{j=2,4…}^{n}[y_{j-2} + 4y_{j-1} + y_{j}]
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        0
</span></span><span class="line"><span class="cl">        (+ (term a)
</span></span><span class="line"><span class="cl">           (sum term (next a) next b)
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (simpson-rule f a b n)
</span></span><span class="line"><span class="cl">    (define (simpson-next x)
</span></span><span class="line"><span class="cl">        (+ x 2)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    (define h (/ (- b a) n))
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    (define (y k)
</span></span><span class="line"><span class="cl">        (f (+ a (* k h)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (simpson-term x)
</span></span><span class="line"><span class="cl">        (+
</span></span><span class="line"><span class="cl">            (y x)
</span></span><span class="line"><span class="cl">            (* 4 (y (+ x 1)))
</span></span><span class="line"><span class="cl">            (y (+ x 2))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (* (sum simpson-term 0 simpson-next n ) (/ h 3))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cub x)
</span></span><span class="line"><span class="cl">    (* x x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(exact-&gt;inexact(simpson-rule cub 0 1 100))
</span></span><span class="line"><span class="cl">(exact-&gt;inexact(simpson-rule cub 0 1 1000))
</span></span></code></pre></div><p><strong>Exercise 1.30.</strong>  The <code>sum</code> procedure above generates a linear recursion. The procedure can be rewritten so that the sum is performed iteratively. Show how to do this by filling in the missing expressions in the following definition:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">  (define (iter a result)
</span></span><span class="line"><span class="cl">      (if &lt;??&gt;
</span></span><span class="line"><span class="cl">	      &lt;??&gt;
</span></span><span class="line"><span class="cl">		  (iter &lt;??&gt; &lt;??&gt;))
</span></span><span class="line"><span class="cl">  (iter &lt;??&gt; &lt;??&gt;)
</span></span></code></pre></div><p><strong>Answer 1.30.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">	(define (iter a result)
</span></span><span class="line"><span class="cl">		(if (&gt; a b)
</span></span><span class="line"><span class="cl">			result
</span></span><span class="line"><span class="cl">			(iter (next a) (+ result (term a)))
</span></span><span class="line"><span class="cl">		)
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">	(iter a 0)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.31.</strong></p>
<p>a.  The <code>sum</code> procedure is only the simplest of a vast number of similar abstractions that can be captured as higher-order procedures. Write an analogous procedure called <code>product</code> that returns the product of the values of a function at points over a given range. Show how to define <code>factorial</code> in terms of product. Also use product to compute approximations to $\pi$ using the formula</p>
<p>$$
\frac{\pi}{4}=\frac{2 \cdot 4 \cdot 4 \cdot 6 \cdot 6 \cdot 8 …}{3 \cdot 3 \cdot 5 \cdot 5 \cdot 7 \cdot 7 …}
$$</p>
<p>b.  If your product procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.</p>
<p><strong>Answer 1.31.</strong></p>
<p>$$
\frac{\pi}{4}=\frac{2 \cdot 4 \cdot 4 \cdot 6 \cdot 6 \cdot 8 …}{3 \cdot 3 \cdot 5 \cdot 5 \cdot 7 \cdot 7 …} =
\frac{1}{n+1}\prod_{i=1}^{n}[(\frac{2(i+1)}{2i})^2]
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (product term a next b)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        1
</span></span><span class="line"><span class="cl">        (* (term a) (product term (next a) next b))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (factorial n)
</span></span><span class="line"><span class="cl">    (define (identity x)
</span></span><span class="line"><span class="cl">        x
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (define (next x)
</span></span><span class="line"><span class="cl">        (+ x 1)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (product identity 1 next n)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (product term a next b)
</span></span><span class="line"><span class="cl">    (define (iter a result)
</span></span><span class="line"><span class="cl">        (if (&gt; a b)
</span></span><span class="line"><span class="cl">            result
</span></span><span class="line"><span class="cl">            (iter (next a) (* result (term a)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (iter a 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (pi-product a b)
</span></span><span class="line"><span class="cl">    (define (pi-term x)
</span></span><span class="line"><span class="cl">       (square (/ (* 2 (+ x 1)) (+ (* 2 x) 1)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (define (pi-next x)
</span></span><span class="line"><span class="cl">        (+ x 1)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (* 4 (/ (product-iter pi-term a pi-next b) (+ b 1)))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(exact-&gt;inexact(pi-product 1 10000))
</span></span></code></pre></div><p><strong>Exercise 1.32.</strong></p>
<p>a. Show that <code>sum</code> and <code>product</code> (exercise 1.31) are both special cases of a still more general notion called <code>accumulate</code> that combines a collection of terms, using some general accumulation function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(accumulate combiner null-value term a next b)
</span></span></code></pre></div><p><code>Accumulate</code> takes as arguments the same term and range specifications as <code>sum</code> and <code>product</code>, together with a <code>combiner</code> procedure (of two arguments) that specifies how the current term is to be combined with the accumulation of the preceding terms and a <code>null-value</code> that specifies what base value to use when the terms run out. Write <code>accumulate</code> and show how <code>sum</code> and <code>product</code> can both be defined as simple calls to <code>accumulate</code>.</p>
<p>b. If your <code>accumulate</code> procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.</p>
<p><strong>Answer 1.32.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (accumulate combiner null-value term a next b)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        null-value
</span></span><span class="line"><span class="cl">        (combiner (term a) (accumulate combiner null-value term (next a) next b))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (accumlate-iter combiner null-value term a next b)
</span></span><span class="line"><span class="cl">    (define (iter a result)
</span></span><span class="line"><span class="cl">        (if (&gt; a b) res
</span></span><span class="line"><span class="cl">            (iter (next a) (combiner res (term a)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (iter a null-value)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">    (accumulate + 0 term a next b)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (product term a next b)
</span></span><span class="line"><span class="cl">    (accumlate * 1 term a next b)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.33.</strong>  You can obtain an even more general version of <code>accumulate</code> (exercise 1.32) by introducing the notion of a <em>filter</em> on the terms to be combined. That is, combine only those terms derived from values in the range that satisfy a specified condition. The resulting <code>filtered-accumulate</code> abstraction takes the same arguments as accumulate, together with an additional predicate of one argument that specifies the filter. Write <code>filtered-accumulate</code> as a procedure. Show how to express the following using <code>filtered-accumulate</code>:</p>
<p>a. the sum of the squares of the prime numbers in the interval $a$ to $b$ (assuming that you have a <code>prime</code>? predicate already written)</p>
<p>b. the product of all the positive integers less than $n$ that are relatively prime to $n$ (i.e., all positive integers $i &lt; n$ such that $GCD(i,n) = 1)$.</p>
<p><strong>Answer 1.33.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (filtered-accumulate combiner null-value term a next b filter)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        null-value
</span></span><span class="line"><span class="cl">        (if (filter a)
</span></span><span class="line"><span class="cl">            (combiner (term a) (filtered-accumulate combiner null-value (next a) next b filter))
</span></span><span class="line"><span class="cl">            (combiner null-value (filtered-accumulate combiner null-value (next a) next b filter))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.34.</strong>  Suppose we define the procedure</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (f g)
</span></span><span class="line"><span class="cl">  (g 2))
</span></span></code></pre></div><p>Then we have</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(f square)
</span></span><span class="line"><span class="cl">4
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(f (lambda (z) (* z (+ z 1))))
</span></span><span class="line"><span class="cl">6
</span></span></code></pre></div><p>What happens if we (perversely) ask the interpreter to evaluate the combination <code>(f f)</code>? Explain.</p>
<p><strong>Answer 1.34.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (f f)
</span></span><span class="line"><span class="cl">=&gt; (f 2)
</span></span><span class="line"><span class="cl">=&gt; (2 2)
</span></span></code></pre></div><p>The third invocation will attempt to apply its argument, <code>2</code>, to <code>2</code>, resulting in error.</p>
<p><strong>Exercise 1.35.</strong>  Show that the golden ratio $\phi$ (section 1.2.2) is a fixed point of the transformation $x \mapsto 1 + 1/x$, and use this fact to compute $\phi$ by means of the <code>fixed-point</code> procedure.</p>
<p><strong>Answer 1.35.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define tolerance 0.00001)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fixed-point f first-guess)
</span></span><span class="line"><span class="cl">    (define (close-enough? v1 v2)
</span></span><span class="line"><span class="cl">        (&lt; (abs (- v1 v2)) tolerance)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (try guess)
</span></span><span class="line"><span class="cl">        (let ((next (f guess)))
</span></span><span class="line"><span class="cl">            (if (close-enough? guess next)
</span></span><span class="line"><span class="cl">                next
</span></span><span class="line"><span class="cl">                (try next)
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (try first-guess)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0)
</span></span></code></pre></div><p><strong>Exercise 1.36.</strong>  Modify <code>fixed-point</code> so that it prints the sequence of approximations it generates, using the <code>newline</code> and <code>display</code> primitives shown in exercise 1.22. Then find a solution to $x^x = 1000$ by finding a fixed point of $x \mapsto \log(1000)/\log(x)$. (Use Scheme’s primitive <code>log</code> procedure, which computes natural logarithms.) Compare the number of steps this takes with and without average damping. (Note that you cannot start fixed-point with a guess of $1$, as this would cause division by $\log(1) = 0$.)</p>
<p><strong>Answer 1.36.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define tolerance 0.00001)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fixed-point f first-guess)
</span></span><span class="line"><span class="cl">    (define (close-enough? v1 v2)
</span></span><span class="line"><span class="cl">        (&lt; (abs (- v1 v2)) tolerance)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (try guess)
</span></span><span class="line"><span class="cl">        (display guess)
</span></span><span class="line"><span class="cl">        (newline)
</span></span><span class="line"><span class="cl">        (let ((next (f guess)))
</span></span><span class="line"><span class="cl">            (if (close-enough? guess next)
</span></span><span class="line"><span class="cl">                next
</span></span><span class="line"><span class="cl">                (try next)
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (try first-guess)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(fixed-point (lambda(x) (/ (log 1000.0) (log x))) 2.0)
</span></span></code></pre></div><p><strong>Exercise 1.37.</strong></p>
<p>a. An infinite continued fraction is an expression of the form</p>
<p>$$
f=\frac{N_1}{D_1+\frac{N_2}{D_2+\frac{N_3}{D_3+…}}}
$$</p>
<p>As an example, one can show that the infinite continued fraction expansion with the $N_i$ and the $D_i$ all equal to $1$ produces $1/\phi$, where $\phi$ is the golden ratio (described in section 1.2.2). One way to approximate an infinite continued fraction is to truncate the expansion after a given number of terms. Such a truncation – a so-called <em>$k$-term finite continued fraction</em> – has the form</p>
<p>$$
\frac{N_1}{D_1+\frac{N_2}{…+\frac{N_k}{D_k}}}
$$</p>
<p>Suppose that <code>n</code> and <code>d</code> are procedures of one argument (the term index $i$) that return the $N_i$ and $D_i$ of the terms of the continued fraction. Define a procedure <code>cont-frac</code> such that evaluating <code>(cont-frac n d k)</code> computes the value of the $k$-term finite continued fraction. Check your procedure by approximating $1/\phi$ using</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(cont-frac (lambda (i) 1.0)
</span></span><span class="line"><span class="cl">           (lambda (i) 1.0)
</span></span><span class="line"><span class="cl">           k)
</span></span></code></pre></div><p>for successive values of <code>k</code>. How large must you make <code>k</code> in order to get an approximation that is accurate to $4$ decimal places?</p>
<p>b. If your <code>cont-frac</code> procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.</p>
<p><strong>Answer 1.37.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (con-frac n d k)
</span></span><span class="line"><span class="cl">    (define (frac i)
</span></span><span class="line"><span class="cl">        (if (&lt; i k)
</span></span><span class="line"><span class="cl">            (/ (n i) (+ (d i) (frac (+ i 1))))
</span></span><span class="line"><span class="cl">            (/ (n i) (d i))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (frac 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (con-frac-iter n d k)
</span></span><span class="line"><span class="cl">    (define (frac-iter i result)
</span></span><span class="line"><span class="cl">        (if (= i 0)
</span></span><span class="line"><span class="cl">            result
</span></span><span class="line"><span class="cl">            (frac-iter (- i 1) (/ (n i) (+ (d i) result)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        (frac-iter (- k 1) (/ (n k) (d k)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(con-frac (lambda(i) 1.0) (lambda(i) 1.0) 10)
</span></span></code></pre></div><p><strong>Exercise 1.38.</strong>  In 1737, the Swiss mathematician Leonhard Euler published a memoir <em>De Fractionibus Continuis</em>, which included a continued fraction expansion for $e - 2$, where $e$ is the base of the natural logarithms. In this fraction, the $E_i$ are all $1$, and the $D_i$ are successively $1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, …$. Write a program that uses your <code>cont-frac</code> procedure from exercise 1.37 to approximate $e$, based on Euler’s expansion.</p>
<p><strong>Answer 1.38.</strong></p>
<p>$$
D_i=
\begin{cases}
2(i+1)/3,  &amp; \text{if } i\bmod 3 = 2;<br>
1, &amp; \text{if } i\bmod 3 \neq  2.
\end{cases}
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (con-frac n d k)
</span></span><span class="line"><span class="cl">    (define (frac i)
</span></span><span class="line"><span class="cl">        (if (&lt; i k)
</span></span><span class="line"><span class="cl">            (/ (n i) (+ (d i) (frac (+ i 1))))
</span></span><span class="line"><span class="cl">            (/ (n i) (d i))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (frac 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (eular k)
</span></span><span class="line"><span class="cl">    (+ 2.0 (con-frac 
</span></span><span class="line"><span class="cl">        (lambda(i) 1)
</span></span><span class="line"><span class="cl">        (lambda(i)
</span></span><span class="line"><span class="cl">            (if (= (remainder i 3) 2)
</span></span><span class="line"><span class="cl">                (/ (+ i 1) 1.5)
</span></span><span class="line"><span class="cl">                1
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        k
</span></span><span class="line"><span class="cl">    ))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(eular 100)
</span></span></code></pre></div><p><strong>Exercise 1.39.</strong>  A continued fraction representation of the tangent function was published in 1770 by the German mathematician J.H. Lambert:</p>
<p>$$
\tan x  = \frac{x}{1-\frac{x^2}{3-\frac{x^2}{5-…}}}
$$</p>
<p>where $x$ is in radians. Define a procedure <code>(tan-cf x k)</code> that computes an approximation to the tangent function based on Lambert’s formula. <code>K</code> specifies the number of terms to compute, as in exercise 1.37.</p>
<p><strong>Answer 1.39.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (con-frac n d k)
</span></span><span class="line"><span class="cl">    (define (frac i)
</span></span><span class="line"><span class="cl">        (if (&lt; i k)
</span></span><span class="line"><span class="cl">            (/ (n i) (- (d i) (frac (+ i 1))))
</span></span><span class="line"><span class="cl">            (/ (n i) (d i))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (frac 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (tan-cf x k)
</span></span><span class="line"><span class="cl">    (con-frac 
</span></span><span class="line"><span class="cl">        (lambda (i) (
</span></span><span class="line"><span class="cl">            if (= i 1)
</span></span><span class="line"><span class="cl">                x
</span></span><span class="line"><span class="cl">                (* x x)
</span></span><span class="line"><span class="cl">        ))
</span></span><span class="line"><span class="cl">        (lambda (i) (
</span></span><span class="line"><span class="cl">            - (* 2 i) 1
</span></span><span class="line"><span class="cl">        ))
</span></span><span class="line"><span class="cl">        k
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.40.</strong>  Define a procedure <code>cubic</code> that can be used together with the <code>newtons-method</code> procedure in expressions of the form</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(newtons-method (cubic a b c) 1)
</span></span></code></pre></div><p>to approximate zeros of the cubic $x^3 + ax^2 + bx + c$.</p>
<p><strong>Answer 1.40.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cubic a b c)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (+
</span></span><span class="line"><span class="cl">            (cube x)
</span></span><span class="line"><span class="cl">            (* a (square x))
</span></span><span class="line"><span class="cl">            (* b x)
</span></span><span class="line"><span class="cl">            c
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cube x)
</span></span><span class="line"><span class="cl">    (* x x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.41.</strong>  Define a procedure <code>double</code> that takes a procedure of one argument as argument and returns a procedure that applies the original procedure twice. For example, if <code>inc</code> is a procedure that adds $1$ to its argument, then <code>(double inc)</code> should be a procedure that adds $2$. What value is returned by</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(((double (double double)) inc) 5)
</span></span></code></pre></div><p><strong>Answer 1.41.</strong></p>
<p>We guess the procedure <code>double</code> is:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (double f)
</span></span><span class="line"><span class="cl">	(lambda (x) (f (f x)))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p>Then:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (((double (double double)) inc) 5) 
</span></span><span class="line"><span class="cl">=&gt; (((double (lambda (x) (double (double x)))) inc) 5) 
</span></span><span class="line"><span class="cl">=&gt; ((double (double (double (double inc)))) 5)
</span></span></code></pre></div><p>Since there are 4 <code>double</code> procedures, <code>call</code> procedure is invoked $2^4 = 16$ times. Thus, result is $5 + 16 = 21$</p>
<p><strong>Exercise 1.42.</strong>  Let $f$ and $g$ be two one-argument functions. The composition $f$ after $g$ is defined to be the function $x \mapsto  f(g(x))$. Define a procedure <code>compose</code> that implements composition. For example, if inc is a procedure that adds $1$ to its argument,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">((compose square inc) 6)
</span></span><span class="line"><span class="cl">49
</span></span></code></pre></div><p><strong>Answer 1.42.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.43.</strong>  If $f$ is a numerical function and $n$ is a positive integer, then we can form the $n$th repeated application of $f$, which is defined to be the function whose value at $x$ is $f(f(…(f(x))…))$. For example, if $f$ is the function $x \mapsto  x + 1$, then the $n$th repeated application of $f$ is the function $x \mapsto  x + n$. If $f$ is the operation of squaring a number, then the $n$th repeated application of $f$ is the function that raises its argument to the $2^n$th power. Write a procedure that takes as inputs a procedure that computes $f$ and a positive integer $n$ and returns the procedure that computes the $n$th repeated application of $f$. Your procedure should be able to be used as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">((repeated square 2) 5)
</span></span><span class="line"><span class="cl">625
</span></span></code></pre></div><p>Hint: You may find it convenient to use <code>compose</code> from exercise 1.42.</p>
<p><strong>Answer 1.43.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (repeated f n)
</span></span><span class="line"><span class="cl">   (if (&lt; n 1)
</span></span><span class="line"><span class="cl">        (lambda(x) x)
</span></span><span class="line"><span class="cl">        (compose f (repeated f (- n 1)))
</span></span><span class="line"><span class="cl">   ) 
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.44.</strong>  The idea of <em>smoothing</em> a function is an important concept in signal processing. If $f$ is a function and $dx$ is some small number, then the smoothed version of $f$ is the function whose value at a point $x$ is the average of $f(x - dx)$, $f(x)$, and $f(x + dx)$. Write a procedure smooth that takes as input a procedure that computes $f$ and returns a procedure that computes the smoothed $f$. It is sometimes valuable to repeatedly smooth a function (that is, smooth the smoothed function, and so on) to obtained the <em>$n$-fold smoothed function</em>. Show how to generate the $n$-fold smoothed function of any given function using $smooth$ and $repeated$ from exercise 1.43.</p>
<p><strong>Answer 1.44.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (repeated f n)
</span></span><span class="line"><span class="cl">   (if (&lt; n 1)
</span></span><span class="line"><span class="cl">        (lambda(x) x)
</span></span><span class="line"><span class="cl">        (compose f (repeated f (- n 1)))
</span></span><span class="line"><span class="cl">   ) 
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (smooth f)
</span></span><span class="line"><span class="cl">    (lambda (x)
</span></span><span class="line"><span class="cl">        (/ (+
</span></span><span class="line"><span class="cl">                (f (- x dx))
</span></span><span class="line"><span class="cl">                (f x)
</span></span><span class="line"><span class="cl">                (f (+ x dx))
</span></span><span class="line"><span class="cl">           )
</span></span><span class="line"><span class="cl">           3 
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (n-fold-smooth f n)
</span></span><span class="line"><span class="cl">    ((repeated smooth n) f)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.45.</strong>  We saw in section 1.3.3 that attempting to compute square roots by naively finding a fixed point of $y \mapsto x/y$ does not converge, and that this can be fixed by average damping. The same method works for finding cube roots as fixed points of the average-damped $y \mapsto x/y^2$. Unfortunately, the process does not work for fourth roots – a single average damp is not enough to make a fixed-point search for $y \mapsto x/y^3$ converge. On the other hand, if we average damp twice (i.e., use the average damp of the average damp of $y \mapsto  x/y^3$) the fixed-point search does converge. Do some experiments to determine how many average damps are required to compute $n$th roots as a fixed-point search based upon repeated average damping of $y \mapsto x/y^{n-1}$. Use this to implement a simple procedure for computing nth roots using <code>fixed-point</code>, <code>average-damp</code>, and the <code>repeated</code> procedure of exercise 1.43. Assume that any arithmetic operations you need are available as primitives.</p>
<p><strong>Answer 1.45.</strong> Here reference <a href="http://www.billthelizard.com/2010/08/sicp-145-computing-nth-roots.html">SICP 1.45: Computing nth roots</a></p>
<p>To fix the problem, we need to increase the number of times invoking <code>average-damp</code>. And we find out the number of average damps, $a$, we can say:</p>
<p>$$
n_{\text{max}} = 2^{a+1} - 1 \
a =  \lfloor \log _2{n} \rfloor
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (nth-root x n)
</span></span><span class="line"><span class="cl">    (fixed-point
</span></span><span class="line"><span class="cl">        ((repeated average-damp (floor (/ (log x) (log 2))))
</span></span><span class="line"><span class="cl">            (lambda (y) (/ x (expt y (- n 1))))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        1.0
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (repeated f n)
</span></span><span class="line"><span class="cl">   (if (&lt; n 1)
</span></span><span class="line"><span class="cl">        (lambda(x) x)
</span></span><span class="line"><span class="cl">        (compose f (repeated f (- n 1)))
</span></span><span class="line"><span class="cl">   ) 
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define tolerance 0.00001)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fixed-point f first-guess)
</span></span><span class="line"><span class="cl">    (define (close-enough? v1 v2)
</span></span><span class="line"><span class="cl">        (&lt; (abs (- v1 v2)) tolerance)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (try guess)
</span></span><span class="line"><span class="cl">        (let ((next (f guess)))
</span></span><span class="line"><span class="cl">            (if (close-enough? guess next)
</span></span><span class="line"><span class="cl">                next
</span></span><span class="line"><span class="cl">                (try next)
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (try first-guess)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (average-damp f)
</span></span><span class="line"><span class="cl">    (define (average x y)
</span></span><span class="line"><span class="cl">        (/ (+ x y) 2)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (lambda (x) (average x (f x)))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (expt b n)
</span></span><span class="line"><span class="cl">    (define (even? n) (= (remainder n 2) 0))
</span></span><span class="line"><span class="cl">    (define (square x) (* x x))
</span></span><span class="line"><span class="cl">    (cond 
</span></span><span class="line"><span class="cl">        ((= n 0) 1)
</span></span><span class="line"><span class="cl">        ((even? n) (square (expt b (/ n 2))))
</span></span><span class="line"><span class="cl">        (else (* b (expt b (- n 1))))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.46.</strong>  Several of the numerical methods described in this chapter are instances of an extremely general computational strategy known as <em>iterative improvement</em>. Iterative improvement says that, to compute something, we start with an initial guess for the answer, test if the guess is good enough, and otherwise improve the guess and continue the process using the improved guess as the new guess. Write a procedure <code>iterative-improve</code> that takes two procedures as arguments: a method for telling whether a guess is good enough and a method for improving a guess. <code>Iterative-improve</code> should return as its value a procedure that takes a guess as argument and keeps improving the guess until it is good enough. Rewrite the sqrt procedure of section 1.1.7 and the <code>fixed-point</code> procedure of section 1.3.3 in terms of <code>iterative-improve</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (close-enough? v1 v2) 
</span></span><span class="line"><span class="cl">   (define tolerance 1.e-6) 
</span></span><span class="line"><span class="cl">   (&lt; (/ (abs (- v1 v2)) v2)  tolerance)) 
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">(define (iterative-improve improve close-enough?) 
</span></span><span class="line"><span class="cl">   (lambda (x) 
</span></span><span class="line"><span class="cl">     (let ((xim (improve x))) 
</span></span><span class="line"><span class="cl">       (if (close-enough? x xim) 
</span></span><span class="line"><span class="cl">           xim 
</span></span><span class="line"><span class="cl">         ((iterative-improve improve close-enough?) xim)) 
</span></span><span class="line"><span class="cl">       ))) 
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">(define (sqrt x) 
</span></span><span class="line"><span class="cl">   ((iterative-improve   
</span></span><span class="line"><span class="cl">     (lambda (y) 
</span></span><span class="line"><span class="cl">       (/ (+ (/ x y) y) 2)) 
</span></span><span class="line"><span class="cl">     close-enough?) 1.0))
</span></span></code></pre></div>]]></description></item><item><title>Building Abstractions with Procedures Section 2 - Part 2</title><link>https://blog.terryx.com/posts/sicp-1-2-2/</link><pubDate>Tue, 20 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-1-2-2/</guid><description><![CDATA[<h2 id="section-12-procedures-and-the-processes-they-generate">Section 1.2 Procedures and the Processes They Generate</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 1.20.</strong>  The process that a procedure generates is of course dependent on the rules used by the interpreter. As an example, consider the iterative <code>gcd</code> procedure given above. Suppose we were to interpret this procedure using normal-order evaluation, as discussed in section 1.1.5. (The normal-order-evaluation rule for if is described in exercise 1.5.) Using the substitution method (for normal order), illustrate the process generated in evaluating <code>(gcd 206 40)</code> and indicate the <code>remainder</code> operations that are actually performed. How many <code>remainder</code> operations are actually performed in the normal-order evaluation of <code>(gcd 206 40)</code>? In the applicative-order evaluation?</p>
<p><strong>Answer 1.20.</strong></p>
<p><em>Normal-order evaluation</em>: fully expand and then reduce. 18 total <code>remainder</code>.</p>
<p><em>Applicative-order evaluation</em>: evaluate arguments and then apply operands. 4 total <code>remainder</code>.</p>
<p><strong>Exercise 1.21.</strong>  Use the smallest-divisor procedure to find the smallest divisor of each of the following numbers: $199$, $1999$, $19999$.</p>
<p><strong>Answer 1.21.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (smallest-divisor n)
</span></span><span class="line"><span class="cl">    (find-divisor n 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (find-divisor n test-divisor)
</span></span><span class="line"><span class="cl">    (cond ((&gt; (square test-divisor) n) n)
</span></span><span class="line"><span class="cl">          ((divides? test-divisor n) test-divisor)
</span></span><span class="line"><span class="cl">          (else (find-divisor n (+ test-divisor 1)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (divides? a b)
</span></span><span class="line"><span class="cl">    (= (remainder b a) 0)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(smallest-divisor 199) =&gt; 199
</span></span><span class="line"><span class="cl">(smallest-divisor 1999) =&gt; 1999
</span></span><span class="line"><span class="cl">(smallest-divisor 19999) =&gt; 7
</span></span></code></pre></div><p><strong>Exercise 1.22.</strong>  Most Lisp implementations include a primitive called <code>runtime</code> that returns an integer that specifies the amount of time the system has been running (measured, for example, in microseconds). The following <code>timed-prime-test</code> procedure, when called with an integer $n$, prints $n$ and checks to see if $n$ is prime. If $n$ is prime, the procedure prints three asterisks followed by the amount of time used in performing the test.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (timed-prime-test n)
</span></span><span class="line"><span class="cl">  (newline)
</span></span><span class="line"><span class="cl">  (display n)
</span></span><span class="line"><span class="cl">  (start-prime-test n (runtime)))
</span></span><span class="line"><span class="cl">(define (start-prime-test n start-time)
</span></span><span class="line"><span class="cl">  (if (prime? n)
</span></span><span class="line"><span class="cl">      (report-prime (- (runtime) start-time))))
</span></span><span class="line"><span class="cl">(define (report-prime elapsed-time)
</span></span><span class="line"><span class="cl">  (display &#34; *** &#34;)
</span></span><span class="line"><span class="cl">  (display elapsed-time))
</span></span></code></pre></div><p>Using this procedure, write a procedure <code>search-for-primes</code> that checks the primality of consecutive odd integers in a specified range. Use your procedure to find the three smallest primes larger than $1000$; larger than $10,000$; larger than $100,000$; larger than $1,000,000$. Note the time needed to test each prime. Since the testing algorithm has order of growth of $\theta(\sqrt n)$, you should expect that testing for primes around $10,000$ should take about $\sqrt{10}$ times as long as testing for primes around $1000$. Do your timing data bear this out? How well do the data for $100,000$ and $1,000,000$ support the $\sqrt n$ prediction? Is your result compatible with the notion that programs on your machine run in time proportional to the number of steps required for the computation?</p>
<p><strong>Answer 1.22.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define runtime real-time-clock)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (timed-prime-test n)
</span></span><span class="line"><span class="cl">  (newline)
</span></span><span class="line"><span class="cl">  (display n)
</span></span><span class="line"><span class="cl">  (start-prime-test n (runtime)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (start-prime-test n start-time)
</span></span><span class="line"><span class="cl">  (if (prime? n)
</span></span><span class="line"><span class="cl">      (report-prime (- (runtime) start-time))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (report-prime elapsed-time)
</span></span><span class="line"><span class="cl">  (display &#34; *** &#34;)
</span></span><span class="line"><span class="cl">  (display elapsed-time))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (find-divisor n test-divisor)
</span></span><span class="line"><span class="cl">	(cond 
</span></span><span class="line"><span class="cl">		((&gt; (square test-divisor) n) n)
</span></span><span class="line"><span class="cl">		((divides? test-divisor n) test-divisor)
</span></span><span class="line"><span class="cl">		(else (find-divisor n (+ test-divisor 1)))
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">	(* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (divides? a b)
</span></span><span class="line"><span class="cl">	(= (remainder b a) 0)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (smallest-divisor n)
</span></span><span class="line"><span class="cl">	(find-divisor n 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">	(= n (smallest-divisor n))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (search-for-primes start end)
</span></span><span class="line"><span class="cl">	(if (even? start)
</span></span><span class="line"><span class="cl">		(search-for-primes (+ start 1) end)
</span></span><span class="line"><span class="cl">		(cond 
</span></span><span class="line"><span class="cl">			((&lt; start end) (timed-prime-test start)
</span></span><span class="line"><span class="cl">			(search-for-primes (+ start 2) end))
</span></span><span class="line"><span class="cl">		)
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(search-for-primes 1000000 1000100)
</span></span></code></pre></div><p><strong>Exercise 1.23.</strong>  The <code>smallest-divisor</code> procedure shown at the start of this section does lots of needless testing: After it checks to see if the number is divisible by $2$ there is no point in checking to see if it is divisible by any larger even numbers. This suggests that the values used <code>for test-divisor</code> should not be $2, 3, 4, 5, 6, …$, but rather $2, 3, 5, 7, 9, …$. To implement this change, define a procedure next that returns $3$ if its input is equal to $2$ and otherwise returns its input plus $2$. Modify the <code>smallest-divisor</code> procedure to use <code>(next test-divisor)</code> instead of <code>(+ test-divisor 1)</code>. With <code>timed-prime-test</code> incorporating this modified version of <code>smallest-divisor</code>, run the test for each of the $12$ primes found in exercise 1.22. Since this modification halves the number of test steps, you should expect it to run about twice as fast. Is this expectation confirmed? If not, what is the observed ratio of the speeds of the two algorithms, and how do you explain the fact that it is different from $2$?</p>
<p><strong>Answer 1.23.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (find-divisor n test-divisor)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((&gt; (square test-divisor) n) n)
</span></span><span class="line"><span class="cl">        ((divides? test-divisor n) test-divisor)
</span></span><span class="line"><span class="cl">        (else (find-divisor n (next test-divisor)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (next test-divisor)
</span></span><span class="line"><span class="cl">    (if (= test-divisor 2) (+ test-divisor 1)
</span></span><span class="line"><span class="cl">                           (+ test-divisor 2)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (divides? a b)
</span></span><span class="line"><span class="cl">    (= (remainder b a) 0)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (smallest-divisor n)
</span></span><span class="line"><span class="cl">    (find-divisor n 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (= (smallest-divisor n) n)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.24.</strong>  Modify the timed-prime-test procedure of exercise 1.22 to use <code>fast-prime?</code> (the Fermat method), and test each of the $12$ primes you found in that exercise. Since the Fermat test has  $\theta (\log n)$ growth, how would you expect the time to test primes near $1,000,000$ to compare with the time needed to test primes near 1000? Do your data bear this out? Can you explain any discrepancy you find?</p>
<p><strong>Answer 1.24.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">    (cond 
</span></span><span class="line"><span class="cl">        ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp) (remainder (square (expmod base (/ exp 2) m)) m))
</span></span><span class="line"><span class="cl">        (else (remainder (* base (expmod base (- exp 1) m)) m))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fermat-test n)
</span></span><span class="line"><span class="cl">    (define (try-it a)
</span></span><span class="line"><span class="cl">        (= (expmod a n n) a)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (try-it (+ 1 (random (- n 1))))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-prime? n times)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= times 0) true)
</span></span><span class="line"><span class="cl">        ((fermat-test n) (fast-prime? n (- times 1)))
</span></span><span class="line"><span class="cl">        (else false)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (fast-prime? n 100 )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.25.</strong>  Alyssa P. Hacker complains that we went to a lot of extra work in writing <code>expmod</code>. After all, she says, since we already know how to compute exponentials, we could have simply written</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">  (remainder (fast-expt base exp) m))
</span></span></code></pre></div><p>Is she correct? Would this procedure serve as well for our fast prime tester? Explain.</p>
<p><strong>Answer 1.25.</strong>  Scheme is able to handle arbitrary-precision arithmetic, but arithmetic with arbitrarily long numbers is computationally expensive. This means that we get the correct results, but it takes considerably longer.</p>
<p><strong>Exercise 1.26.</strong>  Louis Reasoner is having great difficulty doing exercise 1.24. His <code>fast-prime?</code> test seems to run more slowly than his <code>prime?</code> test. Louis calls his friend Eva Lu Ator over to help. When they examine Louis’s code, they find that he has rewritten the <code>expmod</code> procedure to use an explicit multiplication, rather than calling square:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">  (cond ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp)
</span></span><span class="line"><span class="cl">         (remainder (* (expmod base (/ exp 2) m)
</span></span><span class="line"><span class="cl">                       (expmod base (/ exp 2) m))
</span></span><span class="line"><span class="cl">                    m))
</span></span><span class="line"><span class="cl">        (else
</span></span><span class="line"><span class="cl">         (remainder (* base (expmod base (- exp 1) m))
</span></span><span class="line"><span class="cl">                    m))))
</span></span></code></pre></div><p>“I don’t see what difference that could make,” says Louis. “I do.” says Eva. “By writing the procedure like that, you have transformed the $\theta (\log n)$ process into a $\theta (n)$ process.’’ Explain.</p>
<p><strong>Answer 1.26.</strong> Let $n$ is exponent which can generate a complete binary tree recursion. The depth of the tree is $\log n + 1$, the total number of nodes is $2^{\log n + 1} - 1$, is $2n -1 = \theta (n)$.</p>
<p><strong>Exercise 1.27.</strong>  Demonstrate that the Carmichael numbers listed in footnote 47 really do fool the Fermat test. That is, write a procedure that takes an integer $n$ and tests whether $a^n$ is congruent to $a$ modulo $n$ for every $a &lt; n$, and try your procedure on the given Carmichael numbers.</p>
<p><strong>Answer 1.27.</strong> Carmichael numbers fools Fermat test.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">    (cond 
</span></span><span class="line"><span class="cl">        ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp) (remainder (square (expmod base (/ exp 2) m)) m))
</span></span><span class="line"><span class="cl">        (else (remainder (* base (expmod base (- exp 1) m)) m))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fermat-test n test-value)
</span></span><span class="line"><span class="cl">    (define (try-it a)
</span></span><span class="line"><span class="cl">        (= (expmod a n n) a)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (try-it test-value)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-prime? n times)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= times 0) true)
</span></span><span class="line"><span class="cl">        ((fermat-test n times) (fast-prime? n (- times 1)))
</span></span><span class="line"><span class="cl">        (else false)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (fast-prime? n (- n 1))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(prime? 561)
</span></span><span class="line"><span class="cl">(prime? 1105)
</span></span><span class="line"><span class="cl">(prime? 1729)
</span></span><span class="line"><span class="cl">(prime? 2465)
</span></span></code></pre></div><p><strong>Exercise 1.28.</strong>  One variant of the Fermat test that cannot be fooled is called the <em>Miller-Rabin test</em> (Miller 1976; Rabin 1980). This starts from an alternate form of Fermat’s Little Theorem, which states that if $n$ is a prime number and $a$ is any positive integer less than $n$, then $a$ raised to the $(n - 1)$st power is congruent to $1$ modulo $n$. To test the primality of a number $n$ by the Miller-Rabin test, we pick a random number $a&lt;n$ and raise $a$ to the $(n - 1)$st power modulo $n$ using the <code>expmod</code> procedure. However, whenever we perform the squaring step in <code>expmod</code>, we check to see if we have discovered a “nontrivial square root of $1$ modulo $n$,” that is, a number not equal to $1$ or $n - 1$ whose square is equal to $1$ modulo $n$. It is possible to prove that if such a nontrivial square root of $1$ exists, then $n$ is not prime. It is also possible to prove that if $n$ is an odd number that is not prime, then, for at least half the numbers $a&lt;n$, computing $a^{n-1}$ in this way will reveal a nontrivial square root of $1$ modulo $n$. (This is why the Miller-Rabin test cannot be fooled.) Modify the <code>expmod</code> procedure to signal if it discovers a nontrivial square root of $1$, and use this to implement the Miller-Rabin test with a procedure analogous to <code>fermat-test</code>. Check your procedure by testing various known primes and non-primes. Hint: One convenient way to make <code>expmod</code> signal is to have it return $0$.</p>
<p><strong>Answer 1.28.</strong> I got stuck in the exercise for hours. After reading other resources about Miller-Rabin test, I find out we don’t worry about the proof that “if such a nontrivial square root of $1$ exists, then $n$ is not prime”. Just know about the condition apply to the procedure.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp)
</span></span><span class="line"><span class="cl">            (let ((x (expmod base (/ exp 2) m)))
</span></span><span class="line"><span class="cl">                (if (non-trivial-sqrt? x m) 0 (remainder (square x) m))
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        (else (remainder (* base (expmod base (- exp 1) m)) m))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (non-trivial-sqrt? n m)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= n 1) false)
</span></span><span class="line"><span class="cl">        ((= n (- m 1)) false)
</span></span><span class="line"><span class="cl">        (else (= (remainder (square n) m) 1))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (miller-rabin-test a n)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= a 0) true)
</span></span><span class="line"><span class="cl">        ((= (expmod a (- n 1) n ) 1) (miller-rabin-test (- a 1) n))
</span></span><span class="line"><span class="cl">        (else false)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (miller-rabin-test (- n 1) n)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(prime? 561)
</span></span><span class="line"><span class="cl">(prime? 1105)
</span></span><span class="line"><span class="cl">(prime? 1729)
</span></span><span class="line"><span class="cl">(prime? 2465)
</span></span></code></pre></div>]]></description></item><item><title>Building Abstractions with Procedures Section 2 - Part 1</title><link>https://blog.terryx.com/posts/scip-1-2/</link><pubDate>Fri, 16 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/scip-1-2/</guid><description><![CDATA[<h2 id="section-12-procedures-and-the-processes-they-generate">Section 1.2 Procedures and the Processes They Generate</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 1.9.</strong> Each of the following two procedures defines a method for adding two positive integers in terms of the procedures <code>inc</code>, which increments its argument by 1, and dec, which decrements its argument by 1.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (+ a b)
</span></span><span class="line"><span class="cl">  (if (= a 0)
</span></span><span class="line"><span class="cl">      b
</span></span><span class="line"><span class="cl">      (inc (+ (dec a) b))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (+ a b)
</span></span><span class="line"><span class="cl">  (if (= a 0)
</span></span><span class="line"><span class="cl">      b
</span></span><span class="line"><span class="cl">      (+ (dec a) (inc b))))
</span></span></code></pre></div><p>Using the substitution model, illustrate the process generated by each procedure in evaluating <code>(+ 4 5)</code>. Are these processes iterative or recursive?</p>
<p><strong>Answer 1.9.</strong></p>
<p>For the first process, it is recursive:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (+ 4 5)
</span></span><span class="line"><span class="cl">=&gt; (+ 1 ( + 3 5))
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (+ 2 5)))
</span></span><span class="line"><span class="cl">=&gt; ...
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (+ 1 (+ 1 (5)))))
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (+ 1 (6))))
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (7)))
</span></span><span class="line"><span class="cl">=&gt; ...
</span></span><span class="line"><span class="cl">=&gt; 9
</span></span></code></pre></div><p>For the second process, it is iterative:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (+ 4 5)
</span></span><span class="line"><span class="cl">=&gt; (+ 3 6)
</span></span><span class="line"><span class="cl">=&gt; (+ 2 7)
</span></span><span class="line"><span class="cl">=&gt; ...
</span></span><span class="line"><span class="cl">=&gt; (+ 0 8)
</span></span><span class="line"><span class="cl">=&gt; 8
</span></span></code></pre></div><p><strong>Exercise 1.10.</strong>  The following procedure computes a mathematical function called Ackermann’s function.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (A x y)
</span></span><span class="line"><span class="cl">  (cond ((= y 0) 0)
</span></span><span class="line"><span class="cl">        ((= x 0) (* 2 y))
</span></span><span class="line"><span class="cl">        ((= y 1) 2)
</span></span><span class="line"><span class="cl">        (else (A (- x 1)
</span></span><span class="line"><span class="cl">                 (A x (- y 1))))))
</span></span></code></pre></div><p>What are the values of the following expressions?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(A 1 10)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(A 2 4)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(A 3 3)
</span></span></code></pre></div><p>Consider the following procedures, where A is the procedure defined above:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (f n) (A 0 n))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (g n) (A 1 n))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (h n) (A 2 n))
</span></span></code></pre></div><p>Give concise mathematical definitions for the functions computed by the procedures <em>f</em>, <em>g</em>, and <em>h</em> for positive integer values of <em>n</em>.</p>
<p><strong>Answer 1.10.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(A 1 10) = 2^10 = 1024
</span></span><span class="line"><span class="cl">(A 2 4) = 65536
</span></span><span class="line"><span class="cl">(A 3 3) = 65536
</span></span></code></pre></div><p>$$
A(0,n)=f(n)=2n
$$</p>
<p>$$
A(1,n)=g(n)=2^n
$$</p>
<p>$$
A(2,n)=h(n) = \overbrace{(2^{(2^{(2^{…})})})}^{n ~times}
$$</p>
<p><strong>Exercise 1.11.</strong>  A function <code>f</code> is defined by the rule that <code>f(n) = n if n&lt;3 and f(n) = f(n-1) + 2f(n-2) + 3f(n-3) if n&gt;3</code>. Write a procedure that computes <code>f</code> by means of a recursive process. Write a procedure that computes <code>f</code> by means of an iterative process.</p>
<p><strong>Answer 1.11.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (fun-recursive n)
</span></span><span class="line"><span class="cl">  (if (&lt; n 3)
</span></span><span class="line"><span class="cl">  n
</span></span><span class="line"><span class="cl">  (+ (fun-recursive (- n 1))
</span></span><span class="line"><span class="cl">     (* 2 (fun-recursive (- n 2)))
</span></span><span class="line"><span class="cl">     (* 3 (fun-recursive (- n 3)))
</span></span><span class="line"><span class="cl">     )) 
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fun-iter n a b cnt)
</span></span><span class="line"><span class="cl">     (if (= cnt 0)
</span></span><span class="line"><span class="cl">            n
</span></span><span class="line"><span class="cl">            (fun-iter (+ n (* 2 a) (* 3 b)) n a (- cnt 1))
</span></span><span class="line"><span class="cl">     )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fun-iterative n)
</span></span><span class="line"><span class="cl">    (fun-iter 2 1 0 (- n 2))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.12.</strong> The following pattern of numbers is called Pascal’s triangle.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">				1
</span></span><span class="line"><span class="cl">			1		1
</span></span><span class="line"><span class="cl">		1		2		1
</span></span><span class="line"><span class="cl">	1		3		3		1
</span></span><span class="line"><span class="cl">1		4		6		4		1
</span></span><span class="line"><span class="cl">			   ...
</span></span></code></pre></div><p>The numbers at the edge of the triangle are all 1, and each number inside the triangle is the sum of the two numbers above it. Write a procedure that computes elements of Pascal’s triangle by means of a recursive process.</p>
<p><strong>Answer 1.12.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (pascal-triangle m n)
</span></span><span class="line"><span class="cl">    (if (or (= n 1) (= n m))
</span></span><span class="line"><span class="cl">        1
</span></span><span class="line"><span class="cl">        (+ (pascal-triangle (- m 1) (- n 1)) 
</span></span><span class="line"><span class="cl">           (pascal-triangle (- m 1) n))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.13.</strong>  Prove that Fib(n) is the closest integer to $\frac{\phi^{n}}{\sqrt{5}}$, where $\phi=\frac{1 + \sqrt{5}}{2}$.</p>
<p><strong>Answer 1.13.</strong></p>
<p><strong>Theorem 1</strong></p>
<p>$$
Fib(n)=\frac{\phi^n-\psi^n}{\sqrt{5}},\phi=\frac{1+\sqrt{5}}{2}, \psi=\frac{1-\sqrt{5}}{2}
$$</p>
<p><strong>Base Case</strong></p>
<p>$$
Fib(0)=0, Fib(1)=1
$$</p>
<p><strong>Induction Step</strong></p>
<p>\begin{align}
Fib(n-1)+Fib(n-2)&amp;=\frac{(\phi^{n-1}-\psi^{n-1})+(\phi^{n-2}-\psi^{n-2})}{\sqrt{5}}\
&amp;=\frac{(\phi^{n-1}+\phi^{n-2})-(\psi^{n-1}+\psi^{n-2})}{\sqrt{5}}\end{align}</p>
<p>Meanwhile,</p>
<p>\begin{align}
\phi+1=\frac{3+\sqrt{5}}{2}=\frac{6+2\sqrt{5}}{4}=(\frac{1+\sqrt{5}}{2})^2=\phi^2\
\psi+1=\frac{3-\sqrt{5}}{2}=\frac{6-2\sqrt{5}}{4}=(\frac{1-\sqrt{5}}{2})^2=\psi^2
\end{align}</p>
<p>Thus,</p>
<p>\begin{align}
Fib(n-1)+Fib(n-2)&amp;=\frac{\phi^{n-2}(\phi+1)-\psi^{n-2}(\psi+1)}{\sqrt{5}}\
&amp;=\frac{\phi^n-\psi^n}{\sqrt{5}}=Fib(n)
\end{align}</p>
<p><strong>Theorem 2</strong></p>
<p>\begin{align}
\frac{\psi^n}{\sqrt{5}} &lt; \frac{1}{2}
\end{align}</p>
<p><strong>Proof</strong></p>
<p>\begin{align}
\frac{\psi^0}{\sqrt{5}}&amp;\sim0.4472, \frac{\psi^1}{\sqrt{5}}\sim0.2764,…\
\frac{\psi^n}{\sqrt{5}}&amp;&lt;\frac{1}{2}
\end{align}</p>
<p>Therefore,</p>
<p>\begin{align}
Fib(n) &amp;= \frac{\phi^n-\psi^n}{\sqrt{5}} = \left[\frac{\phi^n-\psi^n}{\sqrt{5}}\right]\
&amp;=\left[\frac{\phi^n}{\sqrt{5}}\right]
\end{align}</p>
<p>Q.E.D.</p>
<p><strong>Exercise 1.14.</strong>  Draw the tree illustrating the process generated by the <code>count-change</code> procedure of section 1.2.2 in making change for 11 cents. What are the orders of growth of the space and number of steps used by this process as the amount to be changed increases?</p>
<p><strong>Answer 1.14.</strong></p>
<p><img src="/images/20161217/tree-figure.png" alt=""  loading="lazy">
</p>
<p>Let the number of kinds of coins: $k$;
Amount of money: $n$;
Denominations: $d_1, d_2, …, d_k$.</p>
<p><strong>Orders of growth of the space</strong></p>
<p>The space required is proportional to the maximum depth of the tree.
Clearly, this means the maximum height is going to be linear in the amount $n$, or $\theta(n)$.</p>
<p><strong>Number of steps</strong></p>
<p><em>Basic case</em></p>
<p><img src="/images/20161217/tree-a.png" alt=""  loading="lazy">
</p>
<p>Let see the recursive tree of <code>(cc n 1)</code>, which number of steps is defined as $T(n,1)$. Clearly, we can calculate that $T(n,1)=2n+1=\theta(n)$.</p>
<p><em>Induction step</em></p>
<p><img src="/images/20161217/tree-b.png" alt=""  loading="lazy">
</p>
<p>Next, we look at the recursive tree of <code>(cc n k)</code>. We have:</p>
<p>$$
T(n,k)=\lfloor \frac{n}{d_k} \rfloor (T(n,k-1)+1)+2
$$</p>
<p>We can expand it further:</p>
<p>\begin{align}
T(n,k)&amp;=\lfloor \frac{n}{d_k} \rfloor (T(n,k-1)+1)+2 \
&amp;=\lfloor \frac{n}{d_k} \rfloor ((\lfloor \frac{n}{d_k} \rfloor T(n,k-2)+1)+2+1)+2 \
&amp;= \lfloor \frac{n}{d_k} \rfloor (… (\lfloor \frac{n}{d_k} \rfloor T(n,1)+1)+2 … +1)+2 \
&amp;= \theta(n^k)
\end{align}</p>
<p>Thus, we have $T(n,5) = \theta(n^5)$.</p>
<p><strong>Exercise 1.15.</strong> The sine of an angle (specified in radians) can be computed by making use of the approximation $sin x \approx x$ if $x$ is sufficiently small, and the trigonometric identity</p>
<p>$$
\sin x = 3 \sin \frac{x}{3} - 4 \sin^3 \frac{x}{3}
$$</p>
<p>to reduce the size of the argument of sin. (For purposes of this exercise an angle is considered “sufficiently small” if its magnitude is not greater than 0.1 radians.) These ideas are incorporated in the following procedures:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cube x) (* x x x))
</span></span><span class="line"><span class="cl">(define (p x) (- (* 3 x) (* 4 (cube x))))
</span></span><span class="line"><span class="cl">(define (sine angle)
</span></span><span class="line"><span class="cl">   (if (not (&gt; (abs angle) 0.1))
</span></span><span class="line"><span class="cl">       angle
</span></span><span class="line"><span class="cl">       (p (sine (/ angle 3.0)))))
</span></span></code></pre></div><p>a.  How many times is the procedure <code>p</code> applied when (sine 12.15) is evaluated?</p>
<p>b.  What is the order of growth in space and number of steps (as a function of $a$) used by the process generated by the sine procedure when <code>(sine a)</code> is evaluated?</p>
<p><strong>Answer 1.15.</strong></p>
<p>a. $\lceil \log_3 \frac{12.15}{0.1} \rceil = 5$.</p>
<p>b. The order of growth in space and number of steps are $\theta(\log n)$.</p>
<p><strong>Exercise 1.16.</strong>  Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does <code>fast-expt</code>. (Hint: Using the observation that $(b^{n/2})^2 = (b^2)^{n/2}$, keep, along with the exponent $n$ and the base $b$, an additional state variable $a$, and define the state transformation in such a way that the product $ab^n$ is unchanged from state to state. At the beginning of the process $a$ is taken to be $1$, and the answer is given by the value of $a$ at the end of the process. In general, the technique of defining an invariant quantity that remains unchanged from state to state is a powerful way to think about the design of iterative algorithms.)</p>
<p><strong>Answer 1.16.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (expt-iter b n a)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= n 0) a)
</span></span><span class="line"><span class="cl">        ((even? n) (expt-iter (square b) (/ n 2) a))
</span></span><span class="line"><span class="cl">        (else (expt-iter b (- n 1) (* a b)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-expt a n)
</span></span><span class="line"><span class="cl">    (expt-iter a n 1)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.17.</strong>  The exponentiation algorithms in this section are based on performing exponentiation by means of repeated multiplication. In a similar way, one can perform integer multiplication by means of repeated addition. The following multiplication procedure (in which it is assumed that our language can only add, not multiply) is analogous to the <code>expt</code> procedure:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (* a b)
</span></span><span class="line"><span class="cl">  (if (= b 0)
</span></span><span class="line"><span class="cl">      0
</span></span><span class="line"><span class="cl">      (+ a (* a (- b 1)))))
</span></span></code></pre></div><p>This algorithm takes a number of steps that is linear in <code>b</code>. Now suppose we include, together with addition, operations <code>double</code>, which doubles an integer, and <code>halve</code>, which divides an (even) integer by $2$. Using these, design a multiplication procedure analogous to <code>fast-expt</code> that uses a logarithmic number of steps.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (double x)
</span></span><span class="line"><span class="cl">    (+ x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (halve x)
</span></span><span class="line"><span class="cl">    (/ x 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (mult-iter a b )
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= b 0) 0)
</span></span><span class="line"><span class="cl">        ((even? b) (mult-iter (double a) (halve b)))
</span></span><span class="line"><span class="cl">        (else (+ a (mult-iter a (- b 1) )))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-mult a b)
</span></span><span class="line"><span class="cl">    (mult-iter a b)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.18.</strong>  Using the results of exercises 1.16 and 1.17, devise a procedure that generates an iterative process for multiplying two integers in terms of adding, doubling, and halving and uses a logarithmic number of steps.</p>
<p><strong>Answer 1.18.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (double x)
</span></span><span class="line"><span class="cl">    (+ x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (halve x)
</span></span><span class="line"><span class="cl">    (/ x 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-mult a b)
</span></span><span class="line"><span class="cl">    (define (mult-iter a b acc)
</span></span><span class="line"><span class="cl">        (cond
</span></span><span class="line"><span class="cl">            ((= b 0) acc)
</span></span><span class="line"><span class="cl">            ((even? b) (mult-iter (double a) (halve b) acc))
</span></span><span class="line"><span class="cl">            (else (mult-iter a (- b 1) (+ acc a)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (mult-iter a b 0)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.19.</strong> There is a clever algorithm for computing the Fibonacci numbers in a logarithmic number of steps. Recall the transformation of the state variables $a$ and $b$ in the <code>fib-iter</code> process of section 1.2.2: $a \rightarrow  a + b$ and $b \rightarrow a$. Call this transformation $T$, and observe that applying $T$ over and over again $n$ times, starting with $1$ and $0$, produces the pair $Fib(n + 1)$ and $Fib(n)$. In other words, the Fibonacci numbers are produced by applying $T^n$, the $n$th power of the transformation $T$, starting with the pair $(1,0)$. Now consider $T$ to be the special case of $p = 0$ and $q = 1$ in a family of transformations $T_{pq}$, where $T_{pq}$ transforms the pair $(a,b)$ according to $a \leftarrow  bq + aq + ap$ and $b \leftarrow  bp + aq$. Show that if we apply such a transformation $T_{pq}$ twice, the effect is the same as using a single transformation $T_{p’q’}$ of the same form, and compute $p’$ and $q’$ in terms of $p$ and $q$. This gives us an explicit way to square these transformations, and thus we can compute $T^n$ using successive squaring, as in the <code>fast-expt</code> procedure. Put this all together to complete the following procedure, which runs in a logarithmic number of steps:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (fib n)
</span></span><span class="line"><span class="cl">  (fib-iter 1 0 0 1 n))
</span></span><span class="line"><span class="cl">(define (fib-iter a b p q count)
</span></span><span class="line"><span class="cl">  (cond ((= count 0) b)
</span></span><span class="line"><span class="cl">        ((even? count)
</span></span><span class="line"><span class="cl">         (fib-iter a
</span></span><span class="line"><span class="cl">                   b
</span></span><span class="line"><span class="cl">                   &lt;??&gt;      ; compute p&#39;
</span></span><span class="line"><span class="cl">                   &lt;??&gt;      ; compute q&#39;
</span></span><span class="line"><span class="cl">                   (/ count 2)))
</span></span><span class="line"><span class="cl">        (else (fib-iter (+ (* b q) (* a q) (* a p))
</span></span><span class="line"><span class="cl">                        (+ (* b p) (* a q))
</span></span><span class="line"><span class="cl">                        p
</span></span><span class="line"><span class="cl">                        q
</span></span><span class="line"><span class="cl">                        (- count 1)))))
</span></span></code></pre></div><p><strong>Answer 1.19.</strong></p>
<p>Define $a’$ and $b’$ by the definition of the transformation $T_{pq}$:</p>
<p>\begin{align}
a’ &amp;= qb + qa + pa = (p + q)a + qb \
b’ &amp;= qa + pb
\end{align}</p>
<p>Then, let $a’’$ and $b’’$ be the results of the transformation to $a’$ and $b’$ by applying the transformation once:</p>
<p>\begin{align}
a’’ &amp;= (p + q)a’ + qb’ = (p^2 + 2pq + 2q^2)a + (2pq + q^2)b \
b’’ &amp;= qa’ + pb’ = (2pq + q^2)a + (p^2 + q^2)b
\end{align}</p>
<p>Thus, we get the transformation to $p$ and $q$:</p>
<p>\begin{align}
p’ &amp;= p^2 + q^2 \
q’ &amp;= 2pq + q^2
\end{align}</p>
]]></description></item><item><title>Building Abstractions with Procedures Section 1</title><link>https://blog.terryx.com/posts/scip-1-1/</link><pubDate>Mon, 12 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/scip-1-1/</guid><description><![CDATA[<h2 id="section-11-the-elements-of-programing">Section 1.1 The Elements of Programing</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SICP</a>.</p>
<p><strong>Exercise 1.1.</strong> Below is a sequence of expressions. What is the result printed by the interpreter in response to each expression? Assume that the sequence is to be evaluated in the order in which it is presented.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">10
</span></span><span class="line"><span class="cl">(+ 5 3 4)
</span></span><span class="line"><span class="cl">(- 9 1)
</span></span><span class="line"><span class="cl">(/ 6 2)
</span></span><span class="line"><span class="cl">(+ (* 2 4) (- 4 6))
</span></span><span class="line"><span class="cl">(define a 3)
</span></span><span class="line"><span class="cl">(define b (+ a 1))
</span></span><span class="line"><span class="cl">(+ a b (* a b))
</span></span><span class="line"><span class="cl">(= a b)
</span></span><span class="line"><span class="cl">(if (and (&gt; b a) (&lt; b (* a b)))
</span></span><span class="line"><span class="cl">    b
</span></span><span class="line"><span class="cl">    a)
</span></span><span class="line"><span class="cl">(cond ((= a 4) 6)
</span></span><span class="line"><span class="cl">      ((= b 4) (+ 6 7 a))
</span></span><span class="line"><span class="cl">      (else 25))
</span></span><span class="line"><span class="cl">(+ 2 (if (&gt; b a) b a))
</span></span><span class="line"><span class="cl">(* (cond ((&gt; a b) a)
</span></span><span class="line"><span class="cl">         ((&lt; a b) b)
</span></span><span class="line"><span class="cl">         (else -1))
</span></span><span class="line"><span class="cl">   (+ a 1))
</span></span></code></pre></div><p><strong>Answer 1.1.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">10
</span></span><span class="line"><span class="cl">12
</span></span><span class="line"><span class="cl">8
</span></span><span class="line"><span class="cl">3
</span></span><span class="line"><span class="cl">6
</span></span><span class="line"><span class="cl">a
</span></span><span class="line"><span class="cl">b
</span></span><span class="line"><span class="cl">19
</span></span><span class="line"><span class="cl">#f
</span></span><span class="line"><span class="cl">4
</span></span><span class="line"><span class="cl">16
</span></span><span class="line"><span class="cl">6
</span></span><span class="line"><span class="cl">16
</span></span></code></pre></div><p><strong>Exercise 1.2.</strong> Translate the following expression into prefix form</p>
<p>$$
\frac{5+4+(2-(3-6 + \frac{4}{5}))}{3(6-2)(2-7)}
$$</p>
<p><strong>Answer 1.2.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 3))))) (* 3 (- 6 2) (- 2 7)))
</span></span></code></pre></div><p><strong>Exercise 1.3.</strong> Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.</p>
<p><strong>Answer 1.3.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(DEFINE (SOS x y) (+ (* x x) (* y y)))
</span></span><span class="line"><span class="cl">(DEFINE (F x y z)
</span></span><span class="line"><span class="cl">	(COND ((AND (&lt;= x y) (&lt;= x z)) (SOS y z))
</span></span><span class="line"><span class="cl">	      ((AND (&lt;= y x) (&lt;= y z)) (SOS x z))
</span></span><span class="line"><span class="cl">	      ((AND (&lt;= z x) (&lt;= z y)) (SOS x y))
</span></span><span class="line"><span class="cl">	)	
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.4.</strong> Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behavior of the following procedure:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (a-plus-abs-b a b)
</span></span><span class="line"><span class="cl">  ((if (&gt; b 0) + -) a b))
</span></span></code></pre></div><p><strong>Answer 1.4.</strong></p>
<p>$$
a+|b|
$$</p>
<p><em>a</em> plus the absolute value of <em>b</em>.</p>
<p><strong>Exercise 1.5.</strong> Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (p) (p))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (test x y)
</span></span><span class="line"><span class="cl">  (if (= x 0)
</span></span><span class="line"><span class="cl">      0
</span></span><span class="line"><span class="cl">      y))
</span></span></code></pre></div><p>Then he evaluates the expression:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(test 0 (p))
</span></span></code></pre></div><p>What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form <code>if</code> is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)</p>
<p><strong>Answer 1.5.</strong></p>
<p>The applicative-order evaluation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (test 0 (p))
</span></span><span class="line"><span class="cl">=&gt; (test 0 ((p)))
</span></span><span class="line"><span class="cl">=&gt; (test 0 (((p))))
</span></span></code></pre></div><p>As we see, the evaluation of <code>(test 0 (p))</code> is infinitive.</p>
<p>The normal-order evaluation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (test 0 (p))
</span></span><span class="line"><span class="cl">=&gt; (if (= 0 0) 0 (p))
</span></span><span class="line"><span class="cl">=&gt; (if #t 0 (p))
</span></span><span class="line"><span class="cl">=&gt; 0
</span></span></code></pre></div><p>The expression evaluates to <code>0</code>.</p>
<p><strong>Exercise 1.6.</strong>  Alyssa P. Hacker doesn’t see why if needs to be provided as a special form. “Why can’t I just define it as an ordinary procedure in terms of <code>cond</code>?” she asks. Alyssa’s friend Eva Lu Ator claims this can indeed be done, and she defines a new version of <code>if</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (new-if predicate then-clause else-clause)
</span></span><span class="line"><span class="cl">  (cond (predicate then-clause)
</span></span><span class="line"><span class="cl">        (else else-clause)))
</span></span></code></pre></div><p>Eva demonstrates the program for Alyssa:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(new-if (= 2 3) 0 5)
</span></span><span class="line"><span class="cl">5
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(new-if (= 1 1) 0 5)
</span></span><span class="line"><span class="cl">0
</span></span></code></pre></div><p>Delighted, Alyssa uses new-if to rewrite the square-root program:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sqrt-iter guess x)
</span></span><span class="line"><span class="cl">  (new-if (good-enough? guess x)
</span></span><span class="line"><span class="cl">          guess
</span></span><span class="line"><span class="cl">          (sqrt-iter (improve guess x)
</span></span><span class="line"><span class="cl">                     x)))
</span></span></code></pre></div><p>What happens when Alyssa attempts to use this to compute square roots? Explain.</p>
<p><strong>Answer 1.6.</strong> I believe this program is incorrect, because <code>new-if</code> uses applicative-order evaluation. Thus, it always expands the <code>else-clause</code> and causes an infinite recursion. In contrast, <code>if</code> uses normal-order evaluation.</p>
<p><strong>Exercise 1.7.</strong>  The <code>good-enough</code>? test used in computing square roots will not be very effective for finding the square roots of very small numbers. Also, in real computers, arithmetic operations are almost always performed with limited precision. This makes our test inadequate for very large numbers. Explain these statements, with examples showing how the test fails for small and large numbers. An alternative strategy for implementing <code>good-enough</code>? is to watch how guess changes from one iteration to the next and to stop when the change is a very small fraction of the guess. Design a square-root procedure that uses this kind of end test. Does this work better for small and large numbers?</p>
<p><strong>Answer 1.7.</strong> The results are very inaccurate when calculating <code>sqrt(0.0001)</code> and <code>sqrt(100000000)</code>. We can modify <code>good-enough</code> using current guess and previous guess below:</p>
<p>$$
\frac{|G-G_{pre}|}{G}&lt;0.001
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">  (&lt; (/ (abs (- guess prev-guess))
</span></span><span class="line"><span class="cl">        guess)
</span></span><span class="line"><span class="cl">     0.001))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (sqrt-iter guess prev-guess x)
</span></span><span class="line"><span class="cl">  (if (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">    guess
</span></span><span class="line"><span class="cl">    (sqrt-iter (improve guess x)
</span></span><span class="line"><span class="cl">               guess
</span></span><span class="line"><span class="cl">               x)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (sqrt x) 
</span></span><span class="line"><span class="cl">   (sqrt-iter 1.0 0 x))
</span></span></code></pre></div><p><strong>Exercise 1.8.</strong> Newton’s method for cube roots is based on the fact that if y is an approximation to the cube root of x, then a better approximation is given by the value</p>
<p>$$
\frac{x/y^2+2y}{3}
$$</p>
<p>Use this formula to implement a cube-root procedure analogous to the square-root procedure.</p>
<p><strong>Answer 1.8.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cub-iter guess prev-guess x)
</span></span><span class="line"><span class="cl">  (if (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">    guess
</span></span><span class="line"><span class="cl">    (cub-iter (improve guess x) guess x)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">  (&lt; (/ (abs (- guess prev-guess)) guess) 0.001)
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (improve guess x)
</span></span><span class="line"><span class="cl">  (/ (+ (/ x (square guess)) (* 2 guess)) 3)
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">  (* x x)
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cubroot x) 
</span></span><span class="line"><span class="cl">  ((if (&lt; x 0) - +) (cub-iter (improve 1.0 (abs x)) 1 (abs x)))
</span></span><span class="line"><span class="cl">  )
</span></span></code></pre></div>]]></description></item><item><title>LRU-based Replacement Algorithms Application of Flash Memory</title><link>https://blog.terryx.com/posts/lru-replacement-algorithms/</link><pubDate>Wed, 09 Nov 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/lru-replacement-algorithms/</guid><description><![CDATA[<h2 id="abstract">Abstract</h2>
<p>Nowadays, NAND flash memory has been widely used as storage medium for embedded systems because of its small size, lightweight, shock resistance, power economic and high reliability. As its capacity increases and its price decreases, flash-memory-based SSDs (abbreviated Solid-state Driver) has also become an alternative of magnetic disk in enterprise computing environment. In addition, flash memory has the characteristics of not-in-place update and asymmetric I/O costs among read, write, and erase operations, in which the cost of write/erase operations is much higher than that of read operation. Hence, the buffer replacement algorithms in flash-based systems should take the asymmetric I/O costs into account. There are several solutions to this issue, such as LRU, CFLRU, APRA and AML. As we LRU policy is a basic cache replacement algorithm and page replacement algorithm. Thus we try to introduce the different variants algorithm of LRU used especially in flash memory.</p>
<h2 id="instruction">Instruction</h2>
<p>Toshiba company developed flash memory EEPROM (abbreviated electronically erasable programmable read-only memory). There are two types of flash memory, NOR and NAND. The names are two logic gates used in each flash memory because the two types of memory exhibits similar characteristics of the corresponding logic gates. Besides the different design of two type of flash memories, the most important difference between the NOR and NAND flash memory is the bus interface. NOR flash memory is connected to Address/Data bus like cache memory device as SRAM. NAND flash memory uses a multiplexed I/O interface with additional control inputs. NOR flash memory is a random access device appropriate for code storage application, while NAND flash is a sequential access device appropriate for mass storage application. NOR flash memory can be used to store code and execute code, but NAND flash memory can’t store code because code can’t be executed there. It must be loaded into DRAM and executed there. Table 1 describes the main differences between NOR and NAND flash memory.</p>
<table>
  <thead>
      <tr>
          <th>Property</th>
          <th>NOR</th>
          <th>NAND</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Interface</td>
          <td>Bus</td>
          <td>I/O</td>
      </tr>
      <tr>
          <td>Cell Size</td>
          <td>Large</td>
          <td>Small</td>
      </tr>
      <tr>
          <td>Cell Cost</td>
          <td>High</td>
          <td>Low</td>
      </tr>
      <tr>
          <td>Read Time</td>
          <td>Fast</td>
          <td>Slow</td>
      </tr>
      <tr>
          <td>Program Time single Byte</td>
          <td>Fast</td>
          <td>Slow</td>
      </tr>
      <tr>
          <td>Program Time multi Byte</td>
          <td>Slow</td>
          <td>Fast</td>
      </tr>
      <tr>
          <td>Erase Time</td>
          <td>Slow</td>
          <td>Fast</td>
      </tr>
      <tr>
          <td>Power consumption</td>
          <td>High</td>
          <td>Low, but requires additional RAM</td>
      </tr>
      <tr>
          <td>Can execute code</td>
          <td>Yes</td>
          <td>No, but newer chips can execute a small loader out of the first page</td>
      </tr>
      <tr>
          <td>Bit twiddling</td>
          <td>nearly unrestricted</td>
          <td>1-3 times, also known as “partial page program restriction”</td>
      </tr>
      <tr>
          <td>Bad blocks at ship time</td>
          <td>No</td>
          <td>Allowed</td>
      </tr>
  </tbody>
</table>
<p><em>Table 1. The characteristics of flash memory</em> [1]</p>
<p>In addition, the characteristics of flash memory are significantly different from disks. First, the seek time of disk is very high because of numerous I/O activities. Second, flash memory has asymmetric read and write operation because the performance and energy consumption. Third, flash memory does not support in-place update because the write operation to the same page can’t be finished before the page is erased. Therefore, as the number of write operations is increasing so is the number of erase operations. When we consider the erase operations with write operations, the performance of a flash writing operation costs more than 8 times higher than flash read operation [2].</p>
<p>The operating system of embedded storage of most mobile devices has much more chances to optimize I/O subsystem to use particular features based on the characteristics of flash memory. The operating system can reduce the number of write and erase operations using the kernel-level information, and finally increase the performance. Most operating systems are customized for disk-based system and their replacement algorithms only concern the number of cache hits. But the operating system used for flash memory should consider different read and write cost when they replace pages. In this paper, we propose different replacement algorithms of flash memory, CFLRU, etc., and intend to compare the performance of these different replacement algorithms.
LRU Replacement Algorithm</p>
<p>LRU (abbreviated least recently used) has been frequently used for memory replacement algorithm, but this is not to say all the page lists are strictly maintained in LRU order when it used in operating system. In this section we intend to introduce the page replacement policy based on LRU replacement algorithm in Linux kernel. First, Virtual memory uses page cache to back up the data frequently referenced in the disk. When the page cache is full (see Fig. 1), the cache space is shrunk by selecting some less active pages and swapping them out the cache called page reclaiming. Thus we will focus on how the cache decides which pages to reclaim and how to maintain the least recently used pages swapping out of the cache space first.</p>
<p><img src="/images/20161109/Picture1.png" alt="Figure 1"  loading="lazy">
</p>
<p><em>Figure 1. Virtual Memory and Page Cache List example.</em></p>
<p>When a page in virtual address is accessed but not exists in physical memory the page faults are triggered. The page faults instruct the Linux kernel to read the missing data from the swap area. After writing back the data to the physical memory, the swap policy determines which pages can be swapped out of the physical memory without hitting the operating system performance. First, The LRU in Linux kernel contains two LRU lists called the <code>active_list</code> and <code>inactive_list</code> in Figure 1. The former list includes the pages that have been accessed recently, while the latter includes the pages that have not been accessed for some time. Apparently, future pages should be store from the inactive list. Second, there are two methods in Linux kernel to help maintain a balance between the active and inactive lists, <code>shrink_active_list()</code> and <code>shrink_inactive_list()</code>. The former is essentially responsible for deciding which page swapped out and which are not, while the latter is responsible for removing inactive pages from the <code>inactive_list</code> and transferring them to <code>shrink_page_list</code>, which then reclaims the selected pages by issuing requests to backing stores to write data back in order to free space physical memory.</p>
<p>In addition, the pages in the LRU lists may be cold or hot regardless either they are in <code>active_list</code> or <code>inactive_list</code>. If a page is hot, it means the page has been recently referenced. The pages in the <code>inactive_list</code> should be moved to the active_list because they are recently used. The pages in the <code>inactive_list</code> thus are always the least recently used pages. The kernel designed two flags to mark the hot/cold state of pages, <code>PG_active</code> and <code>PG_referenced</code> [3]. If the former is set, the page is in <code>active_list</code>, and in <code>inactive_list</code> vice versa. If the latter is set, the page is hot, and cold otherwise.
As we known, the page cache is a data structures which contain pages that are backed up. Fault pages or anonymous pages may be cached in this structures. The principle for this cache is to eliminate unnecessary disk reads. Pages read from disk are stored in a page hash table which hashed the address in order to always search the table before the disk is accessed. When caches have been shrunk, pages are moved from <code>active_list</code> to <code>inactive_list</code>. Pages are move from the end of the <code>active_list</code>. If the <code>PG_referenced</code> flag is set, it means the page is still hot and put back at the top of the <code>active_list</code>. This is sometimes called rotating the list in (see Fig. 2). If the <code>PG_referenced</code> flag is cleared, it is moved to <code>inactive_list</code> and set the <code>PG_referenced</code> flag in order to move back to <code>active_list</code> if necessary. After moving pages to <code>inactive_list</code>, the kernel can reclaim the pages in this list. We don’t discuss the page reclaiming in this section because the paper mainly focuses on the page replacement algorithm.</p>
<p><img src="/images/20161109/Picture2.png" alt="Figure 2"  loading="lazy">
</p>
<p><em>Figure 2. Page Cache LRU Lists in Linux kernel.</em> [4]</p>
<p>This LRU replacement algorithm implements is used in Linux kernel and works smoothly in a large number of machines. But it has some differences with machines using flash memory.</p>
<h2 id="cflru-replacement-algorithm">CFLRU Replacement Algorithm</h2>
<p>As we mentioned before, flash memory cost more time on write operation than read operation. Thus when operating system reclaims pages we should minimize the number of write operations. There are two types of pages in page cache, dirty page and clean page. A dirty page contains different data from the data in flash memory thus its data must be written back to the memory before dropped. While A clean page contains the same copy of the original data in flash memory thus it can be just dropped from the page cache when it is evicted by the replacement algorithm. For this purpose, Park, Jung, Kang, Kim, &amp; Lee (2006) propose a new replacement algorithm called CFLRU (abbreviated Clean-First LRU) [2]. CFLRU divides the LRU <code>inactive_list</code> into two regions as shown (see Fig. 3). The working region contains the of hot pages recently used, while the clean-first region contains pages which are candidates for reclaiming.</p>
<p><img src="/images/20161109/Picture3.png" alt="Figure 3"  loading="lazy">
</p>
<p><em>Figure 3. Example of CFLRU Replacement Algorithm.</em></p>
<p>CFLRU first selects a clean page to reclaim in the clean-first region to reduce the cost of flash write operation. If there is no clean page in this region, a dirty page at the end of the <code>inactive_list</code> is reclaimed. For example, under the LRU replacement algorithm the last page in the <code>inactive_list</code> is reclaimed first. Therefore, the order for victim pages is P8, P7, P6, and P5, in Figure 3. However, under the CFLRU replacement algorithm, it is P7, P5, P8, and P6.
The size of the clean-first region is called widow size, w. The cache hit rate may fall dramatically because the window size is too large and the pages can be referenced future only in a small size of working region. If the window size reduces to one, CFLRU replacement algorithm will degenerates to a simple LRU replacement algorithm. Thus, Park et al. devise two methods to deal with this problem, static-CFLRU and dynamic-CFLRU. Under static method, they investigate the proper window size of the clean-first region with static parameters by obtaining an average well-performed value from repetitive experiments. The dynamic method can properly adjust the window size based on the information collected from currently flash memory reading and writing. If the ration of write operation is more than the ratio of read operation, the method can enlarge the window size, and narrow vice versa. With the experiments, the dynamic-CFLRU performs well in contrast to static-CFLRU.</p>
<p>The implement of CFLRU is not difficult based on Linux kernel. As we mentioned before, the original Linux kernel selects the victim page in the <code>inactive_list</code> and swaps out it, but under CFLRU dirty pages are simply skipped and find next victim which is a clean page. If pages in the <code>inactive_list</code> are all dirty, the kernel just swapped out the last pages of the list. For the window size of the clean-first region in CFLRU, we can simply change the priority value of pages in the <code>inactive_list</code>. To adjust the widow size properly, the priority values of pages can be changed dynamically. Park et al. devise a kernel deamon periodically checks the read and write cost and compare with last replacement cost to decide whether to increase or reduce the priority values. The difference between the current cost and last cost must exceed a predefined threshold in order to avoid oscillation of the priority values.</p>
<h2 id="adaptive-page-replacement-algorithm">Adaptive Page Replacement Algorithm</h2>
<p>Shen, Jin, Song, &amp; Lee (2006) propose the APRA (abbreviated Adaptive Page Replacement Algorithm), because Shen et al. find that the read hit ratio of CFLRU is extremely low under certain workloads involving mainly read requests and its predefined window size contributes to the performance only for certain applications [5]. To deal with these shortcomings, the APRA maintains two cache lists of length L, LRU list and ghost list (see Fig. 4). The first list maintains a window to search clean pages just like CFLRU. However, the size of window can vary from W<sub>min</sub> to W<sub>max</sub> while static-CFLRU has fixed window size. Different from dynamic-CFLRU, the size of window in APRA can indicate the extent to which the clean pages are evicted from the buffer. The second list is called ghost list because it doesn’t contain the content of pages and just have the metadata of the pages which have been swapped out of the LRU list. In another word, the ghost list consists of the referenced history of pages which have been existed in LRU list. Although dirty pages evicted from LRU list have been already written back to the flash memory, we still mark these pages as dirty pages in ghost list to indicate the write operations.</p>
<p><img src="/images/20161109/Picture4.png" alt="Figure 4"  loading="lazy">
</p>
<p><em>Figure 4. Example of APRA page replacement.</em></p>
<p>APRA can always modify the size of window w based on the information of the current workload since an appropriate value of w will dramatically increase the hit ratio. The algorithm indents to increase or decrease the window size in LRU list depending on whether the state of pages in ghost list is dirty or clean, because the hit information can be observed in ghost list. Therefore, if a hit happened on a dirty page in ghost list, we enlarger w, and a hit happened on a clean page in ghost list, we narrow w. The extent of w changing is also very important. Hence Shen et al. devise two parameters p and q to control the changing extent of revision, where p = L/w and q = 1/(1-w/L) control the revision rates depending on w. Thus, the smaller the w is, the larger the increment p will be. Similarly, the larger the w is, the larger the decrement q will be. Suppose a large of number requests mainly involving write operations from file system, APRA will increase the size of window to evict more clean pages in the LRU list. Likewise, when a large of number request mainly involving read operations, APRA will decrease the size of widow to achieve a high read hit performance.</p>
<h2 id="aml-replacement-algorithm">AML Replacement Algorithm</h2>
<p>Zhu, Dai, &amp; Yang (2010) propose an improved LRU replacement algorithm called AML (abbreviated Adaptively Mixed List) algorithm, because Zhu et al. investigate that the evicting method of cold clean pages is inefficient. According to the page replacement policy, pages have to be evicted in the order of cold clean pages, hot clean pages, cold dirty pages, and hot dirty pages. Thus, AML replacement algorithm prefers to evict cold clean pages first and never chooses hot dirty pages as victims. In CFLRU algorithm, the clean pages are evicted regardless of cold or hot. However, the hot pages will be more likely to be referenced in the future than the cold pages. The cold pages thus must be evicted first to improve the hit ratio of page replacement in flash memory. To achieve the ideal results, AML maintains three LRU lists (see Fig. 5). The first list, LRU list, is just like CFLRU and APRA list with variable-size window. Cold clean list organizes all cold clean pages in the order of LRU list, and ghost list saves the metadata of swapped pages just like the ghost list in APRA, where it also doesn’t include any content of pages.</p>
<p><img src="/images/20161109/Picture5.png" alt="Figure 5"  loading="lazy">
</p>
<p><em>Figure 5. AML replacement algorithm example.</em></p>
<p>The AML algorithm improves CFLRU and APRA by maintaining a clean cold list, which can achieve the result that the clean cold pages can be first evicted. Zhu et al. devise a procedure to maintain the clean cold list which called cold-detection (see Fig. 6). In cold-detection, <code>COOLMAX</code> is an integer which is used to show the pages are the coldest. When the cold flag of a page reduces to zero, it shows that the page is hottest. For example, when <code>COOLMAX</code> is equal to 7, hot and cold can be divided into many levels from the coldest to the hottest (first hottest is 0, second hottest is 1, …, second coldest is 6, first coldest is 7). In addition, we can define which level is the boundary between cold and hot. When a page in AML lists is referenced, the procedure can move the cold clean pages to the clean cold list. If the referenced page is in the ghost list and it is a cold page (like P12 in fig. 5), moving it to the clean cold list and setting its cold flag as <code>COOLMAX</code>; If the referenced page is in the ghost list and it is a hot page (like P13 in fig. 5), moving it to the LRU list and its cold flag will be cleared to zero showing that it is a hot page; If the referenced page is in the cold clean list (like P9 in fig. 6), moving it to the LRU list and clearing its cold flag.</p>
<p><img src="/images/20161109/Picture6.png" alt="Figure 6"  loading="lazy">
</p>
<p><em>Figure 6. Cold-detection example.</em></p>
<p>The eviction of AML algorithm is just like CFLRU algorithm but AML first concerns the pages in cold clean list. If the list is not empty, evicting the pages in the list. If the list is empty, evicting the pages in LRU list just like LRU list in CFLRU. When pages in LRU list are evicted, the ghost list adds pages contains the metadata of them, such as information of hot/cold and clean/dirty. Besides, the variable size of window in LRU list is just like APRA replacement algorithm, which changes the size that depends on the information in ghost list also maintained by AML algorithm.</p>
<h2 id="performance-evaluation">Performance Evaluation</h2>
<p>Zhu et al. perform a complete experiment includes LRU, CFLRU, APRA, AML and LRUWSR (which is a simple improve version of CFLRU). In the experiment, they use six kinds of workloads contain all the access pattern in Table 2. The total references are 1,000,000. The locality expression 80/20 means 80% of the total number of accesses operation are performed in 20% of the flash memory area. The write/read ration of 90/10 means that the write and read operations are 90% and 10% respectively.</p>
<table>
  <thead>
      <tr>
          <th>Type</th>
          <th>Write/Read</th>
          <th>Locality</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>T9182</td>
          <td>90/10</td>
          <td>80/20</td>
      </tr>
      <tr>
          <td>T5582</td>
          <td>50/50</td>
          <td>80/20</td>
      </tr>
      <tr>
          <td>T1982</td>
          <td>10/90</td>
          <td>80/20</td>
      </tr>
      <tr>
          <td>T9155</td>
          <td>90/10</td>
          <td>50/50</td>
      </tr>
      <tr>
          <td>T5555</td>
          <td>50/50</td>
          <td>50/50</td>
      </tr>
      <tr>
          <td>T1955</td>
          <td>10/90</td>
          <td>50/50</td>
      </tr>
  </tbody>
</table>
<p><em>Table. 2 The types of traces.</em></p>
<p>Figure 7 shows the hit ratios of the five replacement algorithms. The hit ratio of AML is almost equal to LRU. It is higher than other algorithms in most cases (see Fig. 6). Because AML prefers to evict the cold clean page first, and it delays eviction of hot page to keep high hit ratio. When the locality of data access is 50/50, the hit ratio of AML is pretty same as other three replacement algorithms. When locality is good and I/O access is write-dominant as 90/10, the hit ratio of AML is pretty same as that of APRA. On this condition, the major evicted pages are dirty pages, and clean pages are very few. Thus, the faster cold dirty pages are evicted, the higher is hit ratio.</p>
<p><img src="/images/20161109/Picture7.png" alt="Figure 7"  loading="lazy">
</p>
<p><em>Figure 7. Hit ratio of different traces</em></p>
<p>Figure 8 shows the number of pages written into flash memory. They got these results by counting the number of physical flush operations, and adding the number of dirty pages remaining in the buffer. They have known that a good algorithm not only keeps high hit ratio but also decreases the write counts effectively to reduce the replacement cost. AML is basically done both for various traces. When write/read ratio is smaller, the write count of AML is much less than other algorithms including APRA. It reduces the write count on average by 15% compared to APRA and by 10% compared to CFLRU. For write-most access pattern, the write count of AML is smaller than that of other algorithms. However, it is nearly equal to that of APRA.</p>
<p><img src="/images/20161109/Picture8.png" alt="Figure 8"  loading="lazy">
</p>
<p><em>Figure 8. Write counts of various traces</em></p>
<p>Figure 9 shows the overall runtime of various replacement algorithms. Except LRU list AML maintain an additional ghost list. The space overhead of keeping ghost list is very small as the paper mentioned before. They only focus on the time overhead of these algorithm. Runtime is estimated as the sum of read, write latency and the time of erase operations. Runtime therefore reflects overall performance. The runtime is determined by hit ratio and write count. It is the standard to judge whether this algorithm is effective enough. The runtime of AML is reduced at most by 18% compared to APRA. Even if CFLRU has a good performance in the read-most applications, AML reduces the runtime on average by 14% compared to CFLRU.</p>
<p><img src="/images/20161109/Picture9.png" alt="Figure 9"  loading="lazy">
</p>
<p><em>Figure 9. Runtime for various traces.</em></p>
<h2 id="conclusion">Conclusion</h2>
<p>In the LRU-based replacement algorithms of flash memory, we introduce the main LRU algorithm which is widely used in Linux kernel and many other operating systems. Then we mainly investigate three algorithm aiming to improve the traditional LRU replacement algorithm as we called LRU-based replacement algorithms. The first algorithm is CFLRU replacement algorithm. It changes the order of evicting pages in LRU within selecting clean pages first. The method can reduce the cost of write operations. The second algorithm is APRA, which adds ghost list to dynamically change the size of window in CFLRU algorithm. Because the performance of CFLRU may decrease dramatically when the I/O access is read-dominant. The last algorithm is AML replacement algorithm which adds a cold clean list to APRA. The cold clean pages can be evicted first within the cold-detection method, and this algorithm performs better than three other algorithms in different condition in flash memory.</p>
<h2 id="reference">Reference</h2>
<p>[1] Memory Technology Device (MTD) Subsystem for Linux, <a href="http://www.linux-mtd.infradead.org/doc/nand.html/">http://www.linux-mtd.infradead.org/doc/nand.html/</a>.</p>
<p>[2] Park, S. Y., Jung, D., Kang, J. U., Kim, J. S., &amp; Lee, J. (2006, October). CFLRU: a replacement algorithm for flash memory. In Proceedings of the 2006 international conference on Compilers, architecture and synthesis for embedded systems (pp. 234-241). ACM.</p>
<p>[3] Bovet, D. P., &amp; Cesati, M. (2005). Page Frame Reclaiming, Understanding the Linux Kernel, Third Edition (pp. 676-737). O’Reilly Media, Inc.</p>
<p>[4] Page Frame Reclamation, <a href="https://www.kernel.org/doc/gorman/html/understand/understand013.html">https://www.kernel.org/doc/gorman/html/understand/understand013.html</a>.</p>
<p>[5] Shen, B., Jin, X., Song, Y. H., &amp; Lee, S. S. (2009). APRA: adaptive page replacement algorithm for NAND flash memory storages. In Computer Science-Technology and Applications, 2009. IFCSTA’09. International Forum on (Vol. 1, pp. 11-14). IEEE.</p>
<p>[6] Zhu, H., Dai, H., &amp; Yan, Y. (2010, December). AML: a novel page replacement algorithm for Solid State Disks. In Computational Intelligence and Software Engineering (CiSE), 2010 International Conference on (pp. 1-6). IEEE.</p>
]]></description></item><item><title>Spring IoC Container Part 3</title><link>https://blog.terryx.com/posts/spring4-3/</link><pubDate>Mon, 24 Oct 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/spring4-3/</guid><description><![CDATA[<h2 id="defaultsingletonbeanregistry">DefaultSingletonBeanRegistry</h2>
<p>Last time we find that in the <code>DefaultListableBeanFactory</code> it provides map to save bean definitions. But when getting bean instance, we need to step into <code>DefaultSingletonBeanRegistry</code>. First let’s see the document:</p>
<blockquote>
<p>Generic registry for shared bean instances, implementing the <code>SingletonBeanRegistry</code>. <strong>Allows for registering singleton instances that should be shared for all callers of the registry, to be obtained via bean name</strong>.</p>
</blockquote>
<blockquote>
<p>Also supports registration of <code>DisposableBean</code> instances, (which might or might not correspond to registered singletons), to be destroyed on shutdown of the registry. Dependencies between beans can be registered to enforce an appropriate shutdown order.</p>
</blockquote>
<blockquote>
<p>This class mainly serves as base class for <code>BeanFactory</code> implementations, factoring out the common management of singleton bean instances. Note that the <code>ConfigurableBeanFactory</code> interface extends the <code>SingletonBeanRegistry</code> interface.</p>
</blockquote>
<blockquote>
<p>Note that this class assumes neither a bean definition concept nor a specific creation process for bean instances, in contrast to <code>AbstractBeanFactory</code> and <code>DefaultListableBeanFactory</code> (which inherit from it). Can alternatively also be used as a nested helper to delegate to.</p>
</blockquote>
<p>In the class, it has private variable to cache the bean instance:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/** Cache of singleton objects: bean name --&gt; bean instance */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">singletonObjects</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ConcurrentHashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">&gt;</span><span class="p">(</span><span class="n">256</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><h2 id="abstractbeanfactory">AbstractBeanFactory</h2>
<p>Again <code>AbstractBeanFactory</code> is very important <code>BeanFactory</code> implementation to get beans, and it is also a <code>SingletonBeanRegistry</code> interface implementation to save beans.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">doGetBean</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                          </span><span class="n">Class</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">requiredType</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                          </span><span class="n">Object</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                          </span><span class="kt">boolean</span><span class="w"> </span><span class="n">typeCheckOnly</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div><p>When <code>ApplicationContext</code> calls <code>doGetBean(...)</code>, it will call <code>getSingleton(...)</code> which is declared in <code>SingletonBeanRegistry</code> interface and implements in <code>DefaultSingletonBeanRegistry</code>.</p>
<blockquote>
<p>Return the (raw) singleton object registered under the given name.
Only checks already instantiated singletons; does not return an Object for singleton bean definitions which have not been instantiated yet.</p>
</blockquote>
<blockquote>
<p>The main purpose of this method is to access manually registered singletons (see <code>registerSingleton(java.lang.String, java.lang.Object)</code>). Can also be used to access a singleton defined by a bean definition that already been created, in a raw fashion.</p>
</blockquote>
<blockquote>
<p>NOTE: This lookup method is not aware of FactoryBean prefixes or aliases. You need to resolve the canonical bean name first before obtaining the singleton instance.</p>
</blockquote>
<p>In this method, if the bean exists in concurrent map <code>singletonObjects&lt;String, Object&gt;</code> of <code>DefaultSingletonBeanRegistry</code>, it will call <code>getSingleton(...)</code> and return the bean object; Else the bean isn’t defined, the method will also call  <code>getSingleton(...)</code>, if the singleton bean is null then it will generate the object of bean.</p>
<h2 id="create-object-of-bean">Create Object of Bean</h2>
<p>How does spring create object from bean definition file? In <code>AbstractBeanFactory</code>, it provide an abstract bean creation method:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="kd">abstract</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">createBean</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">RootBeanDefinition</span><span class="w"> </span><span class="n">mbd</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="kd">throws</span><span class="w"> </span><span class="n">BeanCreationException</span><span class="p">;</span><span class="w">
</span></span></span></code></pre></div><p>Also see the document:</p>
<blockquote>
<p><strong>Create a bean instance for the given merged bean definition (and arguments).</strong> The bean definition will already have been merged with the parent definition in case of a child definition.</p>
</blockquote>
<blockquote>
<p>All bean retrieval methods delegate to this method for actual bean creation.</p>
</blockquote>
<p>This method is implemented in <code>AbstractAutowireCapableBeanFactory</code>:</p>
<blockquote>
<p>Abstract bean factory superclass that implements default bean creation, with the full capabilities specified by the <code>RootBeanDefinition</code> class. Implements the <code>AutowireCapableBeanFactory</code> interface <strong>in addition to AbstractBeanFactory’s <code>createBean(java.lang.Class&lt;T&gt;)</code> method.</strong></p>
</blockquote>
<blockquote>
<p>Provides bean creation (with constructor resolution), property population, wiring (including autowiring), and initialization. Handles runtime bean references, resolves managed collections, calls initialization methods, etc. Supports autowiring constructors, properties by name, and properties by type.</p>
</blockquote>
<blockquote>
<p>The main template method to be implemented by subclasses is <code>AutowireCapableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter)</code>, used for autowiring by type. In case of a factory which is capable of searching its bean definitions, matching beans will typically be implemented through such a search. For other factory styles, simplified matching algorithms can be implemented.</p>
</blockquote>
<blockquote>
<p>Note that this class does not assume or implement bean definition registry capabilities. See <code>DefaultListableBeanFactory</code> for an implementation of the <code>ListableBeanFactory</code> and <code>BeanDefinitionRegistry</code> interfaces, which represent the API and SPI view of such a factory, respectively.</p>
</blockquote>
<p>Now we just move to <code>createBean(...)</code> method and its main method is <code>doCreateBean(...)</code>:</p>
<blockquote>
<p>Actually create the specified bean. Pre-creation processing has already happened at this point, <em>e.g. checking</em> <code>postProcessBeforeInstantiation</code> <em>callbacks</em>.</p>
</blockquote>
<blockquote>
<p>Differentiates between default bean instantiation, use of a factory method, and autowiring a constructor.</p>
</blockquote>
<p>So we can know from the document that the method just create the specified bean which means it should get class reference in the definition file.</p>
<p>In this method, we find <code>BeanWrapper</code> class which is the central interface of Spring’s low-level JavaBeans infrastructure. The wrapper  is initialized with <code>createBeanInstance(...)</code> method which can create a new instance for the specified bean, using an appropriate instantiation strategy: factory method, constructor autowiring, or simple instantiation. Then it call the core instantiation method <code>instantiateBean(...)</code> and it will step into <code>InstantiationStrategy</code> interface.</p>
<h2 id="instantiationstrategy">InstantiationStrategy</h2>
<blockquote>
<p>Interface responsible for creating instances corresponding to a root bean definition.</p>
</blockquote>
<blockquote>
<p>This is pulled out into a strategy as various approaches are possible, including using CGLIB to create subclasses on the fly to support Method Injection.</p>
</blockquote>
<p>Here we just talk about its <code>SimpleInstantiationStrategy</code> implement class. it has <code>instantiate(...)</code> which can return an instance of the bean with the given name in this factory. First it get the <code>Class&lt;?&gt; clazz</code> of the bean, and call <code>clazz.getDeclaredConstructor(...)</code> to get the <code>Constructor&lt;?&gt;</code> of the bean, then step into <code>BeanUtils</code> class and call <code>instantiateClass(...)</code> method which can call <code>constructor.newInstance(args)</code> and return a new object created by calling the constructor this object represents.</p>
<p>Finally, the object will be saved in the <code>singletonObjects&lt;String, Object&gt;</code> for <code>getBean(...)</code> method to get the object.</p>
<h2 id="whats-next">What’s Next?</h2>
<p>After reading the source code of Spring’s IoC, I find some TODO list.</p>
<ul>
<li><code>ThreadLocal&lt;?&gt;</code>, <code>ConcurrentMap&lt;K, V&gt;</code> and <em>volatile</em> are often appeared in the source, so I need to deal with something about Java Threads;</li>
<li><a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/">Spring Reference</a> is very useful document to read thus I need to focus more with it.</li>
</ul>
]]></description></item><item><title>Spring IoC Container Part 2</title><link>https://blog.terryx.com/posts/spring4-2/</link><pubDate>Fri, 21 Oct 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/spring4-2/</guid><description><![CDATA[<h2 id="log4j">Log4J</h2>
<p>When using Spring framework, we must use <a href="https://commons.apache.org/proper/commons-logging/">Apache Common Logging</a> to print log in console or binary files. As we known, Spring log configuration can change in the <code>web.xml</code> when it works on server. But in these series of articles, we try to analyze the Spring core techniques without works on server. So there should have another way to configure log without <code>web.xml</code> because we want to see the debug informations.</p>
<p>Spring gives <code>Log4jConfigurer.initLogging()</code> method (has been deprecated in Spring 4.2.1) to  initialize log4j from the given file location. Note that we always use Maven to build project, but maven might mash <code>src</code> and <code>resources</code> folders to one. Thus we should use <code>classpath:</code> ,<strong>without slash</strong>, to represent <code>resources</code> folder in the project.</p>
<p>Now Apache Commons Logging (JCL) provides thin-wrapper Log implementations for other logging tools, including Log4J. But <code>Log4jConfigurer.initLogging()</code> calls methods from log4j 1.x. It means that we should add log4j 1.x dependency to make sure that our log configuration file works smoothly.</p>
<p>Here is the configure file <code>log4j.properties</code>, and just opening debug function in <code>org.springframework.beans</code> because we want to know the IOC process:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">log4j.rootCategory=INFO, stdout
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">log4j.appender.stdout=org.apache.log4j.ConsoleAppender
</span></span><span class="line"><span class="cl">log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
</span></span><span class="line"><span class="cl">log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c:%L - %m%n
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">log4j.category.org.springframework.beans=DEBUG
</span></span></code></pre></div><p>As last article, we run the same code but add our log configuration before:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Log4jConfigurer</span><span class="p">.</span><span class="na">initLogging</span><span class="p">(</span><span class="s">&#34;classpath:log4j.properties&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="s">&#34;services.xml&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">PetStoreServiceImpl</span><span class="w"> </span><span class="n">petStoreService</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;petStore&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">PetStoreServiceImpl</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>Now we can follow the log information to know the IOC clearly.</p>
<h2 id="classpathxmlapplicationcontext">ClassPathXmlApplicationContext</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">17:23:15,265  INFO main ClassPathXmlApplicationContext org.springframework.context.support.AbstractApplicationContext.prepareRefresh:581 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@42dafa95: startup date [Fri Oct 21 17:23:15 EDT 2016]; root of context hierarchy
</span></span></code></pre></div><p>First we step into <code>ClassPathXmlApplicationContext</code> constructor and it calls <code>refresh()</code>. This method is declared in the interface <code>ConfigurableApplicationContext</code>, implements in <code>AbstractApplicationContext</code>, finally called in <code>ClassPathXmlApplicationContext</code> which is a subclass of <code>AbstractApplicationContext</code>.</p>
<blockquote>
<p>This method can load or refresh the <strong>persistent representation</strong> of the configuration, which might an XML file, properties file, or relational database schema. As this is a startup method, it should destroy already created singletons if it fails, to avoid dangling resources. In other words, after invocation  of that method, either all or no singletons at all should be instantiated.</p>
</blockquote>
<p>As we see in the document, <code>refresh()</code> is used to load and refresh persistent representation configuration. It should be done first of all.</p>
<h2 id="xmlbeandefinitionreader">XmlBeanDefinitionReader</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">17:23:15,555  INFO main XmlBeanDefinitionReader org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions:317 - Loading XML bean definitions from class path resource [services.xml]
</span></span></code></pre></div><p>The <code>refresh()</code> method calls <code>obtainFreshBeanFactory()</code> in  which can tell the subclass to refresh the internal bean factory. So how to let a class to call the method (in this case it is <code>refreshBeanFactory()</code>) in its subclass? It is a very classical design pattern.</p>
<p>First, the <code>AbstractApplicationContext</code> declares:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="kd">abstract</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">refreshBeanFactory</span><span class="p">()</span><span class="w">
</span></span></span></code></pre></div><p>This method is implemented in <code>AbstractRefreshableApplicationContext</code> which is a subclass of <code>AbstractApplicationContext</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">protected</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">refreshBeanFactory</span><span class="p">()</span><span class="w">
</span></span></span></code></pre></div><p>Therefore the father class can call the method which implemented in its subclass.</p>
<p>Here is <code>XmlBeanDefinitionReader</code>:</p>
<blockquote>
<p>Bean definition reader for XML bean definitions. Delegates the actual XML document reading to an implementation of the <code>BeanDefinitionDocumentReader</code> interface. Typically applied to a
<code>DefaultListableBeanFactory</code> or a <code>GenericApplicationContext</code>.</p>
</blockquote>
<blockquote>
<p>This class loads a DOM document and applies the <code>BeanDefinitionDocumentReader</code> to it.</p>
</blockquote>
<blockquote>
<p>The document reader will register each bean definition with the given bean factory, talking to the latter’s implementation of the <code>BeanDefinitionRegistry</code> interface.</p>
</blockquote>
<p><code>loadBeanDefinition()</code> method is used to load bean definitions from the specified XML file.</p>
<h2 id="defaultdocumentloader">DefaultDocumentLoader</h2>
<p><code>XmlBeanDefinitionReader</code> calls <code>doLoadDocument()</code> and it has local variable <code>DocumentLoader</code> documentLoader which calls <code>loadDocument()</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">19:38:23,603 DEBUG main DefaultDocumentLoader org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument:73 - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
</span></span></code></pre></div><p>Here is <code>DefaultDocumentLoader</code>:</p>
<blockquote>
<p>Spring’s default {@link DocumentLoader} implementation. Simply loads <code>Document</code> documents using the standard JAXP-configured XML parser. If you want to change the <code>DocumentBuilder</code> that is used to load documents, then one strategy is to define a corresponding Java system property when starting your JVM. For example, to use the Oracle <code>DocumentBuilder</code>, might start your application like as follows:</p>
<p><code>java -Djavax.xml.parsers.DocumentBuilderFactory=oracle.xml.jaxp.JXDocumentBuilderFactory MyMainClass</code></p>
</blockquote>
<h2 id="defaultbeandefinitiondocumentreader">DefaultBeanDefinitionDocumentReader</h2>
<p>Here is <code>DefaultBeanDefinitionDocumentReader</code> which is used to read bean definitions:</p>
<blockquote>
<p>Default implementation of the <code>BeanDefinitionDocumentReader</code> interface that reads bean definitions according to the “spring-beans” DTD and XSD format (Spring’s default XML bean definition format).</p>
</blockquote>
<blockquote>
<p>The structure, elements, and attribute names of the required XML document are hard-coded in this class. (Of course a transform could be run if necessary to produce this format). <code>&lt;beans&gt;</code> does not need to be the root element of the XML document: this class will parse all bean definition elements in the XML file, regardless of the actual root element.</p>
</blockquote>
<p>And <code>registerBeanDefinitions(doc, readerContext)</code>:</p>
<blockquote>
<p>Read bean definitions from the given DOM document and register them with the registry in the given reader context.</p>
</blockquote>
<blockquote>
<p><code>doc</code> the DOM document <code>readerContext</code> the current context of the reader (includes the target registry and the resource being parsed)</p>
</blockquote>
<h2 id="defaultlistablebeanfactory">DefaultListableBeanFactory</h2>
<blockquote>
<p>Default implementation of the <code>ListableBeanFactory</code> and <code>BeanDefinitionRegistry</code> interfaces: a full-fledged bean factory based on bean definition objects.
<strong>Typical usage is registering all bean definitions first (possibly read from a bean definition file), before accessing beans</strong>. Bean definition lookup is therefore an inexpensive operation in a local bean definition table, operating on pre-built bean definition metadata objects.</p>
</blockquote>
<blockquote>
<p>Can be used as a standalone bean factory, or as a superclass for custom bean factories. Note that readers for specific bean definition formats are typically implemented separately rather than as bean factory subclasses: see for example <code>PropertiesBeanDefinitionReader</code> and <code>XmlBeanDefinitionReader</code>.</p>
</blockquote>
<blockquote>
<p>For an alternative implementation of the <code>ListableBeanFactory</code> interface, have a look at <code>StaticListableBeanFactory</code>, which manages existing bean instances rather than creating new ones based on bean definitions.</p>
</blockquote>
<p>It implements the bean register method <code>registerBeanDefinition()</code> which is declared in interface <code>BeanDefinitionRegistry</code>.</p>
<blockquote>
<p>Register a new bean definition with this registry. Must support <code>RootBeanDefinition</code> and <code>ChildBeanDefinition</code>.</p>
</blockquote>
<p>Now we look at <code>DefaultListableBeanFactory</code> and find that it has some private variables.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/** Map of bean definition objects, keyed by bean name */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="o">&gt;</span><span class="w"> </span><span class="n">beanDefinitionMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ConcurrentHashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="o">&gt;</span><span class="p">(</span><span class="n">256</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="cm">/** List of bean definition names, in registration order */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="kd">volatile</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">beanDefinitionNames</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="p">(</span><span class="n">256</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>Note that <code>beanDefinitionMap</code> is a <code>java.util.concurrent.ConcurrentHashMap</code> and <code>beanDefinitionNames</code> is a volatile variable.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="k">this</span><span class="p">.</span><span class="na">beanDefinitionMap</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">beanDefinition</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">this</span><span class="p">.</span><span class="na">beanDefinitionNames</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>TODO: <code>java.util.concurrent.ConcurrentHashMap</code> and volatile variable.</p>
]]></description></item><item><title>Spring IoC Container Part 1</title><link>https://blog.terryx.com/posts/spring4-1/</link><pubDate>Mon, 10 Oct 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/spring4-1/</guid><description><![CDATA[<p>Let’s look a simple code within Spring below:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// create and configure beans</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="p">{</span><span class="s">&#34;services.xml&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;daos.xml&#34;</span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// retrieve configured instance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">PetStoreService</span><span class="w"> </span><span class="n">service</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;petStore&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">PetStoreService</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// use configured instance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">userList</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">service</span><span class="p">.</span><span class="na">getUsernameList</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>First of all, we should know the class hierarchy in <code>org.springframework.context.support</code>:</p>
<p><img src="http://www.plantuml.com/plantuml/svg/fP7D2i8m3CVFxYbwd8Xx1zdLW-X540zPpMQnQqiIFs3uxcwh5qLbmq03JVx9Bqq3w1DKg3nL6GSohYe9QhnwEcNQEy6RP7mEmPCqIQ9QCssGIj2eSkzAKvq92ekB4ApH8CQxF9QfffTtDhjuSr249I4VqsaVl_SU2XO2BKfRO5QBv_L3DrC7YpKwuN-v8y7DWB9rH7mPg3te3hyW8nbn0GD8F-UAqCby8zstx_PAzssNFgeufcUCahycqZVXaCLkQpjktczlR9B9anG1UUTN8CTXXC-gs3IvFm00" alt=""  loading="lazy">
</p>
<p><code>ClassPathXmlApplicationContext</code> implements <code>ApplicationContext</code> and calls its constructor as below:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="w"> </span><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Create a new ClassPathXmlApplicationContext, loading the definitions
</span></span></span><span class="line"><span class="cl"><span class="cm"> * from the given XML file and automatically refreshing the context.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param configLocation resource location
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws BeansException if context creation failed
</span></span></span><span class="line"><span class="cl"><span class="cm"> **/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="nf">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">configLocation</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">BeansException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="p">{</span><span class="n">configLocation</span><span class="p">},</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Step into <code>ClassPathXmlApplicationContext(String[], boolean, ApplicationContext)</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Create a new ClassPathXmlApplicationContext with the given parent,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * loading the definitions from the given XML files.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param configLocations array of resource locations
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param refresh whether to automatically refresh the context,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * loading all bean definitions and creating all singletons.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Alternatively, call refresh manually after further configuring the context.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param parent the parent context
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws BeansException if context creation failed
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @see #refresh()
</span></span></span><span class="line"><span class="cl"><span class="cm"> **/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="nf">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">configLocations</span><span class="p">,</span><span class="w"> </span><span class="err">￼</span><span class="kt">boolean</span><span class="w"> </span><span class="n">refresh</span><span class="p">,</span><span class="w"> </span><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">parent</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kd">throws</span><span class="w"> </span><span class="n">BeansException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">super</span><span class="p">(</span><span class="n">parent</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">setConfigLocations</span><span class="p">(</span><span class="n">configLocations</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">refresh</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">refresh</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>In this method, it first call <code>super(parent)</code>, which is <code>AbstractXmlApplicationContext(parent)</code> –&gt; <code>AbstractRefreshableConfigApplicationContext(parent)</code> –&gt; <code>AbstractRefreshableApplicationContext(parent)</code> –&gt; <code>AbstractApplicationContext(parent)</code>.</p>
<p>Then, for the <code>setConfigLocations(configLocations)</code>, we need move to <code>AbstractRefreshableConfigApplicationContext</code>, the superclass of <code>ClassPathXmlApplicationContext</code>. It has <code>setConfigLocations(configLocations)</code> that deals with the locations String and save to its private value <code>String[] configLocations</code>.</p>
<p>Now, we get to the <code>refresh()</code> method belong to <code>AbstractApplicationContext</code> that implements the method in the interface <code>ConfigurableApplicationContext</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Load or refresh the persistent representation of the configuration,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * which might an XML file, properties file, or relational database schema.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * &lt;p&gt;As this is a startup method, it should destroy already created singletons
</span></span></span><span class="line"><span class="cl"><span class="cm"> * if it fails, to avoid dangling resources. In other words, after invocation
</span></span></span><span class="line"><span class="cl"><span class="cm"> * of that method, either all or no singletons at all should be instantiated.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws BeansException if the bean factory could not be initialized
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @throws IllegalStateException if already initialized and multiple refresh
</span></span></span><span class="line"><span class="cl"><span class="cm"> * attempts are not supported
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">refresh</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">BeansException</span><span class="p">,</span><span class="w"> </span><span class="n">IllegalStateException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="kd">synchronized</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="na">startupShutdownMonitor</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// Prepare this context for refreshing.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">prepareRefresh</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// Tell the subclass to refresh the internal bean factory.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ConfigurableListableBeanFactory</span><span class="w"> </span><span class="n">beanFactory</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">obtainFreshBeanFactory</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// Prepare the bean factory for use in this context.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">prepareBeanFactory</span><span class="p">(</span><span class="n">beanFactory</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">// remainder...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>For this line call <code>obtainFreshBeanFactory()</code> that then calls <code>refreshBeanFactory()</code>, subclass <code>AbstractXmlApplicationContext</code> to refresh bean factory and load bean definitions by calling <code>loadBeanDefinitions(beanFactory)</code>, and then it calls <code>loadBeanDefinitions(reader)</code>, in which reader is <code>XmlBeanDefinitionReader</code> implements <code>BeanDefinitionReader</code>. This class loads a DOM document and applies the reader to it. The document reader will register each bean definition with the given bean factory, talking to the latter’s implementation of the <code>BeanDefinitionRegistry</code> interface.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="c1">// Tell the subclass to refresh the internal bean factory.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">ConfigurableListableBeanFactory</span><span class="w"> </span><span class="n">beanFactory</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">obtainFreshBeanFactory</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>The reader has the <code>loadBeanDefinitions(configLocations)</code> method and the inner method of <code>XmlBeanDefinitionReader</code> provides a <code>loadBeanDefinitions(encodedResource)</code> where <code>EncodedResource</code> is the resource descriptor for the XML file, allowing to specify an encoding to use for parsing the file.</p>
<p>Method <code>doLoadDocument(inputSource, resource)</code> actually load bean definitions from the specified XML file. <code>DefaultDocumentLoader</code> that implements <code>DocumentLoader</code> loads a <code>Document</code> document from the supplied <code>InputSource</code> source by calling method <code>loadDocument(InputSource, EntityResolver, ...)</code> (that is a classical design pattern).</p>
<p>Further topics: <code>InputSource</code> of Spring Resource,<code>ThreadLocal</code> of Java SE concurrency, <code>context.getBean(...)</code> of how to get instantialization of service.</p>
]]></description></item><item><title>3.2 Bean Scopes</title><link>https://blog.terryx.com/posts/2016-01-21-32---bean-scopes/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-21-32---bean-scopes/</guid><description><![CDATA[<h3 id="bean-scopes-singleton-and-prototype">Bean scopes: singleton and prototype</h3>
<h4 id="1-singleton">1. singleton</h4>
<p>Only one instance in Spring IoC container. Only return the same Bean.</p>
<blockquote>
<p>One instance of the bean is created for the entire application.</p>
</blockquote>
<p>Two ways to implement, we could learn how Spring work through the code bellow:</p>
<ul>
<li><strong>Define static attribute to hold the instance:</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">cn.javass.spring.chapter3.bean</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">Singleton</span><span class="w"> </span><span class="p">{</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">//1. Private constructor  </span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="nf">Singleton</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">class</span> <span class="nc">InstanceHolder</span><span class="w"> </span><span class="p">{</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Singleton</span><span class="w"> </span><span class="n">INSTANCE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Singleton</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">//3.Global accession  </span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">Singleton</span><span class="w"> </span><span class="nf">getInstance</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">InstanceHolder</span><span class="p">.</span><span class="na">INSTANCE</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Via <em>SingletonBeanRegistry</em>:</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.HashMap</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.Map</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.beans.factory.config.SingletonBeanRegistry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">SingletonBeanRegister</span><span class="w"> </span><span class="kd">implements</span><span class="w"> </span><span class="n">SingletonBeanRegistry</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">BEANS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="o">&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">containsSingleton</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">getSingleton</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">getSingletonCount</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">size</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="nf">getSingletonNames</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">BEANS</span><span class="p">.</span><span class="na">keySet</span><span class="p">().</span><span class="na">toArray</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">registerSingleton</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="n">bean</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">BEANS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">beanName</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">beanName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&#34;] is exist&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">BEANS</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">bean</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>JUnit Test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.junit.Test</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">SingletonTest</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testRegister</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">SingletonBeanRegister</span><span class="w"> </span><span class="n">register</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SingletonBeanRegister</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">register</span><span class="p">.</span><span class="na">registerSingleton</span><span class="p">(</span><span class="s">&#34;bean1&#34;</span><span class="p">,</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HelloImpl2</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">HelloImpl2</span><span class="w"> </span><span class="n">bean1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">HelloImpl2</span><span class="p">)</span><span class="w"> </span><span class="n">register</span><span class="p">.</span><span class="na">getSingleton</span><span class="p">(</span><span class="s">&#34;bean1&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bean1</span><span class="p">.</span><span class="na">sayHello</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">register</span><span class="p">.</span><span class="na">registerSingleton</span><span class="p">(</span><span class="s">&#34;bean1&#34;</span><span class="p">,</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HelloImpl2</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">Exception</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="na">getMessage</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>We could define <em>singleton</em> in xml:</strong></li>
</ul>
<p>In most time, <em>singleton</em> is default in Spring.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span>  <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter3.bean.Printer&#34;</span> <span class="na">scope=</span><span class="s">&#34;singleton&#34;</span><span class="nt">/&gt;</span>
</span></span></code></pre></div><h4 id="2-prototype">2. prototype</h4>
<p>Return new Bean when container request a Bean. Contrast with <em>singleton</em>, <em>prototype</em> would not cache Bean.</p>
<blockquote>
<p>One instance of the bean is created every time the bean is injected
into or retrieved from the Spring application context.</p>
</blockquote>
<ul>
<li><strong>Here is the implement of <em>prototype</em> in Spring</strong>:</li>
</ul>
<p>Bean definition:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BeanDefinition</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//singleton</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">SCOPE_SINGLETON</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//prototype</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">SCOPE_PROTOTYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//identity</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">id</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">clazz</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//Scope</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">scope</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SCOPE_SINGLETON</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setId</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">id</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">this</span><span class="p">.</span><span class="na">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">id</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">getId</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">id</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setClazz</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">clazz</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">this</span><span class="p">.</span><span class="na">clazz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">clazz</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">getClazz</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">clazz</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setScope</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">scope</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">this</span><span class="p">.</span><span class="na">scope</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">scope</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">getScope</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">scope</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Bean registry, also use Map:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BeanDifinitionRegister</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="o">&gt;</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">registerBeanDefinition</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">()))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;Bean definition is exist!&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">(),</span><span class="w"> </span><span class="n">bd</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="w"> </span><span class="nf">getBeanDefinition</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">containsBeanDefinition</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">containsKey</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Bean factory checks in the registry so that the Bean is new every time:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">DefaultBeanFactory</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//Bean registry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">BeanDifinitionRegister</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">BeanDifinitionRegister</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">//singleton registry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">SingletonBeanRegistry</span><span class="w"> </span><span class="n">SINGLETONS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SingletonBeanRegister</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">getBean</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">beanName</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//is Bean definition exist?</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">containsBeanDefinition</span><span class="p">(</span><span class="n">beanName</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;Not exist[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">beanName</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&#34;]Bean difinition&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//get Bean definition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">getBeanDefinition</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//is it singleton?</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getScope</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="p">.</span><span class="na">SCOPE_SINGLETON</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="c1">//yes</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">containsSingleton</span><span class="p">(</span><span class="n">beanName</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="k">return</span><span class="w"> </span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">getSingleton</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="c1">//no</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">registerSingleton</span><span class="p">(</span><span class="n">beanName</span><span class="p">,</span><span class="w"> </span><span class="n">createBean</span><span class="p">(</span><span class="n">bd</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">SINGLETONS</span><span class="p">.</span><span class="na">getSingleton</span><span class="p">(</span><span class="n">beanName</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//if it is prototype, construct new one every time.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getScope</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="p">.</span><span class="na">SCOPE_PROTOTYPE</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">createBean</span><span class="p">(</span><span class="n">bd</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;UNKNOWN Definition!&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">registerBeanDefinition</span><span class="p">(</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">DEFINITIONS</span><span class="p">.</span><span class="na">registerBeanDefinition</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">(),</span><span class="w"> </span><span class="n">bd</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="nf">createBean</span><span class="p">(</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//new Bean</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">Class</span><span class="w"> </span><span class="n">clazz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Class</span><span class="p">.</span><span class="na">forName</span><span class="p">(</span><span class="n">bd</span><span class="p">.</span><span class="na">getClazz</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="n">clazz</span><span class="p">.</span><span class="na">getConstructor</span><span class="p">().</span><span class="na">newInstance</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">ClassNotFoundException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;Not found Bean[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">Exception</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">&#34;New Bean[&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">bd</span><span class="p">.</span><span class="na">getId</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">&#34;] failed&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Junit test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">BeanFatoryTest</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testPrototype</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//new Bean factory</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">DefaultBeanFactory</span><span class="w"> </span><span class="n">bf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">DefaultBeanFactory</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//new Bean definition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">BeanDefinition</span><span class="w"> </span><span class="n">bd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">BeanDefinition</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bd</span><span class="p">.</span><span class="na">setId</span><span class="p">(</span><span class="s">&#34;bean&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bd</span><span class="p">.</span><span class="na">setScope</span><span class="p">(</span><span class="n">BeanDefinition</span><span class="p">.</span><span class="na">SCOPE_PROTOTYPE</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bd</span><span class="p">.</span><span class="na">setClazz</span><span class="p">(</span><span class="n">HelloImpl2</span><span class="p">.</span><span class="na">class</span><span class="p">.</span><span class="na">getName</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">bf</span><span class="p">.</span><span class="na">registerBeanDefinition</span><span class="p">(</span><span class="n">bd</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">bf</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;bean&#34;</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">bf</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;bean&#34;</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>We could define <em>prototype</em> in xml:</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span>  <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter3.bean.Printer&#34;</span> <span class="na">scope=</span><span class="s">&#34;prototypes&#34;</span><span class="nt">/&gt;</span>
</span></span></code></pre></div><h3 id="bean-scopes-in-web-application">Bean Scopes in Web application</h3>
<h4 id="1-request">1. request</h4>
<blockquote>
<p>In a web application, one instance of the bean is created for each
request.</p>
</blockquote>
<h4 id="2-session">2. session</h4>
<blockquote>
<p>In a web application, one instance of the bean is created for each session.</p>
</blockquote>
]]></description></item><item><title>4.1 Resource</title><link>https://blog.terryx.com/posts/2016-01-21-41-resource/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-21-41-resource/</guid><description><![CDATA[<h3 id="resource">Resource</h3>
<h4 id="1-resource-api">1. Resource API</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">interface</span> <span class="nc">InputStreamSource</span><span class="w"> </span><span class="p">{</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">InputStream</span><span class="w"> </span><span class="nf">getInputStream</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">interface</span> <span class="nc">Resource</span><span class="w"> </span><span class="kd">extends</span><span class="w"> </span><span class="n">InputStreamSource</span><span class="w"> </span><span class="p">{</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">exists</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">isReadable</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">boolean</span><span class="w"> </span><span class="nf">isOpen</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">URL</span><span class="w"> </span><span class="nf">getURL</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">URI</span><span class="w"> </span><span class="nf">getURI</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">File</span><span class="w"> </span><span class="nf">getFile</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">long</span><span class="w"> </span><span class="nf">contentLength</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="kt">long</span><span class="w"> </span><span class="nf">lastModified</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">Resource</span><span class="w"> </span><span class="nf">createRelative</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">relativePath</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">;</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">String</span><span class="w"> </span><span class="nf">getFilename</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">String</span><span class="w"> </span><span class="nf">getDescription</span><span class="p">();</span><span class="w">  
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>
<p><strong><em>InputStreamSource</em>:</strong></p>
</li>
<li>
<p><em><strong>getInputStream</strong></em>: Return new <em>java.io.InputStream</em> which needs close after used.</p>
</li>
<li>
<p><strong><em>Resource</em> extends <em>InputStreamSource</em>:</strong></p>
</li>
<li>
<p><em><strong>exists</strong></em>: Resource exists?</p>
</li>
<li>
<p><em><strong>isReadable</strong></em>: Resource readable?</p>
</li>
<li>
<p><em><strong>isOpen</strong></em>: Resource open?</p>
</li>
<li>
<p><em><strong>getURL</strong></em>: <em>java.util.URL</em>.</p>
</li>
<li>
<p><em><strong>getURI</strong></em>: <em>java.util.URI</em>.</p>
</li>
</ul>
<blockquote>
<p>URIs identify and URLs locate; however, locators are also identifiers, so every URL is also a URI, but there are URIs which are not URLs.</p>
</blockquote>
<ul>
<li><em><strong>getFile</strong></em>: <em>java.io.File</em>.</li>
<li><em><strong>contentLength</strong></em>: Resource length.</li>
<li><strong>lastModified_</strong>: Modified date.</li>
<li><em><strong>createRelateive</strong></em>: create file in Resource.</li>
<li><em><strong>getFilename</strong></em>: ONLY return <strong>file path</strong>.</li>
<li><em><strong>getDescription</strong></em> return <strong>full file path</strong>.</li>
</ul>
]]></description></item><item><title>4.2 Using Resource</title><link>https://blog.terryx.com/posts/2016-01-22-42--using-resource/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-22-42--using-resource/</guid><description><![CDATA[<h3 id="using-resource">Using Resource</h3>
<h4 id="1-bytearrayresource">1. ByteArrayResource</h4>
<p>Junit test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.junit.Test</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.ByteArrayResource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.Resource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ResourceTest</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testByteArraryResorce</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ByteArrayResource</span><span class="p">(</span><span class="s">&#34;Hello World!&#34;</span><span class="p">.</span><span class="na">getBytes</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">dumpStream</span><span class="p">(</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">InputStream</span><span class="w"> </span><span class="n">inputStream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">inputStream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getInputStream</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="kt">byte</span><span class="w"> </span><span class="o">[]</span><span class="w"> </span><span class="n">descByte</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="o">[</span><span class="n">inputStream</span><span class="p">.</span><span class="na">available</span><span class="p">()</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">inputStream</span><span class="p">.</span><span class="na">read</span><span class="p">(</span><span class="n">descByte</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="p">(</span><span class="n">descByte</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">IOException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">e</span><span class="p">.</span><span class="na">printStackTrace</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w"> </span><span class="k">finally</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">try</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="n">inputStream</span><span class="p">.</span><span class="na">close</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">IOException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="n">e</span><span class="p">.</span><span class="na">printStackTrace</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><strong>NOTE:</strong> <em><strong>ByteArrayResource</strong></em> can be used repeatedly, because <em><strong>isOpen()</strong></em> always returns <em>false</em>.</p>
<h4 id="2-inputstreamresource">2. InputStreamResource:</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testInputStreamResource</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ByteArrayInputStream</span><span class="w"> </span><span class="n">byteArrayInputStream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ByteArrayInputStream</span><span class="p">(</span><span class="s">&#34;Hello World!&#34;</span><span class="p">.</span><span class="na">getBytes</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">InputStreamResource</span><span class="p">(</span><span class="n">byteArrayInputStream</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><strong>NOTE:</strong> <em><strong>InputStreamResource</strong></em> can be used only one time, because <em><strong>isOpen()</strong></em> always returns <em>true</em>.</p>
<h4 id="3-filesystemresource">3. FileSystemResource:</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testFileResource</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">File</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">File</span><span class="p">(</span><span class="s">&#34;d:/test.txt&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">FileSystemResource</span><span class="p">(</span><span class="n">file</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><strong>NOTE:</strong> <em><strong>FileSystemResource</strong></em> can be used repeatedly, because <em><strong>isOpen()</strong></em> always returns <em>false</em>.</p>
<h4 id="4-classpathresource">4. ClassPathResource:</h4>
<p><em><strong>ClassPathResource</strong></em> replaces <em><strong>Class</strong></em> and <em><strong>ClassLoader</strong></em> to give a uniform implement. The resource can be used repeatedly, because <em><strong>isOpen()</strong></em> always returns <em>false</em>.</p>
<p>Here are three constructors in <em><strong>ClassPathResource</strong></em>:</p>
<ul>
<li><em><strong>public ClassPathResource(String path)</strong></em>: using default <em><strong>ClassLoader</strong></em> to load resource.</li>
<li><em><strong>public ClassPathResource(String path, ClassLoader classLoader)</strong></em>: using specified <em><strong>ClassLoader</strong></em> to load path resource.</li>
<li><strong>_ public ClassPathResource(String path, Class<?> clazz)_</strong>: using <em>Class</em> path to load resource.</li>
</ul>
<blockquote>
<p>For example, if the Class path is “cn.javass.spring.ResourceTest”, the path is “cn/javass/spring/ResourceTest”.</p>
</blockquote>
<ol>
<li><em><strong>public ClassPathResource(String path)</strong></em>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testClasspathResourceBydefaultClassLoader</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><ol>
<li><em><strong>public ClassPathResource(String path, ClassLoader classLoader)</strong></em>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testClasspathResourceByClassLoader</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ClassLoader</span><span class="w"> </span><span class="n">classLoader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">getClass</span><span class="p">().</span><span class="na">getClassLoader</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">classLoader</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><ol>
<li><strong>_ public ClassPathResource(String path, Class<?> clazz)_</strong>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testClasspathResourceByClass</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Class</span><span class="w"> </span><span class="n">clazz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">getClass</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">clazz</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource1</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource1</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource1</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">(</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">getClass</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource2</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource2</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource2</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource1</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>If not provide the full path, it will search in the <em><strong>resource</strong></em> folder. If not found in the <em><strong>resource</strong></em> folder, it will search in other package folders.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">classpathResourceTestFromJar</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">(</span><span class="s">&#34;overview.html&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;path:&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getURL</span><span class="p">().</span><span class="na">getPath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h3 id="5-urlresource">5. UrlResource:</h3>
<p><em><strong>isOpen()</strong></em> always return <em>false</em>. Supporting three ways to load resources:</p>
<ul>
<li><strong>http</strong></li>
<li><strong>ftp</strong></li>
<li><strong>file:</strong> For example, <strong>new <em>UrlResource</em>(“<em>file:d:/test.txt</em>“)</strong>.</li>
</ul>
<h3 id="6-servletcontextresource">6. ServletContextResource:</h3>
<p>To simplize the <em><strong>ServletContext</strong></em> of servlet.</p>
<h3 id="7-vfsresource">7. VfsResource:</h3>
<p>JBoss AS is now provide on <a href="http://wildfly.org/downloads/">http://wildfly.org/downloads/</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testVfsResourceForRealFileSystem</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//New virtual path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">VirtualFile</span><span class="w"> </span><span class="n">home</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">VFS</span><span class="p">.</span><span class="na">getChild</span><span class="p">(</span><span class="s">&#34;/home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//Mapping physical path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">VFS</span><span class="p">.</span><span class="na">mount</span><span class="p">(</span><span class="n">home</span><span class="p">,</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RealFileSystem</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">File</span><span class="p">(</span><span class="s">&#34;d:&#34;</span><span class="p">)));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="c1">//Load resource from virtual path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">VirtualFile</span><span class="w"> </span><span class="n">virtualFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">home</span><span class="p">.</span><span class="na">getChild</span><span class="p">(</span><span class="s">&#34;test.txt&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">VfsResource</span><span class="p">(</span><span class="n">virtualFile</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="n">dumpStream</span><span class="p">(</span><span class="n">resource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">resource</span><span class="p">.</span><span class="na">getFile</span><span class="p">().</span><span class="na">getAbsolutePath</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">isOpen</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>]]></description></item><item><title>4.3 Access Resource</title><link>https://blog.terryx.com/posts/2016-01-22-43--access-resource/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-01-22-43--access-resource/</guid><description><![CDATA[<h3 id="access-resource">Access Resource</h3>
<h4 id="1-resourceloader">1. ResourceLoader</h4>
<p>Spring has a <em><strong>DefaultResourceLoader</strong></em> which can return <em><strong>ClassPathResource</strong></em>, <em><strong>UrlResource</strong></em>, and <em><strong>ServletContextResourceLoader</strong></em> which extends all functions of <em><strong>DefaultResourceLoader</strong></em>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">testResourceLoad</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">ResourceLoader</span><span class="w"> </span><span class="n">loader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">DefaultResourceLoader</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">loader</span><span class="p">.</span><span class="na">getResource</span><span class="p">(</span><span class="s">&#34;classpath:cn/javass/spring/chapter4/test.txt&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertEquals</span><span class="p">(</span><span class="n">ClassPathResource</span><span class="p">.</span><span class="na">class</span><span class="p">,</span><span class="w"> </span><span class="n">resource</span><span class="p">.</span><span class="na">getClass</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>In <em><strong>ApplicationContext</strong></em> also can implement <em><strong>ResourceLoader</strong></em>:</p>
<ul>
<li><em><strong>ClassPathXmlApplicationContext</strong></em></li>
<li><em><strong>FileSystemXmlApplicationContext</strong></em></li>
<li><em><strong>WebApplicationContext</strong></em></li>
</ul>
<h4 id="2-resourceloaderaware">2. ResourceLoaderAware</h4>
<p>Injection via <em><strong>ApplicationContext</strong></em>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.context.ResourceLoaderAware</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.ResourceLoader</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ResourceBean</span><span class="w"> </span><span class="kd">implements</span><span class="w"> </span><span class="n">ResourceLoaderAware</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">ResourceLoader</span><span class="w"> </span><span class="n">resourceLoader</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setResourceLoader</span><span class="p">(</span><span class="n">ResourceLoader</span><span class="w"> </span><span class="n">resourceLoader</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">this</span><span class="p">.</span><span class="na">resourceLoader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">resourceLoader</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">ResourceLoader</span><span class="w"> </span><span class="nf">getResourceLoader</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="n">resourceLoader</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter4.ResourceBean&#34;</span> <span class="nt">/&gt;</span>
</span></span></code></pre></div><p>JUnit test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">test</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="s">&#34;chapter4/resourceLoaderAware.xml&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ResourceBean</span><span class="w"> </span><span class="n">bean</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="n">ResourceBean</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ResourceLoader</span><span class="w"> </span><span class="n">loader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bean</span><span class="p">.</span><span class="na">getResourceLoader</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertTrue</span><span class="p">(</span><span class="n">loader</span><span class="w"> </span><span class="k">instanceof</span><span class="w"> </span><span class="n">ApplicationContext</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h4 id="3-resource-injection">3. Resource Injection</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">org.springframework.core.io.Resource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ResourceBean3</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">private</span><span class="w"> </span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="n">Resource</span><span class="w"> </span><span class="nf">getResource</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">resource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setResource</span><span class="p">(</span><span class="n">Resource</span><span class="w"> </span><span class="n">resource</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">this</span><span class="p">.</span><span class="na">resource</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">resource</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">&#34;resourceBean1&#34;</span> <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter4.ResourceBean3&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;resource&#34;</span> <span class="na">value=</span><span class="s">&#34;cn/javass/spring/chapter4/test.properties&#34;</span><span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/bean&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">&#34;resourceBean2&#34;</span> <span class="na">class=</span><span class="s">&#34;cn.javass.spring.chapter4.ResourceBean3&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;resource&#34;</span> <span class="na">value=</span><span class="s">&#34;classpath:cn/javass/spring/chapter4/test.properties&#34;</span><span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/bean&gt;</span>
</span></span></code></pre></div><p>JUnit test:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">test</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ApplicationContext</span><span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ClassPathXmlApplicationContext</span><span class="p">(</span><span class="s">&#34;chapter4/resourceInject.xml&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ResourceBean3</span><span class="w"> </span><span class="n">resourceBean1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;resourceBean1&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">ResourceBean3</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">ResourceBean3</span><span class="w"> </span><span class="n">resourceBean2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">context</span><span class="p">.</span><span class="na">getBean</span><span class="p">(</span><span class="s">&#34;resourceBean2&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">ResourceBean3</span><span class="p">.</span><span class="na">class</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertTrue</span><span class="p">(</span><span class="n">resourceBean1</span><span class="p">.</span><span class="na">getResource</span><span class="p">()</span><span class="w"> </span><span class="k">instanceof</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="n">Assert</span><span class="p">.</span><span class="na">assertTrue</span><span class="p">(</span><span class="n">resourceBean2</span><span class="p">.</span><span class="na">getResource</span><span class="p">()</span><span class="w"> </span><span class="k">instanceof</span><span class="w"> </span><span class="n">ClassPathResource</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>]]></description></item><item><title>Java Web 系统总结 (一)</title><link>https://blog.terryx.com/posts/2016-02-16-java-web-summary-1/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-02-16-java-web-summary-1/</guid><description><![CDATA[<h3 id="一-jsp-总结">一. JSP 总结</h3>
<h4 id="9个隐含对象及其常用方法-虽然为-java-代码-但是使用-el-表达式完全可以进行调用相关-get-方法">9个隐含对象及其常用方法 (虽然为 Java 代码, 但是使用 <em>EL</em> 表达式完全可以进行调用相关 get 方法):</h4>
<p><strong>1. <em>Request (HttpServletRequest)</em></strong></p>
<ul>
<li><strong>Attribute</strong> 相关:</li>
</ul>
<p>可以理解在 <code>request</code> 作用域范围内的一个存储空间, 实现方法是将键值对放入一个 <code>HashMap</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Object</span><span class="w"> </span><span class="nf">getAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">setAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="n">o</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">removeAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Paramater</strong> 相关:</li>
</ul>
<p>一般用于与 <code>html</code>, <code>jsp</code>页面 及 <code>url</code> 地址传递参数, 仅能传递字符串. 注意: 没有 <code>setParamater</code> 方法.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getParameter</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="nf">getParameterValues</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Cookie</strong> 相关:</li>
</ul>
<p>作为浏览器端持久化储存的一种实现方法, 由服务器加入 <code>response</code> 中, 并在 <code>request</code> 中取出.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Cookie</span><span class="o">[]</span><span class="w"> </span><span class="nf">getCookies</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Session</strong> 相关:</li>
</ul>
<p>作为服务器持久化储存的一种实现方法, 在浏览器第一次访问服务器资源时自动创建.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">HttpSession</span><span class="w"> </span><span class="nf">getSession</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>URI</strong> 路径:</li>
</ul>
<p><strong>应用名称 + 页面路径</strong></p>
<p>比如: <code>/day_15/bbs/bbs.jsp</code> .</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getRequestURI</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>URL</strong> 路径:</li>
</ul>
<p><strong>站点地址 + URI路径</strong></p>
<p>比如: <code>http://localhost:8080/day_15/bbs/bbs.jsp</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">StringBuffer</span><span class="w"> </span><span class="nf">getRequestURL</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>ServletPath</strong> 路径:</li>
</ul>
<p><strong>页面路径</strong></p>
<p>一般用于 <code>filter</code> 进行页面筛选. 比如: <code>/bbs/bbs.jsp</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getServletPath</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>转发地址:</li>
</ul>
<p>可以将 <code>request</code> 转发到另一页面或 <code>Servlet</code>. 注意: <code>path</code> 为 <code>Servlet context path</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">RequestDispatcher</span><span class="w"> </span><span class="nf">getRequestDispatcher</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">path</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>编码问题:</li>
</ul>
<p>对于携带中文作为 <code>Paramater</code> 的 <code>request</code> 在打印时会出现乱码, 所以需要进行编码.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">setCharacterEncoding</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">env</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p><strong>2. <em>Response (HttpServletResponse)</em></strong></p>
<ul>
<li><strong>Cookie</strong> 相关:</li>
</ul>
<p>作为浏览器端持久化储存的一种实现方法, 由服务器加入 <code>response</code> 中, 并在 <code>request</code> 中取出.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">addCookie</span><span class="p">(</span><span class="n">Cookie</span><span class="w"> </span><span class="n">cookie</span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>重定向地址</li>
</ul>
<p>可以跳转到另一页面, 但不转发 <code>request</code>. <code>location</code> 必须包含 <code>application context path</code> 或为 <code>URL</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">sendRedirect</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">location</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p><strong>3. <em>Session (HttpSession)</em></strong></p>
<ul>
<li><strong>Attribute</strong> 相关:</li>
</ul>
<p>和 <code>request</code> 类似, <code>session</code> 也可以携带键值对, 使用方法完全类似.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Object</span><span class="w"> </span><span class="nf">getAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">setAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="n">value</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">removeAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>设置生命周期:</li>
</ul>
<p>从创建到销毁的时间.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">setMaxInactiveInterval</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">interval</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="nf">getMaxInactiveInterval</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>立即销毁 <code>session</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">invalidate</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>JSessionId</strong>:</li>
</ul>
<p>以 <code>JSessionId</code> 为名称存入 <code>Cookie</code> 中.</p>
<p>获取 <code>JSessionId</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getId</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>时间信息:</li>
</ul>
<p>获取创建与最近访问时间:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kt">long</span><span class="w"> </span><span class="nf">getCreationTime</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">long</span><span class="w"> </span><span class="nf">getLastAccessedTime</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>获取 <strong>ServletContext</strong></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">ServletContext</span><span class="w"> </span><span class="nf">getServletContext</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>以上总结的三个隐含对象 <code>request</code> <code>response</code> <code>session</code>, 不只是对于 <code>JSP</code> , 而在整个 <code>Java Web</code> 技术中都极为重要, 对其常用的实现方法必须使用熟练.</p>
<p><strong>4. <em>Application (ServletContext)</em></strong></p>
<ul>
<li><strong>Attribute</strong> 相关:</li>
</ul>
<p>和 <code>request</code> <code>session</code> 类似, <code>Servlet</code> 也可以携带键值对, 使用方法完全类似.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">Object</span><span class="w"> </span><span class="nf">getAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">setAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">Object</span><span class="w"> </span><span class="n">value</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="w"> </span><span class="nf">removeAttribute</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Paramater</strong> 相关:</li>
</ul>
<p>获取在 <code>web.xml</code> 中设置的 <code>Servlet</code> 初始化参数.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getInitParameter</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li><strong>Servlet Context Path</strong></li>
</ul>
<p>为服务器应用的路径名, 如: <code>/day_15</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getContextPath</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p>仅获取应用名称,  如: <code>day_15</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getServletContextName</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p><strong>5. <em>Config (ServletConfig)</em></strong></p>
<p><code>ServletContext</code> 可以覆盖其实现的所有功能.</p>
<ul>
<li><strong>Paramater</strong> 相关:</li>
</ul>
<p>获取在 <code>web.xml</code> 中设置的 <code>Servlet</code> 初始化参数.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getInitParameter</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>获取 <strong>ServletContext</strong>:</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">ServletContext</span><span class="w"> </span><span class="nf">getServletContext</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><ul>
<li>获取应用名称:</li>
</ul>
<p>如: <code>day_15</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="n">String</span><span class="w"> </span><span class="nf">getServletContextName</span><span class="p">();</span><span class="w">
</span></span></span></code></pre></div><p><strong>6. <em>PageContext (PageContext)</em></strong></p>
<ul>
<li>可以获取其他所有隐藏对象 <strong>Request Response Session ServletContext ServletConfig Out Page Exception</strong>:</li>
</ul>
<p>直接调用 <code>get</code> 方法既可. 因为可以调用所有功能, 多用于 <code>EL</code> 表达式.</p>
<p><strong>7. 其余不常用的三个: Out Page Exception</strong>:</p>
<p>以上9个隐藏对象包含 <code>Java Web</code> 最重要的四个作用域:</p>
<ul>
<li><strong>Application</strong>: 作用于整个 Web 应用, 生命周期为 <strong>应用的添加到移除</strong>.</li>
<li><strong>Session</strong>: 作用于一次会话, 生命周期为 <strong>浏览器第一次访问生成到生命周期结束自动注销</strong>.</li>
<li><strong>Request</strong>: 作用于一次请求, 生命周期为 <strong>发送请求到请求处理结束</strong>.</li>
<li><strong>Page</strong>: 仅作用于本页面, 无生命周期.</li>
</ul>
]]></description></item><item><title>深入理解 HTTP Session</title><link>https://blog.terryx.com/posts/2016-02-17-http-session-summary/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-02-17-http-session-summary/</guid><description><![CDATA[<blockquote>
<p>转载于 <a href="http://lavasoft.blog.51cto.com/62575/275589">深入理解 HTTP Session</a></p>
</blockquote>
<p>Session 在 web 开发中是一个非常重要的概念, 这个概念很抽象,很难定义,也是最让人迷惑的一个名词, 也是最多被滥用的名字之一, 在不同的场合,session一次的含义也很不相同. 这里只探讨 HTTP Session.</p>
<p>为了说明问题,这里基于 Java Servlet 理解 Session 的概念与原理,这里所说 Servlet 已经涵盖了 JSP 技术,因为 JSP 最终也会被编译为 Servlet,两者有着相同的本质.</p>
<p>在 Java 中, HTTP 的 Session 对象用 <code>javax.servlet.http.HttpSession</code> 来表示.</p>
<ol>
<li>概念: Session 代表服务器与浏览器的一次会话过程, 这个过程是连续的, 也可以时断时续的. 在 Servlet 中, session 指的是 HttpSession 类的对象, 这个概念到此结束了, 也许会很模糊, 但只有看完本文,才能真正有个深刻理解.</li>
<li>Session 创建的时间是:</li>
</ol>
<p>一个常见的误解是以为 session 在有客户端访问时就被创建, 然而事实是直到某 server 端程序调用 <code>HttpServletRequest.getSession(true)</code> 这样的语句时才被创建,注意如果JSP没有显示的使用 <code>&lt;% @page session=&quot;false&quot;%&gt;</code> 关闭 session, <strong>则 JSP 文件在编译成 Servlet 时将会自动加上这样一条语句 <code>HttpSession session = HttpServletRequest.getSession(true)</code>; 这也是JSP中隐含的 session对象的来历.</strong></p>
<p>由于 session 会消耗内存资源, 因此, 如果不打算使用 session, 应该在所有的 JSP 中关闭它.</p>
<p>引申:</p>
<ul>
<li>访问 <code>*.html</code> 的静态资源因为不会被编译为 Servlet, 也就不涉及 session 的问题.</li>
<li>当 JSP 页面没有显式禁止 session 的时候, 在打开浏览器第一次请求该 jsp 的时候, 服务器会自动为其创建一个 session, 并赋予其一个 sessionID, 发送给客户端的浏览器. 以后客户端接着请求本应用中其他资源的时候, 会自动在请求头上添加:
<code>Cookie:JSESSIONID</code> = 客户端第一次拿到的 session ID
这样, 服务器端在接到请求时候, 就会收到 session ID, 并根据 ID 在内存中找到之前创建的 session 对象, 提供给请求使用. 这也是 session 使用的基本原理 —- 搞不懂这个, 就永远不明白session的原理.</li>
</ul>
<ol start="3">
<li>Session删除的时间是:</li>
</ol>
<ul>
<li>Session 超时: 超时指的是连续一定时间服务器没有收到该 Session 所对应客户端的请求,并且这个时间超过了服务器设置的 Session 超时的最大时间.</li>
<li>程序调用 <code>HttpSession.invalidate()</code></li>
<li>服务器关闭或服务停止</li>
</ul>
<ol start="4">
<li>session 存放在哪里: 服务器端的内存中. 不过 session 可以通过特殊的方式做持久化管理.</li>
<li>session 的 id 是从哪里来的, sessionID 是如何使用的: 当客户端第一次请求 session 对象时候, 服务器会为客户端创建一个 session, 并将通过特殊算法算出一个 session 的 ID, 用来标识该session对象, 当浏览器下次 (session 继续有效时) 请求别的资源的时候, 浏览器会偷偷地将sessionID放置到请求头中, 服务器接收到请求后就得到该请求的 sessionID, 服务器找到该 id 的 session 返还给请求者 (Servlet) 使用. 一个会话只能有一个 session 对象, <strong>对 session 来说是只认 id 不认人</strong>.</li>
<li>session 会因为浏览器的关闭而删除吗？</li>
</ol>
<p>不会, session 只会通过上面提到的方式去关闭.
7. 同一客户端机器多次请求同一个资源, session 一样吗？</p>
<p>一般来说,每次请求都会新创建一个 session.</p>
<p>其实, 这个也不一定的, 总结下: <strong>对于多标签的浏览器 (比如 Chrome 浏览器) 来说, 在一个浏览器窗口中, 多个标签同时访问一个页面, session是一个. 对于多个浏览器窗口之间, 同时或者相隔很短时间访问一个页面, session是多个的, 和浏览器的进程有关. 对于一个同一个浏览器窗口, 直接录入url访问同一应用的不同资源, session是一样的.</strong>
8. session 是一个容器,可以存放会话过程中的任何对象.
9. session 因为请求 (request对象) 而产生, 同一个会话中多个 request 共享了一个 session 对象, 可以直接从请求中获取到 session 对象.
10. <strong>其实, session 的创建和使用总在服务端, 而浏览器从来都没得到过 session 对象.</strong> 但浏览器可以请求 Servlet (jsp 也是 Servlet) 来获取 session 的信息. 客户端浏览器真正紧紧拿到的是 session ID, 而这个对于浏览器操作的人来说, 是不可见的, 并且用户也无需关心自己处于哪个会话过程中.</p>
]]></description></item><item><title>用 Redis 实现分布式锁 与 实现任务队列</title><link>https://blog.terryx.com/posts/2016-04-27-redis/</link><pubDate>Wed, 28 Sep 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/2016-04-27-redis/</guid><description><![CDATA[<blockquote>
<p>转载于 <a href="http://www.cnblogs.com/it-cen/p/4984272.html">用 Redis 实现分布式锁 与 实现任务队列</a></p>
</blockquote>
<p>这一次总结和分享用Redis实现分布式锁 与 实现任务队列 这两大强大的功能. 先扯点个人观点, 之前我看了一篇博文说博客园的文章大部分都是分享代码, 博文里强调说分享思路比分享代码更重要 (貌似大概是这个意思, 若有误请谅解) , 但我觉得, 分享思路固然重要, 但有了思路, 却没有实现的代码, 那会让人觉得很浮夸的, 在工作中的程序猿都知道, 你去实现一个功能模块, 一段代码, 虽然你有了思路, 但是实现的过程也是很耗时的, 特别是代码调试, 还有各种测试等等. 所以我认为, 思路+代码, 才是一篇好博文的主要核心.</p>
<p>直接进入主题.</p>
<h3 id="一前言">一、前言</h3>
<p>双十一刚过不久, 大家都知道在天猫、京东、苏宁等等电商网站上有很多秒杀活动, 例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时, 会迎来一个用户请求的高峰期, 可能会有几十万几百万的并发量, 来抢这个手机, 在高并发的情形下会对数据库服务器或者是文件服务器应用服务器造成巨大的压力, 严重时说不定就宕机了, 另一个问题是, 秒杀的东西都是有量的, 例如一款手机只有10台的量秒杀, 那么, 在高并发的情况下, 成千上万条数据更新数据库 (例如10台的量被人抢一台就会在数据集某些记录下 减1) , 那次这个时候的先后顺序是很乱的, 很容易出现10台的量, 抢到的人就不止10个这种严重的问题. 那么, 以后所说的问题我们该如何去解决呢？ 接下来我所分享的技术就可以拿来处理以上的问题： 分布式锁 和 任务队列.</p>
<h3 id="二实现思路">二、实现思路</h3>
<h4 id="1redis-实现分布式锁思路">1.Redis 实现分布式锁思路</h4>
<p>思路很简单, 主要用到的 <code>redis</code> 函数是 <code>setnx()</code> , 这个应该是实现分布式锁最主要的函数. 首先是将某一任务标识名 (这里用 <code>Lock:order</code> 作为标识名的例子) 作为键存到 <code>redis</code> 里, 并为其设个过期时间, 如果是还有 <code>Lock:order</code> 请求过来, 先是通过 <code>setnx()</code> 看看是否能将 <code>Lock:order</code> 插入到 redis 里, 可以的话就返回 true, 不可以就返回 false. 当然, 在我的代码里会比这个思路复杂一些, 我会在分析代码时进一步说明.</p>
<h4 id="2redis-实现任务队列">2.Redis 实现任务队列</h4>
<p>这里的实现会用到上面的 <code>Redis</code> 分布式的锁机制, 主要是用到了<code>Redis</code> 里的有序集合这一数据结构. 例如入队时, 通过 <code>zset</code> 的 <code>add()</code> 函数进行入队, 而出对时, 可以用到 <code>zset</code> 的 <code>getScore()</code> 函数. 另外还可以弹出顶部的几个任务.</p>
<p>以上就是实现 分布式锁 和 任务队列 的简单思路, 如果你看完有点模棱两可, 那请看接下来的代码实现.</p>
<h3 id="三代码分析">三、代码分析</h3>
<h4 id="一-先来分析redis分布式锁的代码实现">(一) 先来分析Redis分布式锁的代码实现</h4>
<ul>
<li>(1) 为避免特殊原因导致锁无法释放, 在加锁成功后, 锁会被赋予一个生存时间 (通过 <code>lock</code>方法的参数设置或者使用默认值) , 超出生存时间锁会被自动释放锁的生存时间默认比较短 (秒级) , 因此, 若需要长时间加锁, 可以通过 <code>expire</code> 方法延长锁的生存时间为适当时间, 比如在循环内.</li>
<li>(2) 系统级的锁当进程无论何种原因时出现 crash 时, 操作系统会自己回收锁, 所以不会出现资源丢失, 但分布式锁不用, 若一次性设置很长时间, 一旦由于各种原因出现进程crash 或者其他异常导致unlock未被调用时, 则该锁在剩下的时间就会变成垃圾锁, 导致其他进程或者进程重启后无法进入加锁区域.</li>
</ul>
<p>先看加锁的实现代码：这里需要主要两个参数, 一个是 <code>$timeout</code>,这个是循环获取锁的等待时间, 在这个时间内会一直尝试获取锁知道超时, 如果为 0, 则表示获取锁失败后直接返回而不再等待；另一个重要参数的 <code>$expire</code>, 这个参数指当前锁的最大生存时间, 以秒为单位的, 它必须大于0, 如果超过生存时间锁仍未被释放, 则系统会自动强制释放. 这个参数的最要作用请看上面的 (1) 里的解释.</p>
<p>这里先取得当前时间, 然后再获取到锁失败时的等待超时的时刻 (是个时间戳), 再获取到锁的最大生存时刻是多少. 这里 redis 的 key 用这种格式：<code>Lock: 锁的标识名</code>, 这里就开始进入循环了, 先是插入数据到redis里, 使用 <code>setnx()</code> 函数, 这函数的意思是, 如果该键不存在则插入数据, 将最大生存时刻作为值存储, 假如插入成功, 则对该键进行失效时间的设置, 并将该键放在 <code>$lockedName</code> 数组里, 返回 true, 也就是上锁成功；如果该键存在, 则不会插入操作了, 这里有一步严谨的操作, 那就是取得当前键的剩余时间, 假如这个时间小于 0, 表示 key 上没有设置生存时间 (key是不会不存在的, 因为前面setnx会自动创建) 如果出现这种状况, 那就是进程的某个实例 setnx 成功后 crash 导致紧跟着的 expire 没有被调用, 这时可以直接设置expire并把锁纳为己用. 如果没设置锁失败的等待时间或者已超过最大等待时间了, 那就退出循环, 反之则隔 <code>$waitIntervalUs</code> 后继续请求. 这就是加锁的整一个代码分析.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 加锁
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  [type]  $name           锁的标识名
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  integer $timeout        循环获取锁的等待超时时间，在此时间内会一直尝试获取锁直到超时，为 0表示失败后直接返回不等待
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  integer $expire         当前锁的最大生存时间(秒)，必须大于 0，如果超过生存时间锁仍未被释放，则系统会自动强制释放
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @param  integer $waitIntervalUs 获取锁失败后挂起再试的时间间隔(微秒)
</span></span></span><span class="line"><span class="cl"><span class="cm">     * @return [type]                  [description]
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="nf">lock</span><span class="p">(</span><span class="n">$name</span><span class="p">,</span><span class="w"> </span><span class="n">$timeout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">,</span><span class="w"> </span><span class="n">$expire</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">15</span><span class="p">,</span><span class="w"> </span><span class="n">$waitIntervalUs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">100000</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">$name</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="c1">//取得当前时间</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$now</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">time</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="c1">//获取锁失败时的等待超时时刻</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$timeoutAt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$now</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">$timeout</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="c1">//锁的最大生存时刻</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$expireAt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$now</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">$expire</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">$redisKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;Lock:{$name}&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="kc">true</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//将rediskey的最大生存时刻存到redis里，过了这个时刻该锁会被自动释放</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">$result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">setnx</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">,</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">$result</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">false</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="c1">//设置key的失效时间</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">expire</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">,</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="c1">//将锁标志放到lockedNames数组里</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">lockedNames</span><span class="o">[</span><span class="n">$name</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//以秒为单位，返回给定key的剩余生存时间</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">$ttl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">ttl</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//ttl小于0 表示key上没有设置生存时间（key是不会不存在的，因为前面setnx会自动创建）</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//如果出现这种状况，那就是进程的某个实例setnx成功后 crash 导致紧跟着的expire没有被调用</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//这时可以直接设置expire并把锁纳为己用</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">$ttl</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">redisString</span><span class="o">-&gt;</span><span class="n">set</span><span class="p">(</span><span class="n">$redisKey</span><span class="p">,</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">$this</span><span class="o">-&gt;</span><span class="n">lockedNames</span><span class="o">[</span><span class="n">$name</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$expireAt</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="cm">/*****循环请求锁部分*****/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//如果没设置锁失败的等待时间 或者 已超过最大等待时间了，那就退出</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">$timeout</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">$timeoutAt</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">microtime</span><span class="p">(</span><span class="kc">true</span><span class="p">))</span><span class="w"> </span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="c1">//隔 $waitIntervalUs 后继续 请求</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">usleep</span><span class="p">(</span><span class="n">$waitIntervalUs</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>]]></description></item></channel></rss>