﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Jeff on Java -随笔分类-Jeff On Java 2008</title><link>http://www.blogjava.net/jeff-lau/category/28613.html</link><description>新年新气象！</description><language>zh-cn</language><lastBuildDate>Wed, 02 Jan 2008 23:45:20 GMT</lastBuildDate><pubDate>Wed, 02 Jan 2008 23:45:20 GMT</pubDate><ttl>60</ttl><item><title>全排列</title><link>http://www.blogjava.net/jeff-lau/archive/2008/01/03/172350.html</link><dc:creator>Jeff Lau</dc:creator><author>Jeff Lau</author><pubDate>Wed, 02 Jan 2008 17:58:00 GMT</pubDate><guid>http://www.blogjava.net/jeff-lau/archive/2008/01/03/172350.html</guid><wfw:comment>http://www.blogjava.net/jeff-lau/comments/172350.html</wfw:comment><comments>http://www.blogjava.net/jeff-lau/archive/2008/01/03/172350.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jeff-lau/comments/commentRss/172350.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jeff-lau/services/trackbacks/172350.html</trackback:ping><description><![CDATA[<p>摘要：全排列是组合数学中的基本问题。求全排列有很多方法，比如：递归算法、字典顺序法、递增/递减进位制数法和邻位对换法等。本文就在Java、JUnit4平台中，采用测试驱动开发方法，通过实现全排列，来学习Java SE 5中的泛化编程。</p> <p>关键字：全排列 Java JUnit 测试驱动开发 泛化</p> <p>首先写个测试</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_2.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="110" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb.png" width="455" border="0"></a> </p> <p>以最快的方式，通过编译，并让测试通过。</p> <p>在eclipse中通过使用快捷键 Ctrl + 1 ，可以快速生成Stob。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_4.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="413" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_1.png" width="599" border="0"></a> </p> <p>编译通过，测试通过。</p> <p>发现问题：(task list）</p> <ul> <li>length方法中的6是怎么来的？  <li>排列中的元素可不仅仅是String  <li>排列中的元素个数，很有可能不是3个。  <li>获取排列中的元素</li></ul> <p>重构代码。</p> <p>&nbsp;</p> <p><strong>排列中的元素个数，很有可能不是3个。</strong></p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_8.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="45" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_3.png" width="383" border="0"></a> </p> <p>采用了Java SE 5中最新的特性：可变参数。vararg。这样可以传入任意个元素，或一个元素数组。然后，并重命名了参数。</p> <p>&nbsp;</p> <p><strong>排列中的元素可不仅仅是String</strong></p> <p>修改测试代码</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_10.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="33" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_4.png" width="611" border="0"></a> </p> <p>出现了编译错误。这次Ctrl + 1 不会自动解决问题。修改Arrangement类。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_12.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="60" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_5.png" width="355" border="0"></a> </p> <p>&nbsp;</p> <p><strong>获取排列中的元素</strong></p> <p>在测试testArrange中加入代码：</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_14.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="18" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_6.png" width="302" border="0"></a> </p> <p>Ctrl + 1 。并改之。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_16.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="76" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_7.png" width="347" border="0"></a> </p> <p>测试失败。加入字段。并改get方法和构造函数。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_20.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="161" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_9.png" width="324" border="0"></a> </p> <p>增加测试用例</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_22.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="37" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_10.png" width="390" border="0"></a> </p> <p>&nbsp;</p> <p><strong>length方法中的6是怎么来的？</strong></p> <p>6表示：传入3个元素，就有六种排列方式。再看看Arrangement类的职责？Arrangement表示的应该是一个排列，而对于全排列来说，需要一个新的类来表示，取名为：AllArrangement。</p> <p>所以修改测试，修改length方法。length方法返回的就是，elements.length。</p> <p>&nbsp;</p> <p>还需要Arrangement类实现什么功能？暂时还不清楚，这最好问AllArrangement类。编写AllArrangement类的测试。</p> <p>注意：当时为了方便，把测试类命名为TestArrange，现重命名为：TestArrangement。</p> <p>&nbsp;</p> <p><strong>AllArrangement</strong></p> <p>编写测试</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_24.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="142" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_11.png" width="718" border="0"></a> </p> <p>生成Stob类和方法</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_26.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="210" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_12.png" width="476" border="0"></a> </p> <p>测试通过。</p> <p>&nbsp;</p> <p>注意：Arrangement类型，由于没使用泛型，编译器出现了警告。Ctrl + 1 变为Arrangement&lt;?&gt;, </p> <p><strong>Arrangement和Arrangement&lt;?&gt;有什么区别？</strong></p> <p>如果Arrangement类存在下面的方法：</p> <p>public set(int index, E element) {...}</p> <p>如果参数是Arrangement，就可以调用这个方法，如果是Arrangement&lt;?&gt;就不能调用。因为element的类型为?，<strong>无法把一个对象传给？类型的参数</strong>。</p> <p>这个方法中，不需要更改Arrangement中的元素，取Arrangement&lt;?&gt;类型作为arrangement的参数，刚好。</p> <p>&nbsp;</p> <p>任务列表：</p> <ul> <li>如何求得全排列的元素个数？  <li>AllArrange应该实现Iterable接口。</li></ul> <p>&nbsp;</p> <p><strong>如何求得全排列的元素个数？</strong></p> <p>6=3！只要有个求阶乘的函数，就可以了。因为对求阶乘的方法，我很熟悉，我认为我不会写错，就没写测试了。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_28.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="363" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_13.png" width="509" border="0"></a> </p> <p>&nbsp;</p> <p>AllArrange应该实现Iterable接口。</p> <p>写测试。</p> <p>Arrangement的判等</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_30.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_14.png" width="595" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_32.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="22" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_15.png" width="638" border="0"></a> </p> <p>增加toString方法。toString只是用来更加直观的显示，没必要测试。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image68.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="95" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image68_thumb.png" width="373" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image71.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="26" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image71_thumb.png" width="647" border="0"></a> </p> <p>元素顺序没有错。增加equals方法。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image74.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="344" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image74_thumb.png" width="572" border="0"></a> </p> <p>判等要考虑的有两个：</p> <ul> <li>与null对象判等  <li>与非同类对象判等</li></ul> <p>&nbsp;</p> <p>再回到TestAllArrangement类。用字典顺序法去迭代排列。</p> <ul> <li>hasNext == Arrangement.isNotMax  <li>next = Arrangement.next</li></ul> <p><strong>hasNext </strong></p>排列 54321(12345 五个元素的排列)是最大。  <p>测试</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image77.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="91" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image77_thumb.png" width="632" border="0"></a> </p> <p>这里用到了自动装箱。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image86.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="142" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image86_thumb.png" width="545" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image83.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="19" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image83_thumb.png" width="432" border="0"></a> </p> <p>改变了类型参数。</p> <p>增加测试用例</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image89.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="94" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image89_thumb.png" width="632" border="0"></a> </p> <p>&nbsp;</p> <p><strong>next</strong></p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image92.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="61" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image92_thumb.png" width="305" border="0"></a> </p> <p>21354的下一个是21435</p> <p>步骤：</p> <ol> <li>找到5。从右往左，第一个大值  <li>找到4。从5开始往右，大于3的最小数  <li>交换3和4. 变成：21453  <li>把4右边的元素排序。</li></ol> <p>&nbsp;</p> <p>找到5</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image95.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="115" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image95_thumb.png" width="654" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image98.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="151" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image98_thumb.png" width="478" border="0"></a> </p> <p>isMax方法和lastTop方法很相似，更改isMax。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image101.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="70" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image101_thumb.png" width="287" border="0"></a> </p> <p>&nbsp;</p> <p>找到4</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image104.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="85" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image104_thumb.png" width="691" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image107.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="163" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image107_thumb.png" width="972" border="0"></a> </p> <p>交换34</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_42.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="91" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_2.png" width="454" border="0"></a> </p> <p>这里又用了一个新的类型变量T。由于这么简单的函数，就不写测试了。</p> <p> 排序，用Arrays.sort简单解决。</p> <p>&nbsp;</p> <p>next</p> <p>测试</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_62.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="82" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_8.png" width="947" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_64.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="166" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_20.png" width="582" border="0"></a> </p> <p>保证原Arrangement不变</p> <p>&nbsp;</p> <p>TestAllArrangement</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_66.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="156" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_30.png" width="752" border="0"></a> </p> <p>&nbsp;</p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_68.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="450" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_31.png" width="402" border="0"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_70.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="337" alt="image" src="http://www.blogjava.net/images/blogjava_net/jeff-lau/WindowsLiveWriter/3a817b821159_E783/image_thumb_32.png" width="703" border="0"></a> </p> <p>还有：</p> <ul> <li>Arrangement的个数不能太多</li> <li>Arrangement中的元素不能重复</li> <li>AllArrangement中的迭代器iterator应该用Singleton(单例)模式</li> <li>迭代器next方法返回的是Arrangement&lt;?&gt;</li> <li>remove方法</li></ul> <p>&nbsp;</p> <p>代码缺少的还有注释。</p> <p>最终的源代码下载地址：<a title="http://www.blogjava.net/Files/jeff-lau/arrangement.zip" href="http://www.blogjava.net/Files/jeff-lau/arrangement.zip">http://www.blogjava.net/Files/jeff-lau/arrangement.zip</a></p><img src ="http://www.blogjava.net/jeff-lau/aggbug/172350.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jeff-lau/" target="_blank">Jeff Lau</a> 2008-01-03 01:58 <a href="http://www.blogjava.net/jeff-lau/archive/2008/01/03/172350.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>