??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧洲国产经精品香蕉网,精品久久久久久亚洲综合网,国产成人亚洲精品电影http://www.tkk7.com/ArcticOcean/archive/2010/09/01/330469.htmlCool JazzCool JazzTue, 31 Aug 2010 16:19:00 GMThttp://www.tkk7.com/ArcticOcean/archive/2010/09/01/330469.htmlhttp://www.tkk7.com/ArcticOcean/comments/330469.htmlhttp://www.tkk7.com/ArcticOcean/archive/2010/09/01/330469.html#Feedback10http://www.tkk7.com/ArcticOcean/comments/commentRss/330469.htmlhttp://www.tkk7.com/ArcticOcean/services/trackbacks/330469.html         像每个技术h员一P我也遇到了职业迷茫期?br />          在一个半大不的公司做研发,学历比本U高些,技术自认ؓ可以Q也许有Zq么认ؓ吧)。时间过了一q。在一个开发兼除了销售什么都q的名字换了又换的部门。这是大体情况?br />          公司q可以,得上不错。我认ؓ公司的文化,人员l构Q还不错。我也比较认同。只是我所在的部门Q由于偏重于目Q和销售,现场支持接触?比较多?br />          部门的情况大体是q样Q研发、测试、支持和q维全部都有Q部门分工不是很明确。近一q换了两ơ名Uͼ负责我们的一把手换了Q原因我猜可能是Q但不做妄论Q故此不谈)。我的老大是个大牛Qjava、VB、VC、net、ajax{。什么都会,数据库可能差点,但通常用的不在话下。只是老大在管理上既无建树。虽然如此,他也是我们部门的中uQ没有他Q估计部门都q行不v来。在最q一ơ部门变动后Q正在{理中?br />          老大好,没有一Ҏ子。和他一起交没有一点压力。我很喜Ƣ这个。作为技术h员,我没有过人的口才。这也是我认为,没有得到老大的上司(以前的,做销售的Q重视或?#8220;赏识”的原因吧。没有敢和领导做很多交流?br />         在大的公司政{下Q部门随着变动Q一个比我后来的子Q靠着他四处ؕ谈的口才Q坐上了“研发l理”的位子。当时我也有ZQ只是我在ؓ政策房手l,紧接着又ؓl婚忙,几乎无暇估计q点升值机会。再加上老大上司“看h听说”的看人本领,和老大一起定了他做。不q说实话Q他很能“?#8221;Q只是很多话Q你不仔l回想的话,很可能就认ؓ是真的。经怸说一变。刚来时很我搞的很好Q工作中也是能忽悠就忽悠q去。有时也见他加班。尤其是在要升职的那D|间?br />         做上研发l理后,也是按着原来的的无管理\子,对现场的问题能拖久拖。现在就着上l部门培训梳理的q程Q对我仗势压人。哎Q谁让我比他先来Q比他。。。不说他了?br />         相比他而言Q我需要学习的地方Q一是口才,当然不能学他不诚实的“忽悠”Q要善于和h沟通交;诚信是一个h立h的根本。h可以诚实Q但一定要灉|Q否则就是传说中?#8220;?#8221;Q二是善于抓Z。和领导搞关pR搞关系q点我不在行Q更别提拍马屁了。说实话Q谁也能做,只是在我的hDQ和性格上说Q我不愿意去那样做。前朝的太监Q当今的宰相。也是现在常有的现象。只是我不愿意去做。还是学和别人沟通交的Q在善意的基上。俗话说?害h之心不可有,防h之心不可无?br />         其实Q我也想q离职。但对于q样一个公司,有点舍不得。还׃Q我老婆q没有毕业,没有正式获得力_合同。我不能在她q没有稳定之Ӟ开始离职另选它路。还有我来这个公司,也是׃我的某些贵hQ我不想背负他们。在她稳定之后,我在考虑q个吧?br />         面对qӞq样去解冻I 职业q-->分析原因-->以史为鉴-->求解-->明确方向-->行动
        ~程不是最l目的,语言不是万能。在目前的中国,Z能只靠代码吃饭?br />         人生也许是q样Qd一个又一个的烦恼和偶的快乐中度q。在此过E中Q或怽会发玎ͼ哦,长大了?br />       

                                                                                                                                    W于 九月一日晨零时十八?

Cool Jazz 2010-09-01 00:19 发表评论
]]>
HashMap原理、源码、实?/title><link>http://www.tkk7.com/ArcticOcean/archive/2010/08/09/328316.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Mon, 09 Aug 2010 07:14:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/archive/2010/08/09/328316.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/328316.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/archive/2010/08/09/328316.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/328316.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/328316.html</trackback:ping><description><![CDATA[HashMap是一U十分常用的数据l构Q作Z个应用开发h员,对其原理、实现的加深理解有助于更高效地进行数据存取。本文所用的jdk版本?.5?<br /> <br /> <span style="font-size: large"><strong>使用HashMap</strong></span> <br /> <br /> 《Effective JAVA》中认ؓQ?9%的情况下Q当你覆盖了equalsҎ后,请务必覆盖hashCodeҎ。默认情况下Q这两者会采用Object?#8220;原生”实现方式Q即Q?<br /> <br /> <div id="fpvtbj3" class="dp-highlighter"> <div id="9jpdbvd" class="tools">Java代码Q?a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" ></a></div> <ol class="dp-j"> <li><span><span id="5hblvfj" class="keyword">protected</span><span> </span><span id="lxl393v" class="keyword">native</span><span> </span><span id="xx1zfzp" class="keyword">int</span><span> hashCode();   </span></span> <li><span id="pbd3fxd" class="keyword">public</span><span> </span><span id="dxfzb79" class="keyword">boolean</span><span> equals(Object obj) {   </span></span> <li><span>    </span><span id="tvlpbbn" class="keyword">return</span><span> (</span><span id="xb7hjjv" class="keyword">this</span><span> == obj);   </span></span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">protected native int hashCode(); public boolean equals(Object obj) { return (this == obj); } </pre> <br /> <br /> hashCodeҎ的定义用Cnative关键字,表示它是由C或C++采用较ؓ底层的方式来实现的,你可以认为它q回了该对象的内存地址Q而缺省equals则认为,只有当两者引用同一个对象时Q才认ؓ它们是相{的。如果你只是覆盖了equals()而没有重新定义hashCode()Q在dHashMap的时候,除非你用一个与你保存时引用完全相同的对象作为key|否则你将得不到该key所对应的倹{?<br /> <br /> 另一斚wQ你应该量避免使用“可变”的类作ؓHashMap的键。如果你一个对象作为键值ƈ保存在HashMap中,之后又改变了其状态,那么HashMap׃产生混ؕQ你所保存的值可能丢失(管遍历集合可能可以扑ֈQ。可参?em><a target="_blank">http://www.ibm.com/developerworks/cn/java/j-jtp02183/</a></em> <br /> <br /> <span style="font-size: large"><strong>HashMap存取机制</strong></span> <br /> <br /> Hashmap实际上是一个数l和链表的结合体Q利用数l来模拟一个个ӞcM于Bucket SortQ以快速存取不同hashCode的keyQ对于相同hashCode的不同keyQ再调用其equalsҎ从List中提取出和key所相对应的value?<br /> <br /> JAVA中hashMap的初始化主要是ؓinitialCapacity和loadFactorq两个属性赋倹{前者表ChashMap中用来区分不同hash值的keyI间长度Q后者是指定了当hashMap中的元素过多少的时候,开始自动扩容,。默认情况下initialCapacity?6QloadFactor?.75Q它表示一开始hashMap可以存放16个不同的hashCodeQ当填充到第12个的时候,hashMap会自动将其keyI间的长度扩容到32Q以此类推;q点可以从源码中看出来: <br /> <br /> <div id="x99hx9f" class="dp-highlighter"> <div id="vnfprxz" class="bar">Java代码Q?/div> <ol class="dp-j"> <li><span><span id="dz7bltn" class="keyword">void</span><span> addEntry(</span><span id="bxxhh7r" class="keyword">int</span><span> hash, K key, V value, </span><span id="rvlfhxr" class="keyword">int</span><span> bucketIndex) {   </span></span> <li><span>    Entry<K,V> e = table[bucketIndex];   </span> <li><span>        table[bucketIndex] = </span><span id="73n3pvd" class="keyword">new</span><span> Entry<K,V>(hash, key, value, e);   </span></span> <li><span>        </span><span id="txzh7vh" class="keyword">if</span><span> (size++ >= threshold)   </span></span> <li><span>            resize(</span><span id="hxphtbt" class="number">2</span><span> * table.length);   </span></span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); } </pre> <br /> <br /> 而每当hashMap扩容后,内部的每个元素存攄位置都会发生变化Q因为元素的最l位|是其hashCode对keyI间长度取模而得Q,因此resizeҎ中又会调用transfer函数Q用来重新分配内部的元素Q这个过E成为rehashQ是十分消耗性能的,因此在可预知元素的个数的情况下,一般应该避免用缺省的initialCapacityQ而是通过构造函Cؓ其指定一个倹{例如我们可能会惌数据库查询所?000条记录以某个特定字段Q比如IDQؓkey~存在hashMap中,Z提高效率、避免rehashQ可以直接指定initialCapacity?048?<br /> <br /> 另一个值得注意的地ҎQhashMap其keyI间的长度一定ؓ2的Nơ方Q这一点可以从一下源码中看出来: <br /> <div id="fddv999" class="dp-highlighter"> <div id="vjrjdr7" class="tools">Java代码Q?/div> <ol class="dp-j"> <li><span><span id="bvxh73l" class="keyword">int</span><span> capacity = </span><span id="zh7dbvf" class="number">1</span><span>;   </span></span> <li><span id="3rjd3tl" class="keyword">while</span><span> (capacity < initialCapacity)    </span></span> <li><span>    capacity <<= </span><span id="br9vfpp" class="number">1</span><span>;  </span></span> </li> </ol> </div> <pre class="java" style="display: none" name="code">int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; </pre> <br /> <br /> 即我们在构造函C指定的initialCapacity不是2的^ҎQcapacityq是会被赋gؓ2的Nơ方?<br /> <br /> Z么Sun Microsystem的工E师要将hashMap keyI间的长度设?的Nơ方呢?q里参考R.W.Floyedl出的衡量散列思想的三个标准: <br /> <br /> <ul><br /> 一个好的hash法的计应该是非常快的 <br /> 一个好的hash法应该是冲H极化 <br /> 如果存在冲突,应该是冲H均匀?<br /> </ul> <br /> <br /> Z各元素的hashCode保存至长度ؓLength的key数组中,一般采用取模的方式Q即index = hashCode % Length。不可避免的Q存在多个不同对象的hashCode被安排在同一位置Q这是我们qx所谓的“冲突”。如果仅仅是考虑元素均匀化与冲突极小化,g应该Length取ؓ素数Q尽没有明昄理论来支持这一点,但数学家们通过大量的实践得出结论,对素数取模的产生l果的无x要大于其它数字Q。ؓ此,Craig Larman and Rhett Guthrie《Java Performence》中Ҏ也大加抨凅Rؓ了弄清楚q个问题QBruce EckelQThinking in JAVA的作者)专程采访了java.util.hashMap的作者Joshua BlochQƈ他采用q种设计的原因放C|上Q?a target=_blank><em>http://www.roseindia.net/javatutorials/javahashmap.shtml</em></a>Q??<br /> <br /> 上述设计的原因在于,取模q算在包括JAVA在内的大多数语言中的效率都十分低下,而当除数?的Nơ方Ӟ取模q算退化ؓ最单的位运,其效率明显提升(按照Bruce Eckell出的数据,大约可以提升5?倍) 。看看JDK中是如何实现的: <br /> <br /> <div id="vlvv3p3" class="dp-highlighter"> <div id="5r99rjr" class="tools">Java代码Q?/div> <ol class="dp-j"> <li><span><span id="3fhtvnn" class="keyword">static</span><span> </span><span id="pl3dn3h" class="keyword">int</span><span> indexFor(</span><span id="znf1jtt" class="keyword">int</span><span> h, </span><span id="fxh9fxp" class="keyword">int</span><span> length) {   </span></span> <li><span>    </span><span id="zfphjtf" class="keyword">return</span><span> h & (length-</span><span id="n99xjhb" class="number">1</span><span>);   </span></span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">static int indexFor(int h, int length) { return h & (length-1); } </pre> <br /> <br /> 当keyI间长度?的Nơ方Ӟ计算hashCode为h的元素的索引可以用简单的与操作来代替W拙的取模操作!假设某个对象的hashCode?5Q二q制?00011Q,而hashMap采用默认的initialCapacityQ?6Q,那么indexFor计算所得结果将会是100011 & 1111 = 11Q即十进制的3Q是不是恰好?5 Mod 16?<br /> <br /> 上面的方法有一个问题,是它的计算l果仅有对象hashCode的低位决定,而高位被l统屏蔽了;以上面ؓ例,19Q?0011Q?5Q?00011Q?7Q?000011Q等具有相同的l果。针对这个问题, Joshua Bloch采用?#8220;防M性编E?#8221;的解x法,在用各对象的hashCode之前对其q行二次HashQ参看JDK中的源码Q?<br /> <br /> <div id="bf1zttt" class="dp-highlighter"> <div id="jhjt5ph" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="zvffzxz" class="keyword">static</span><span> </span><span id="xv97hjh" class="keyword">int</span><span> hash(Object x) {   </span></span> <li><span>        </span><span id="p3zr79n" class="keyword">int</span><span> h = x.hashCode();   </span></span> <li><span>        h += ~(h << </span><span id="nbtvhhp" class="number">9</span><span>);   </span></span> <li><span>        h ^=  (h >>> </span><span id="7tnnhnn" class="number">14</span><span>);   </span></span> <li><span>        h +=  (h << </span><span id="nttlfx1" class="number">4</span><span>);   </span></span> <li><span>        h ^=  (h >>> </span><span id="drhbjj1" class="number">10</span><span>);   </span></span> <li><span>        </span><span id="53d3hb9" class="keyword">return</span><span> h;   </span></span> <li><span>    }  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">static int hash(Object x) { int h = x.hashCode(); h += ~(h << 9); h ^= (h >>> 14); h += (h << 4); h ^= (h >>> 10); return h; } </pre> <br /> <br /> 采用q种旋{Hash函数的主要目的是让原有hashCode的高位信息也能被充分利用Q且兼顾计算效率以及数据l计的特性,其具体的原理已超Z本文的领域?<br /> <br /> 加快Hash效率的另一个有效途径是编写良好的自定义对象的HashCodeQString的实现采用了如下的计方法: <br /> <br /> <div id="l9r19f9" class="dp-highlighter"> <div id="rnxzhp7" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="lzzbd1z" class="keyword">for</span><span> (</span><span id="xdvnfnx" class="keyword">int</span><span> i = </span><span id="dzjrrb1" class="number">0</span><span>; i < len; i++) {   </span></span> <li><span>h = </span><span id="xd7llvx" class="number">31</span><span>*h + val[off++];   </span></span> <li><span>}   </span> <li><span>hash = h;  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; </pre> <br /> <br /> q种ҎHashCode的计方法可能最早出现在Brian W. Kernighan和Dennis M. Ritchie的《The C Programming Language》中Q被认ؓ是性h比最高的法Q又被称为times33法Q因为C中乘数常量ؓ33QJAVA中改?1Q,实际上,包括List在内的大多数的对象都是用q种Ҏ计算Hash倹{?<br /> <br /> 另一U比较特D的hash法UCؓ布隆qo器,它以牺牲l微_ֺZP换来存储I间的大量节俭,常用于诸如判断用户名重复、是否在黑名单上{等Q可以参考李开复的数学之美pdW?3(<em><a target="_blank">http://googlechinablog.com/2006/08/blog-post.html</a></em>Q?<br /> <br /> <span style="font-size: large"><strong>Fail-Fast机制</strong></span> <br /> <br /> 众所周知QHashMap不是U程安全的集合类。但在某些容错能力较好的应用中,如果你不想仅仅因?%的可能性而去承受hashTable的同步开销Q则可以考虑利用一下HashMap的Fail-Fast机制Q其具体实现如下Q?<br /> <br /> <div id="db99vtd" class="dp-highlighter"> <div id="7vbdxfx" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span>Entry<K,V> nextEntry() {    </span></span> <li><span id="trbvv73" class="keyword">if</span><span> (modCount != expectedModCount)   </span></span> <li><span>    </span><span id="5v99h9v" class="keyword">throw</span><span> </span><span id="5npz99z" class="keyword">new</span><span> ConcurrentModificationException();   </span></span> <li><span>                     ……   </span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); …… } </pre> <br /> <br /> 其中modCount为HashMap的一个实例变量,q且被声明ؓvolatileQ表CZQ何线E都可以看到该变量被其它U程修改的结果(ҎJVM内存模型的优化,每一个线E都会存一份自q工作内存Q此工作内存的内容与本地内存q时时d都同步,因此可能会出现线E间的修改不可见的问题) 。用Iterator开始P代时Q会modCount的赋值给expectedModCountQ在q代q程中,通过每次比较两者是否相{来判断HashMap是否在内部或被其它线E修攏VHashMap的大多数修改Ҏ都会改变ModCountQ参考下面的源码Q?<br /> <div id="flnfndn" class="dp-highlighter"> <div id="jfx73zd" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="9b9h3h7" class="keyword">public</span><span> V put(K key, V value) {   </span></span> <li><span>    K k = maskNull(key);   </span> <li><span>        </span><span id="l39txpf" class="keyword">int</span><span> hash = hash(k);   </span></span> <li><span>        </span><span id="7p9xfp9" class="keyword">int</span><span> i = indexFor(hash, table.length);   </span></span> <li><span>        </span><span id="tfdfzp7" class="keyword">for</span><span> (Entry<K,V> e = table[i]; e != </span><span id="llbt7bb" class="keyword">null</span><span>; e = e.next) {   </span></span> <li><span>            </span><span id="b9l3xhr" class="keyword">if</span><span> (e.hash == hash && eq(k, e.key)) {   </span></span> <li><span>                V oldValue = e.value;   </span> <li><span>                e.value = value;   </span> <li><span>                e.recordAccess(</span><span id="fjt9fzf" class="keyword">this</span><span>);   </span></span> <li><span>                </span><span id="drll7pp" class="keyword">return</span><span> oldValue;   </span></span> <li><span>            }   </span> <li><span>        }   </span> <li><span>        modCount++;   </span> <li><span>        addEntry(hash, k, value, i);   </span> <li><span>        </span><span id="bjj7x9t" class="keyword">return</span><span> </span><span id="3p13dtn" class="keyword">null</span><span>;   </span></span> <li><span>    }  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">public V put(K key, V value) { K k = maskNull(key); int hash = hash(k); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { if (e.hash == hash && eq(k, e.key)) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, k, value, i); return null; }</pre> <br /> <br /> 以putҎZQ每ơ往HashMap中添加元素都会导致modCount自增。其它诸如remove、clearҎ也都包含cM的操作?<br /> 从上面可以看出,HashMap所采用的Fail-Fast机制本质上是一U乐观锁机制Q通过查状态——没有问题则忽略——有问题则抛出异常的方式Q来避免U程同步的开销Q下面给Z个在单线E环境下发生Fast-Fail的例子: <br /> <br /> <div id="nj7pxzx" class="dp-highlighter"> <div id="ftz1lpx" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="pldvxp9" class="keyword">class</span><span> Test {     </span></span> <li><span>    </span><span id="xddfhff" class="keyword">public</span><span> </span><span id="b1bd3lv" class="keyword">static</span><span> </span><span id="9fpzxp3" class="keyword">void</span><span> main(String[] args) {                </span></span> <li><span>        java.util.HashMap<Object,String> map=</span><span id="h7zb9jh" class="keyword">new</span><span> java.util.HashMap<Object,String>();     </span></span> <li><span>       map.put(</span><span id="zl7jjrt" class="keyword">new</span><span> Object(), </span><span id="733hjjv" class="string">"a"</span><span>);     </span></span> <li><span>       map.put(</span><span id="jlnxnhd" class="keyword">new</span><span> Object(), </span><span id="x7zrl9j" class="string">"b"</span><span>);     </span></span> <li><span>       java.util.Iterator<Object> it=map.keySet().iterator();     </span> <li><span>       </span><span id="fbbvp7t" class="keyword">while</span><span>(it.hasNext()){     </span></span> <li><span>           it.next();     </span> <li><span>           map.put(</span><span id="3hx3d9j" class="string">""</span><span>, </span><span id="x1fpx9l" class="string">""</span><span>);          </span></span> <li><span>        System.out.println(map.size());     </span> <li><span>    }     </span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">class Test { public static void main(String[] args) { java.util.HashMap<Object,String> map=new java.util.HashMap<Object,String>(); map.put(new Object(), "a"); map.put(new Object(), "b"); java.util.Iterator<Object> it=map.keySet().iterator(); while(it.hasNext()){ it.next(); map.put("", ""); System.out.println(map.size()); } }</pre> <br /> <br /> q行上面的代码会抛出java.util.ConcurrentModificationExceptionQ因为在q代q程中修改了HashMap内部的元素导致modCount自增。若上面代码中 map.put(new Object(), "b") q句注释掉,E序会顺利通过Q因为此时HashMap中只包含一个元素,l过一ơP代后已到了尾部,所以不会出现问题,也就没有抛出异常的必要了?<br /> 在通常q发环境下,q是采用同步机制。这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在q样的对象,则应该?Collections.synchronizedMap Ҏ?#8220;包装”该映。最好在创徏时完成这一操作Q以防止意外的非同步讉K?<br /> <br /> <span style="font-size: large"><strong>LinkedHashMap</strong></span> <br /> <br /> 遍历HashMap所得到的数据是杂ؕ无章的,q在某些情况下客户需要特定遍历顺序时是十分有用的。比如,q种数据l构很适合构徏 LRU ~存。调?put ?get Ҏ会讉K相应的条目(假定调用完成后它q存在)。putAll Ҏ以指定映的条目集合q代器提供的?值映关pȝ序Qؓ指定映射的每个映关pȝ成一个条目访问。Sun提供的J2SE说明文特别规定M其他Ҏ均不生成条目讉KQ尤Ӟcollection 集合cȝ操作不会影响底层映射的P代顺序?<br /> <br /> LinkedHashMap的实C HashMap 的不同之处在于,前者维护着一个运行于所有条目的双重链接列表。此链接列表定义了P代顺序,该P代顺序通常是集合中元素的插入序。该cd义了header、before与after三个属性来表示该集合类的头与前?#8220;指针”Q其具体用法cM于数据结构中的双链表Q以删除某个元素ZQ?<br /> <br /> <div id="jd7lvd9" class="dp-highlighter"> <div id="7lt3phf" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="rzrtn1j" class="keyword">private</span><span> </span><span id="zn99bvt" class="keyword">void</span><span> remove() {   </span></span> <li><span>       before.after = after;   </span> <li><span>       after.before = before;   </span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">private void remove() { before.after = after; after.before = before; }</pre> <br /> <br /> 实际上就是改变前后指针所指向的元素?<br /> <br /> 昄Q由于增加了l护链接列表的开支,其性能要比 HashMap E逊一{,不过有一点例外:LinkedHashMap的P代所需旉与其的所包含的元素成比例Q而HashMap q代旉很可能开支较大,因ؓ它所需要的旉与其定wQ分配给KeyI间的长度)成比例。一a以蔽之,随机存取用HashMapQ顺序存取或是遍历用LinkedHashMap?<br /> <br /> LinkedHashMapq重写了removeEldestEntryҎ以实现自动清除过期数据的功能Q这在HashMap中是无法实现的,因ؓ后者其内部的元素是无序的。默认情况下QLinkedHashMap中的removeEldestEntry的作用被关闭Q其具体实现如下Q?<br /> <br /> <div id="zx7l3dd" class="dp-highlighter"> <div id="jhrzbj7" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="xdfphxx" class="keyword">protected</span><span> </span><span id="p9pppzp" class="keyword">boolean</span><span> removeEldestEntry(Map.Entry<K,V> eldest) {   </span></span> <li><span>    </span><span id="dz7nhzp" class="keyword">return</span><span> </span><span id="j7r99pz" class="keyword">false</span><span>;   </span></span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; }</pre> <br /> <br /> 可以使用如下的代码覆盖removeEldestEntryQ?<br /> <br /> <div id="rzhjlbd" class="dp-highlighter"> <div id="9bdv9jt" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="x9pxpr3" class="keyword">private</span><span> </span><span id="7pz1vx3" class="keyword">static</span><span> </span><span id="v9npnhz" class="keyword">final</span><span> </span><span id="dr5n9bl" class="keyword">int</span><span> MAX_ENTRIES = </span><span id="drjrrl1" class="number">100</span><span>;   </span></span> <li><span>  </span> <li><span id="lxzp1nx" class="keyword">protected</span><span> </span><span id="t1ztbdd" class="keyword">boolean</span><span> removeEldestEntry(Map.Entry eldest) {   </span></span> <li><span>    </span><span id="plnnpnh" class="keyword">return</span><span> size() > MAX_ENTRIES;   </span></span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">private static final int MAX_ENTRIES = 100; protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_ENTRIES; } </pre> <br /> <br /> 它表C,刚开始,LinkedHashMap中的元素不断增长Q当它内部的元素过MAX_ENTRIESQ?00Q后Q每当有新的元素被插入时Q都会自动删除双链表中最前端Q最旧)的元素,从而保持LinkedHashMap的长度稳定?<br /> <br /> ~省情况下,LinkedHashMap采取的更新策略是cM于队列的FIFOQ如果你惛_现更复杂的更新逻辑比如LRUQ最q最用) {,可以在构造函C指定其accessOrder为trueQ因为的讉K元素的方法(getQ内部会调用一?#8220;钩子”Q即recordAccessQ其具体实现如下Q?<br /> <br /> <div id="b7jtd3r" class="dp-highlighter"> <div id="nbldf1h" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="j3v3jbr" class="keyword">void</span><span> recordAccess(HashMap<K,V> m) {   </span></span> <li><span>    LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;   </span> <li><span>    </span><span id="5vlxfn9" class="keyword">if</span><span> (lm.accessOrder) {   </span></span> <li><span>        lm.modCount++;   </span> <li><span>        remove();   </span> <li><span>        addBefore(lm.header);   </span> <li><span>    }   </span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">void recordAccess(HashMap<K,V> m) { LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; if (lm.accessOrder) { lm.modCount++; remove(); addBefore(lm.header); } }</pre> <br /> <br /> 上述代码主要实现了这L功能Q如果accessOrder被设|ؓtrueQ则每次讉K元素Ӟ都将该元素移至headr的前面,即链表的N。将removeEldestEntry与accessOrder一起用,可以实现最基本的内存缓存,具体代码可参?a target=_blank><em>http://bluepopopo.javaeye.com/blog/180236</em></a>?<br /> <br /> <span style="font-size: large"><strong>WeakHashMap</strong></span> <br /> <br /> 99%的JAVA教材教导我们不要d预JVM的垃圑֛收机Ӟ但JAVA中确实存在着与其密切相关的四U引用:强引用、Y引用、弱引用以及q象引用?<br /> <br /> JAVA中默认的HashMap采用的是采用cM于强引用的强键来理的,q意味着即作ؓkey的对象已l不存在了(指没有Q何一个引用指向它Q,也仍然会保留在HashMap中,在某些情况下Q例如内存缓存)中,q些q期的条目可能会造成内存泄漏{问题?<br /> <br /> WeakHashMap采用的策略是Q只要作为key的对象已l不存在了(出生命周期Q,׃会阻止垃圾收集器清空此条目,即当前机器的内存ƈ不紧张。不q,׃GC是一个优先很低的线E,因此不一定会很快发现那些只具有弱引用的对象,除非你显C地调用它,可以参考下面的例子Q?<br /> <br /> <div id="r9pzjb3" class="dp-highlighter"> <div id="793l9rb" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="nl1bdln" class="keyword">public</span><span> </span><span id="h7xxxhf" class="keyword">static</span><span> </span><span id="rdl393p" class="keyword">void</span><span> main(String[] args) {   </span></span> <li><span>    Map<String, String>map = </span><span id="7f97pzr" class="keyword">new</span><span> WeakHashMap<String, String>();   </span></span> <li><span>    map.put(</span><span id="pdtv9lt" class="keyword">new</span><span> String(</span><span id="rdvvnbd" class="string">"Alibaba"</span><span>), </span><span id="rvnn3fn" class="string">"alibaba"</span><span>);   </span></span> <li><span>    </span><span id="bf9lvxx" class="keyword">while</span><span> (map.containsKey(</span><span id="j9prrt3" class="string">"Alibaba"</span><span>)) {   </span></span> <li><span>        </span><span id="z7dvfvh" class="keyword">try</span><span> {   </span></span> <li><span>            Thread.sleep(</span><span id="7d9rlvf" class="number">500</span><span>);   </span></span> <li><span>         } </span><span id="19jblll" class="keyword">catch</span><span> (InterruptedException ignored) {   </span></span> <li><span>         }   </span> <li><span>         System.out.println(</span><span id="79p93p3" class="string">"Checking for empty"</span><span>);   </span></span> <li><span>         System.gc();   </span> <li><span>    }  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">public static void main(String[] args) { Map<String, String>map = new WeakHashMap<String, String>(); map.put(new String("Alibaba"), "alibaba"); while (map.containsKey("Alibaba")) { try { Thread.sleep(500); } catch (InterruptedException ignored) { } System.out.println("Checking for empty"); System.gc(); } </pre> <br /> <br /> 上述代码输出一ơChecking for empty退ZȝE,意味着GC在最q的一ơ垃圑֛收周期中清除了new String(“Alibaba”),同时WeakHashMap也做Z及时的反应,该键对应的条目删除了。如果将map的类型改为HashMap的话Q由于其内部采用的是强引用机Ӟ因此即GC被显C用,map中的条目依然存在Q程序会不断地打出Checking for empty字样。另外,在用WeakHashMap的情况下Q若是将 <br /> <br /> <div id="lppxrj3" class="dp-highlighter"> <div id="xltdn7t" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span>map.put(</span><span id="7p3ppj3" class="keyword">new</span><span> String(</span><span id="7xzttff" class="string">"Alibaba"</span><span>), </span><span id="xld7hpz" class="string">"alibaba"</span><span>);   </span></span> </li> </ol> </div> <pre class="java" style="display: none" name="code">map.put(new String("Alibaba"), "alibaba"); </pre> <br /> <br /> 改ؓ <br /> <br /> <div id="5rjt9nh" class="dp-highlighter"> <div id="jdxh93d" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span>map.put(</span><span id="rt1jb3r" class="string">"Alibaba"</span><span>, </span><span id="nrrbddf" class="string">"alibaba"</span><span>);   </span></span> </li> </ol> </div> <pre class="java" style="display: none" name="code">map.put("Alibaba", "alibaba"); </pre> <br /> <br /> E序q是会不断输出Checking for empty。这与前面我们分析的WeakHashMap的弱引用机制q不矛盾Q因为JVMZ减小重复创徏和维护多个相同String的开销Q其内部采用了蝇量模式(《JAVA与模式》)Q此时的“Alibaba”是存攑֜帔R池而非堆中的,因此即没有对象指向“Alibaba”Q它也不会被GC回收。弱引用特别适合以下对象Q占用大量内存,但通过垃圾回收功能回收以后很容易重新创建?<br /> <br /> 介于HashMap和WeakHashMap之中的是SoftHashMapQ它所采用的Y引用的策略指的是Q垃圾收集器q不像其攉弱可及的对象一样尽量地攉软可及的对象Q相反,它只在真?“需?#8221; 内存时才攉软可及的对象。Y引用对于垃圾攉器来说是一U?#8220;睁一只眼Q闭一只眼”方式Q即 “只要内存不太紧张Q我׃保留该对象。但是如果内存变得真正紧张了Q我׃L集ƈ处理q个对象?#8221; p一点看Q它其实要比WeakHashMap更适合于实现缓存机制。遗憄是,JAVA中ƈ没有实现相关的SoftHashMapc(Apache和Google提供了第三方的实玎ͼQ但它却是提供了两个十分重要的类java.lang.ref.SoftReference以及ReferenceQueueQ可以在对象应用状态发生改变是得到通知Q可以参考com.alibaba.common.collection.SofthashMap中processQueueҎ的实? <br /> <br /> <div id="rdfxfhz" class="dp-highlighter"> <div id="lhppj1f" class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" >Java代码Q?/a></div> <ol class="dp-j"> <li><span><span id="pt1xrrl" class="keyword">private</span><span> ReferenceQueue queue = </span><span id="j7nnpz9" class="keyword">new</span><span> ReferenceQueue();   </span></span> <li><span>ValueCell vc;   </span> <li><span>Map hash = </span><span id="pjt7xxp" class="keyword">new</span><span> HashMap(initialCapacity, loadFactor);   </span></span> <li><span>……   </span> <li><span id="nj9nfhx" class="keyword">while</span><span> ((vc = (ValueCell) queue.poll()) != </span><span id="l3xxxnf" class="keyword">null</span><span>) {   </span></span> <li><span id="533xpzf" class="keyword">if</span><span> (vc.isValid()) {   </span></span> <li><span>          hash.remove(vc.key);   </span> <li><span>           } </span><span id="tndx7vf" class="keyword">else</span><span> {   </span></span> <li><span>             valueCell.dropped--;   </span> <li><span>           }   </span> <li><span>}   </span> <li><span>}  </span> </li> </ol> </div> <pre class="java" style="display: none" name="code">private ReferenceQueue queue = new ReferenceQueue(); ValueCell vc; Map hash = new HashMap(initialCapacity, loadFactor); …… while ((vc = (ValueCell) queue.poll()) != null) { if (vc.isValid()) { hash.remove(vc.key); } else { valueCell.dropped--; } } }</pre> <br /> <br /> processQueueҎ会在几乎所有SoftHashMap的方法中被调用到QJVM会通过ReferenceQueue的pollҎ通知该对象已l过期ƈ且当前的内存现状需要将它释放,此时我们可以将其从hashMap中剔除。事实上Q默认情况下QAlibaba的MemoryCache所使用的就是SoftHashMap?<br /> <br /> 来源Q?a >http://grunt1223.javaeye.com/blog/544497</a><br /> <img src ="http://www.tkk7.com/ArcticOcean/aggbug/328316.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2010-08-09 15:14 <a href="http://www.tkk7.com/ArcticOcean/archive/2010/08/09/328316.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转蝲QY件开发的一些感?/title><link>http://www.tkk7.com/ArcticOcean/archive/2010/08/04/327923.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Wed, 04 Aug 2010 04:34:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/archive/2010/08/04/327923.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/327923.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/archive/2010/08/04/327923.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/327923.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/327923.html</trackback:ping><description><![CDATA[      看了Eric77的Y件开发的一些感惻I五年工作l验ȝQ,很有感触。这个世界真是好大,自己作ؓ个体真是太ؓ,q有太多的东襉K要学习?br />       把他文章的部分{接过来,Z自己也备注下Q对自己有个参考?br />        一、需求分?设计,开?试和项目管理整个流E:<br /> <p>对Q何系l来? 无非是做?件事: IPO. 也就是Input,Process,Output. Q偏重于设计Q类g计算机本w,作ؓȝ本nq是蛮清楚的Q?/p> <p>寚w求分析来? 你最重要的是搞明?用户的需?也就是搞清用L输入(Input)和输?Output)是什?它的要求辑ֈ的功?Process)是什? 明白以后,你就可以写一些用户需求说明书,描述用例,输入输出处理异常什么的,或者做一个简单的Demopȝ,拿去l用L,看看q个界面是不是用户喜Ƣ的,q个程是不是用h需要的{等.Q注Q如果加入点理Q就丰满了。还有以后的需求变_要知道需要可能是不断变化的)</p> <p>然后是pȝ分析: 首先,你需要对用户的需求分模块,每个模块的IPO是什?他们应采用什么架?需要和那些模块交互,互相之间的接口是怎样?需要用什么技?每个模块的运行环境是什么样子的,Ҏ?安全或者容错等Ҏ是否要着重考虑.Q注Q考虑的蛮多的Q加个词Q系l的可扩展性)</p> <p>接着是pȝ设计: 每个模块的数据库要怎么设计,所用技术和架构军_?要确定不同层ơ有哪些接口,比如说表现层,业务逻辑?数据库访问层,怺之间怎么调用,定好框架和开发模式和格式,剩下的就是编码了..Q注Q说的似乎少了点Q?/p> <p>~码部分: 首先团队要有一个良好的~码规范.q且Ҏ个h提交的代码要review,我发现程序编多了,自己成了一台计?看到E序׃知道会出C么结?Ҏ都不用跑h.Q注Q编码的时候,多考虑下:复用和模式)</p> <p>试: 单元试是否~写试用例? Junit是个好工?每个人都要保证好自己的代码没有问? 整体试p整个程的跑一?看看需求实现的对不?q有没有什么其他纰?  .Q注Q测试分好多U,单元Q压力,持久性、黑白盒{,有专门的试部分或组׃一样了Q?/p> <p>风险理: q一点很重要,要时ȝ道自q目有什么风?无论是h员的,技术的,旉?q是协调上面?都要心里有数,按时按周向领导汇报?br /> <br />      以下部分—?/p> <p>      记得我去IBM面试的时?问过,以后有几条职业发展的方向,回答有三?一条是IT Specialist,一条是Project Manager,q有一条是IT Architect. 我还曾要求以后能不能向IT Architect发展,那h?Architect要熟悉很多技术呢,我问了两?他这样回{了两遍.后来l我订了Advisory I/T Specialist. 我当时很U闷,我搞Javaq么?J2ME,J2SE,J2EE全都搞过,而且对Gof?lt;Design Pattern>也悟?q?了熟于心,各种各样的经怹c也看了不少,怎么不能向Architect发展? 现在我加入了IBM,q入一个香港的目,q段旉要去香港培训几星?才明白了,原来一个大目会涉及到各种各样的语a,技?什么Cobal(韌),forturn(韌),java,vb,C#,soa xxȝ模式,mq,大型机开?{?很多我只在书上看到过的古老语a,q有一些听都没听过的语a,框架,模式,全都出现?我当时这个汗?我才发现我真的很无知.知识是一个气?你知道的多,接触的越多就会发现自p无知.所以这也是我要今天赶紧把这个写出来的原? 我怕以后又有了变故,q要沉淀,需要时?</p> <p> </p> <p>本文部分来自CSDN博客Q?a >http://blog.csdn.net/Eric77/archive/2010/08/01/5781573.aspx</a></p> <img src ="http://www.tkk7.com/ArcticOcean/aggbug/327923.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2010-08-04 12:34 <a href="http://www.tkk7.com/ArcticOcean/archive/2010/08/04/327923.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分布式计框架Hadoophttp://www.tkk7.com/ArcticOcean/archive/2010/08/03/327836.htmlCool JazzCool JazzTue, 03 Aug 2010 09:03:00 GMThttp://www.tkk7.com/ArcticOcean/archive/2010/08/03/327836.htmlhttp://www.tkk7.com/ArcticOcean/comments/327836.htmlhttp://www.tkk7.com/ArcticOcean/archive/2010/08/03/327836.html#Feedback0http://www.tkk7.com/ArcticOcean/comments/commentRss/327836.htmlhttp://www.tkk7.com/ArcticOcean/services/trackbacks/327836.htmlHadoop上{来的。其中有?/span>介绍HDFS的pdf文档Q对Hadoop介绍的比较全面?br />       先说一下Hadoop的来龙去脉。谈到Hadoop׃得不提到Lucene?/span>Nutch。首先,Luceneq不是一个应用程序,而是提供了一个纯Java的高性能全文索引引擎工具?/span>Q它可以方便的嵌入到各种实际应用中实现全文搜?索引功能?span style="color: rgb(0,0,255)">Nutch是一个应用程序,是一个以Lucene为基实现的搜索引擎应?/span>QLucene 为Nutch提供了文本搜索和索引的APIQNutch不光有搜索的功能Q还有数据抓取的功能。在nutch0.8.0版本之前QHadoopq属?Nutch的一部分Q而从nutch0.8.0开始,其中实现的NDFS和MapReduce剥离出来成立一个新的开源项目,q就是HadoopQ?nutch0.8.0版本较之以前的Nutch在架构上有了Ҏ性的变化Q那是完全构徏在Hadoop的基之上了。在Hadoop中实C Google的GFS和MapReduce法QHadoop成ؓ了一个分布式的计^台?br />        Hadoopq不仅仅是一个用于存储的分布式文件系l,而是设计用来在由通用计算讑֤l成的大型集上执行分布式应用的框架?br />
   Hadoop包含两个部分Q?/span>

   1、HDFS

      即Hadoop Distributed File System (Hadoop分布式文件系l?
      HDFS h高容错性,q且可以被部|在低h的硬件设备之上。HDFS很适合那些有大数据集的应用Qƈ且提供了Ҏ据读写的高吞吐率。HDFS是一?master/slave的结构,通常的部|来_在master上只q行一个NamenodeQ而在每一个slave上运行一个Datanode?br />       HDFS 支持传统的层ơ文件组l结构,同现有的一些文件系l在操作上很cMQ比如你可以创徏和删除一个文Ӟ把一个文件从一个目录移到另一个目录,重命名等{操 作。Namenode理着整个分布式文件系l,Ҏ件系l的操作Q如建立、删除文件和文g夹)都是通过Namenode来控制?nbsp;
     下面是HDFS的结构:


      从上面的图中可以?出,NamenodeQDatanodeQClient之间的通信都是建立在TCP/IP的基之上的。当Client要执行一个写入的操作的时候,命o 不是马上发送到NamenodeQClient首先在本Z临时文g夹中~存q些数据Q当临时文g夹中的数据块辑ֈ了设定的Block的|默认?64MQ时QClient便会通知NamenodeQNamenode便响应Client的RPChQ将文g名插入文件系l层ơ中q且?Datanode中找C块存放该数据的blockQ同时将该Datanode及对应的数据块信息告诉ClientQClient便这些本C时文件夹?的数据块写入指定的数据节炏V?br />       HDFS采取了副本策略,其目的是Z提高pȝ的可靠性,可用性。HDFS的副本放|策略是三个副本Q?一个放在本节点上,一个放在同一机架中的另一个节点上Q还有一个副本放在另一个不同的机架中的一个节点上。当前版本的hadoop0.12.0中还没有?玎ͼ但是正在q行中,怿不久可以出来了?br />
   2、MapReduce的实?br />
      
MapReduce是Google 的一w要技术,它是一个编E模型,用以q行大数据量的计。对于大数据量的计算Q通常采用的处理手法就是ƈ行计。至现阶段而言Q对许多开发h员来 _q行计算q是一个比较遥q的东西。MapReduce是一U简化ƈ行计的~程模型Q它让那些没有多ƈ行计经验的开发h员也可以开发ƈ行应用?br />       MapReduce的名字源于这个模型中的两Ҏ心操作:Map?Reduce。也许熟悉Functional ProgrammingQ?/span>函数式编E?/span>Q?的h见到q两个词会倍感亲切。简单的说来QMap是把一l数据一对一的映ؓ另外的一l数据,其映的规则׃个函数来指定Q比如对[1, 2, 3, 4]q行?的映就变成了[2, 4, 6, 8]。Reduce是对一l数据进行归U,q个归约的规则由一个函数指定,比如对[1, 2, 3, 4]q行求和的归U得到结果是10Q而对它进行求U的归约l果?4?br />
      关于MapReduce的内容,看看孟岩的这?/span>MapReduce:The Free Lunch Is Not Over! q篇是介绍的比较详l的。MapReduce的算法内容见Google文档Q?a title="MapReduce.pdf" >MapReduce.pdf

        有关其它介绍Hadoop的文章徏议看下:分布式计开源框架Hadoop介绍 。(whatQwhyQhow提的不错Q?br />         
        安装配置可以看:1?a rel="permalink">Hadoop中的集群配置和用技?/a>
                                        2?a >Hadoop应用之Hadoop安装?/a>
                                        3?a title="Hadoop安装部v指南" >Hadoop安装部v指南
         如果要开发的话,初步参考:Hadoop基本程与应用开?/a>
         
         其中用到数据库的部分Q在Hadoop?.19.0开始支撑数据库讉KQ主要采用DBInputFormat来访问数据库。文章可见:
Hadoop中的数据库访?/a>
      

Cool Jazz 2010-08-03 17:03 发表评论
]]>
字符集编码研I?/title><link>http://www.tkk7.com/ArcticOcean/articles/324841.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Wed, 30 Jun 2010 01:08:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/articles/324841.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/324841.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/articles/324841.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/324841.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/324841.html</trackback:ping><description><![CDATA[<h1 style="margin-bottom: 0pt; line-height: normal; text-align: center" align="center">--字符集编?/h1> <p class="1">1. 概述</p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">本文主要包括以下几个斚wQ编码基本知识,javaQ系lYӞurlQ工兯Y件等?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">在下面的描述中,以"中文"两个字ؓ例,l查表可以知道其GB2312~码?<u>d6d0 cec4</u>"QUnicode~码?<u>4e2d 6587</u>"QUTF~码是"<u>e4b8ad e69687</u>"。注意,q两个字没有iso8859-1~码Q但可以用iso8859-1~码?表示"?/p> <p class="1">2. ~码基本知识</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">最早的~码是iso8859-1Q和ascii~码怼。但Z方便表示各种各样的语aQ逐渐出现了很多标准编码,重要的有如下几个?/p> <p class="2">2.1. iso8859-1</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">属于单字节编码,最多能表示的字W范围是0-255Q应用于英文pd。比如,字母'a'的编码ؓ0x61=97?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">很明显,iso8859-1~码表示的字W范围很H,无法表示中文字符。但是,׃是单字节~码Q和计算机最基础的表C单位一_所以很多时候,仍旧使用iso8859-1~码来表C。而且在很多协议上Q默认用该~码。比如,虽然"中文"两个字不存在iso8859-1~码Q以gb2312~码ZQ应该是"<u>d6d0 cec4</u>"两个字符Q用iso8859-1~码的时候则它拆开?个字节来表示Q?<u>d6 d0 ce c4</u>"Q事实上Q在q行存储的时候,也是以字节ؓ单位处理的)。而如果是UTF~码Q则?个字?<u>e4 b8 ad e6 96 87</u>"。很明显Q这U表C方法还需要以另一U编码ؓ基础?/p> <p class="2">2.2. GB2312/GBK</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">q就是汉子的国标码,专门用来表示汉字Q是双字节编码,而英文字母和iso8859-1一_兼容iso8859-1~码Q。其中gbk~码能够用来同时表示J体字和体字Q而gb2312只能表示体字Qgbk是兼容gb2312~码的?/p> <p class="2">2.3. unicode</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">q是最l一的编码,可以用来表示所有语a的字W,而且是定长双字节Q也有四字节的)~码Q包括英文字母在内。所以可以说它是不兼容iso8859-1~码的,也不兼容M~码。不q,相对于iso8859-1~码来说Quniocode~码只是在前面增加了一?字节Q比如字?a'?<u>00 61</u>"?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">需要说明的是,定长~码便于计算机处理(注意GB2312/GBK不是定长~码Q,而unicode又可以用来表C所有字W,所以在很多软g内部是用unicode~码来处理的Q比如java?/p> <p class="2">2.4. UTF</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">考虑到unicode~码不兼容iso8859-1~码Q而且Ҏ占用更多的空_因ؓ对于英文字母Qunicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而生了utf~码Qutf~码兼容iso8859-1~码Q同时也可以用来表示所有语a的字W,不过Qutf~码是不定长~码Q每一个字W的长度?-6个字节不{。另外,utf~码自带单的校验功能。一般来Ԍ英文字母都是用一个字节表C,而汉字用三个字节?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">注意Q虽然说utf是ؓ了用更的I间而用的Q但那只是相对于unicode~码来说Q如果已l知道是汉字Q则使用GB2312/GBK无疑是最节省的。不q另一斚wQ值得说明的是Q虽然utf~码Ҏ字?个字节,但即使对于汉字网,utf~码也会比unicode~码节省Q因为网中包含了很多的英文字符?/p> <p class="1">3. java对字W的处理</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">在java应用软g中,会有多处涉及到字W集~码Q有些地斚w要进行正的讄Q有些地斚w要进行一定程度的处理?/p> <p class="2">3.1. getBytes(charset)</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">q是java字符串处理的一个标准函敎ͼ其作用是字W串所表示的字W按照charset~码Qƈ以字节方式表C。注意字W串在java内存中L按unicode~码存储的。比?中文"Q正常情况下Q即没有错误的时候)存储?<u>4e2d 6587</u>"Q如果charset?gbk"Q则被编码ؓ"<u>d6d0 cec4</u>"Q然后返回字?<u>d6 d0 ce c4</u>"。如果charset?utf8"则最后是"<u>e4 b8 ad e6 96 87</u>"。如果是"iso8859-1"Q则׃无法~码Q最后返?"<u>3f 3f</u>"Q两个问P?/p> <p class="2">3.2. new String(charset)</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">q是java字符串处理的另一个标准函敎ͼ和上一个函数的作用相反Q将字节数组按照charset~码q行l合识别Q最后{换ؓunicode存储。参考上qgetBytes的例子,"gbk" ?utf8"都可以得出正的l果"<u>4e2d 6587</u>"Q但iso8859-1最后变成了"<u>003f 003f</u>"Q两个问P?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">因ؓutf8可以用来表示/~码所有字W,所以new String( str.getBytes( "utf8" ), "utf8" ) === strQ即完全可逆?/p> <p class="2">3.3. setCharacterEncoding()</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">该函数用来设|httph或者相应的~码?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">对于requestQ是指提交内容的~码Q指定后可以通过getParameter()则直接获得正的字符Ԍ如果不指定,则默认用iso8859-1~码Q需要进一步处理。参见下q?表单输入"。值得注意的是在执行setCharacterEncoding()之前Q不能执行Q何getParameter()。java doc上说明:This method must be called prior to reading request parameters or reading input using getReader()。而且Q该指定只对POSTҎ有效Q对GETҎ无效。分析原因,应该是在执行W一个getParameter()的时候,java会按照~码分析所有的提交内容Q而后l的getParameter()不再q行分析Q所以setCharacterEncoding()无效。而对于GETҎ提交表单是,提交的内容在URL中,一开始就已经按照~码分析所有的提交内容QsetCharacterEncoding()自然无效?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">对于responseQ则是指定输出内容的~码Q同Ӟ该设|会传递给览器,告诉览器输出内Ҏ采用的编码?/p> <p class="2">3.4. 处理q程</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">下面分析两个有代表性的例子Q说明java对编码有关问题的处理Ҏ?/p> <p class="3">3.4.1. 表单输入</p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">User input<u>  *(gbk:d6d0 cec4)  </u>browser<u>  *(gbk:d6d0 cec4)  </u>web server<u>  iso8859-1(00d6 00d 000ce 00c4)  </u>classQ需要在class中进行处理:getbytes("iso8859-1")?u>d6 d0 ce c4</u>Qnew String("gbk")?u>d6d0 cec4</u>Q内存中以unicode~码则ؓ<u>4e2d 6587</u>?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> 用户输入的编码方式和面指定的编码有养I也和用户的操作系l有养I所以是不确定的Q上例以gbkZ?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> 从browser到web serverQ可以在表单中指定提交内Ҏ使用的字W集Q否则会使用面指定的编码。而如果在url中直接用?的方式输入参敎ͼ则其~码往往是操作系l本w的~码Q因时和面无关。上qC旧以gbk~码Z?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> Web server接收到的是字节流Q默认时QgetParameterQ会以iso8859-1~码处理之,l果是不正确的,所以需要进行处理。但如果预先讄了编码(通过request. setCharacterEncoding ()Q,则能够直接获取到正确的结果?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> 在页面中指定~码是个好习惯,否则可能失去控制Q无法指定正的~码?/p> <p class="3">3.4.2. 文g~译</p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">假设文g是gbk~码保存的,而编译有两种~码选择Qgbk或者iso8859-1Q前者是中文windows的默认编码,后者是linux的默认编码,当然也可以在~译时指定编码?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">Jsp<u>  *(gbk:d6d0 cec4)  </u>java file<u>  *(gbk:d6d0 cec4)  </u>compiler read<u>  uincode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  </u>compiler write<u>  utf(gbk: e4b8ad e69687; iso8859-1: *)  </u>compiled file<u>  unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  </u>class。所以用gbk~码保存Q而用iso8859-1~译的结果是不正的?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">class<u>  unicode(4e2d 6587)  </u>system.out / jsp.out<u>  gbk(d6d0 cec4)  </u>os console / browser?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> 文g可以以多U编码方式保存,中文windows下,默认为ansi/gbk?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> ~译器读取文件时Q需要得到文件的~码Q如果未指定Q则使用pȝ默认~码。一般class文gQ是以系l默认编码保存的Q所以编译不会出问题Q但对于jsp文gQ如果在中文windows下编辑保存,而部|在英文linux下运?~译Q则会出现问题。所以需要在jsp文g中用pageEncoding指定~码?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> Java~译的时候会转换成统一的unicode~码处理Q最后保存的时候再转换为utf~码?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> 当系l输出字W的时候,会按指定~码输出Q对于中文windows下,System.out用gbk~码Q而对于responseQ浏览器Q,则用jsp文g头指定的contentTypeQ或者可以直接ؓresponse指定~码。同Ӟ会告诉browser|页的编码。如果未指定Q则会用iso8859-1~码。对于中文,应该为browser指定输出字符串的~码?/p> <p class="MsoBodyTextIndent" style="margin-left: 43pt; text-indent: -21pt; tab-stops: list 43.0pt"><span lang="EN-US" style="font-size: 11pt; font-family: Wingdings">l</span> browser昄|页的时候,首先使用response中指定的~码Qjsp文g头指定的contentType最l也反映在response上)Q如果未指定Q则会用网中metaҎ定中的contentType?/p> <p class="2">3.5. 几处讄</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">对于web应用E序Q和~码有关的设|或者函数如下?/p> <p class="3">3.5.1. jsp~译</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">指定文g的存储编码,很明显,该设|应该置于文件的开头。例如:<%@page pageEncoding="GBK"%>。另外,对于一般class文gQ可以在~译的时候指定编码?/p> <p class="3">3.5.2. jsp输出</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">指定文g输出到browser是用的~码Q该讄也应该置于文件的开头。例如:<%@ page contentType="text/html; charset= GBK" %>。该讄和response.setCharacterEncoding("GBK"){效?/p> <p class="3">3.5.3. meta讄</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">指定|页使用的编码,该设|对静态网尤其有作用。因为静态网|法采用jsp的设|,而且也无法执行response.setCharacterEncoding()。例如:<<ST1:PLACE w:st="on">META http-equiv="Content-Type" content="text/html; charset=GBK" /></p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">如果同时采用了jsp输出和meta讄两种~码指定方式Q则jsp指定的优先。因为jsp指定的直接体现在response中?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">需要注意的是,apache有一个设|可以给无编码指定的|页指定~码Q该指定{同于jsp的编码指定方式,所以会覆盖静态网中的meta指定。所以有人徏议关闭该讄?/p> <p class="3">3.5.4. form讄</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">当浏览器提交表单的时候,可以指定相应的编码。例如:<form accept-charset= "gb2312">。一般不必不使用该设|,览器会直接使用|页的编码?/p> <p class="1">4. pȝ软g</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">下面讨论几个相关的系lY件?/p> <p class="2">4.1. mysql数据?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">很明显,要支持多语言Q应该将数据库的~码讄成utf或者unicodeQ而utf更适合与存储。但是,如果中文数据中包含的英文字母很少Q其实unicode更ؓ适合?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">数据库的~码可以通过mysql的配|文件设|,例如default-character-set=utf8。还可以在数据库链接URL中设|,例如Q?useUnicode=true&characterEncoding=UTF-8。注意这两者应该保持一_在新的sql版本里,在数据库链接URL里可以不q行讄Q但也不能是错误的设|?/p> <p class="2">4.2. apache</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">appache和编码有关的配置在httpd.conf中,例如AddDefaultCharset UTF-8。如前所qͼ该功能会所有静态页面的~码讄为UTF-8Q最好关闭该功能?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">另外Qapacheq有单独的模块来处理|页响应_其中也可能对~码q行讄?/p> <p class="2">4.3. linux默认~码</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">q里所说的linux默认~码Q是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANGQ默认编码会影响到java URLEncode的行为,下面有描q?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">都设|ؓ"zh_CN.UTF-8"?/p> <p class="2">4.4. 其它</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">Z支持中文文g名,linux在加载磁盘时应该指定字符集,例如Qmount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">另外Q如前所qͼ使用GETҎ提交的信息不支持request.setCharacterEncoding()Q但可以通过tomcat的配|文件指定字W集Q在tomcat的server.xml文g中,形如Q?lt;Connector ... URIEncoding="GBK"/>。这U方法将l一讄所有请求,而不能针对具体页面进行设|,也不一定和browser使用的编码相同,所以有时候ƈ不是所期望的?/p> <p class="1">5. URL地址</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">URL地址中含有中文字W是很麻烦的Q前面描q过使用GETҎ提交表单的情况,使用GETҎӞ参数是包含在URL中?/p> <p class="2">5.1. URL~码</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">对于URL中的一些特D字W,览器会自动q行~码。这些字W除?/?&"{外Q还包括unicode字符Q比如汉子。这时的~码比较Ҏ?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">IE有一个选项"L使用UTF-8发送URL"Q当该选项有效ӞIE会对特D字W进行UTF-8~码Q同时进行URL~码。如果改选项无效Q则使用默认~码"GBK"Qƈ且不q行URL~码。但是,对于URL后面的参敎ͼ则L不进行编码,相当于UTF-8选项无效。比?中文.html?a=中文"Q当UTF-8选项有效Ӟ发送链?%<u>e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87</u>"Q而UTF-8选项无效Ӟ发送链?<u>\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87</u>"。注意后者前面的"中文"两个字只?个字节,而前者却?8个字节,q主要时URL~码的原因?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">当web serverQtomcatQ接收到该链接时Q将会进行URL解码Q即L"%"Q同时按照ISO8859-1~码Q上面已l描qͼ可以使用URLEncoding来设|成其它~码Q识别。上qC子的l果分别?<u>\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87</u>"?<u>\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87</u>"Q注意前者前面的"中文"两个字恢复成?个字W。这里用"\u"Q表C是unicode?/p> <p class="MsoBodyTextIndent" style="text-indent: 22pt">所以,׃客户端设|的不同Q相同的链接Q在服务器上得到了不同结果。这个问题不h都遇刎ͼ却没有很好的解决办法。所以有的网站会用户试关闭UTF-8选项。不q,下面会描qC个更好的处理办法?/p> <p class="2">5.2. rewrite</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">熟悉的h都知道,apache有一个功能强大的rewrite模块Q这里不描述其功能。需要说明的是该模块会自动将URL解码Q去?Q,卛_成上qweb serverQtomcatQ的部分功能。有相关文介绍说可以用[NE]参数来关闭该功能Q但我试验ƈ未成功,可能是因为版本(我用的是apache <ST1:CHSDATE w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.0.54Q问题。另外,当参C含有"?& "{符L时候,该功能将Dpȝ得不到正常结果?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">rewrite本ng完全是采用字节处理的方式Q而不考虑字符串的~码Q所以不会带来编码问题?/p> <p class="2">5.3. URLEncode.encode()</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">q是Java本n提供对的URL~码函数Q完成的工作和上qUTF-8选项有效时浏览器所做的工作怼。值得说明的是Qjava已经不赞成不指定~码来用该ҎQdeprecatedQ。应该在使用的时候增加编码指定?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">当不指定~码的时候,该方法用系l默认编码,q会D软gq行l果得不定。比如对?中文"Q当pȝ默认~码?gb2312"Ӟl果?%<u>4e%2d%65%87</u>"Q而默认编码ؓ"UTF-8"Q结果却?%<u>e4%b8%ad%e6%96%87</u>"Q后l程序将难以处理。另外,q儿说的pȝ默认~码是由q行tomcat时的环境变量LC_ALL和LANG{决定的Q曾l出现过tomcat重启后就出现q的问题,最后才郁闷的发现是因ؓ修改修改了这两个环境变量?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">l一指定?UTF-8"~码Q可能需要修改相应的E序?/p> <p class="2">5.4. 一个解x?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">上面说vq,因ؓ览器设|的不同Q对于同一个链接,web server收到的是不同内容Q而Y件系l有无法知道q中间的区别Q所以这一协议目前q存在缺陗?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">针对具体问题Q不应该侥幸认ؓ所有客LIE讄都是UTF-8有效的,也不应该_暴的徏议用户修改IE讄Q要知道Q用户不可能去记住每一个web server的设|。所以,接下来的解决办法只能是让自qE序多一Ҏ能:Ҏ内容来分析编码是否UTF-8?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">比较q运的是UTF-8~码相当有规律,所以可以通过分析传输q来的链接内容,来判断是否是正确的UTF-8字符Q如果是Q则以UTF-8处理之,如果不是Q则使用客户默认~码Q比?GBK"Q,下面是一个判断是否UTF-8的例子,如果你了解相应规律,容易理解?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">public static boolean isValidUtf8(byte[] b,int aMaxCount){</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       int lLen=b.length,lCharCount=0;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       for(int i=0;i<lLen && lCharCount<aMaxCount;++lCharCount){</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">              byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;)</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">              if(lByte>=0) continue;//>=0 is normal ascii</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">              if(lByte<(byte)0xc0 || lByte>(byte)0xfd) return false;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">              int lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">                     :lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">              if(i+lCount>lLen) return false;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">              for(int j=0;j<lCount;++j,++i) if(b[i]>=(byte)0xc0) return false;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       }</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       return true;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">}</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">相应圎ͼ一个用上q方法的例子如下Q?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">public static String getUrlParam(String aStr,String aDefaultCharset)</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">throws UnsupportedEncodingException{</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       if(aStr==null) return null;</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       byte[] lBytes=aStr.getBytes("ISO-8859-1");</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">       return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset);</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">}</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">不过Q该Ҏ也存在缺P如下两方面:</p> <p class="MsoBodyTextIndent" style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span lang="EN-US" style="font-family: Wingdings">l</span> 没有包括对用户默认编码的识别Q这可以Ҏh信息的语a来判断,但不一定正,因ؓ我们有时候也会输入一些韩文,或者其他文字?/p> <p class="MsoBodyTextIndent" style="margin-left: 42pt; text-indent: -21pt; tab-stops: list 42.0pt"><span lang="EN-US" style="font-family: Wingdings">l</span> 可能会错误判断UTF-8字符Q一个例子是"学习"两个字,其GBK~码? <u>\xd1\xa7\xcf\xb0</u>"Q如果用上qisValidUtf8Ҏ判断Q将q回true。可以考虑使用更严格的判断ҎQ不q估计效果不大?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">有一个例子可以证明google也遇C上述问题Q而且也采用了和上q相似的处理ҎQ比如,如果在地址栏中输入"<a Qgoogle无法正识别,而其他汉字一般能够正常识别?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">最后,应该补充说明一下,如果不用rewrite规则Q或者通过表单提交数据Q其实ƈ不一定会遇到上述问题Q因时可以在提交数据时指定希望的~码。另外,中文文g名确实会带来问题Q应该}慎用?/p> <p class="1">6. 其它</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">下面描述一些和~码有关的其他问题?/p> <p class="2">6.1. SecureCRT</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">除了览器和控制C~码有关外,一些客L也很有关pR比如在使用SecureCRTq接linuxӞ应该让SecureCRT的显C编码(不同的sessionQ可以有不同的编码设|)和linux的编码环境变量保持一致。否则看到的一些帮助信息,可能是q?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">另外Qmysql有自q~码讄Q也应该保持和SecureCRT的显C编码一致。否则通过SecureCRT执行sql语句的时候,可能无法处理中文字符Q查询结果也会出Cؕ码?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">对于Utf-8文gQ很多编辑器Q比如记事本Q会在文件开头增加三个不可见的标志字节,如果作ؓmysql的输入文Ӟ则必要Lq三个字W。(用linux的vi保存可以Lq三个字W)。一个有的现象是,在中文windows下,创徏一个新txt文gQ用C本打开Q输?q?两个字,保存Q再打开Q你会发C个字没了Q只留下一个小黑点?/p> <p class="2">6.2. qo?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">如果需要统一讄~码Q则通过filterq行讄是个不错的选择。在filter class中,可以l一为需要的h或者回应设|编码。参加上qsetCharacterEncoding()。这个类apache已经l出了可以直接用的例子SetCharacterEncodingFilter?/p> <p class="2">6.3. POST和GET</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">很明显,以POST提交信息ӞURL有更好的可读性,而且可以方便的用setCharacterEncoding()来处理字W集问题。但GETҎ形成的URL能够更容易表辄늚实际内容Q也能够用于收藏?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">从统一的角度考虑问题Q徏议采用GETҎQ这要求在程序中获得参数是进行特D处理,而无法用setCharacterEncoding()的便利,如果不考虑rewriteQ就不存在IE的UTF-8问题Q可以考虑通过讄URIEncoding来方便获取URL中的参数?/p> <p class="2">6.4. J体~码转换</p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">GBK同时包含体和J体~码Q也是说同一个字Q由于编码不同,在GBK~码下属于两个字。有时候,Z正确取得完整的结果,应该繁体和体进行统一。可以考虑UTF、GBK中的所有繁体字Q{换ؓ相应的简体字QBIG5~码的数据,也应该{化成相应的简体字。当Ӟ仍旧以UTF~码存储?/p> <p class="MsoBodyTextIndent" style="text-indent: 21pt">例如Q对?语言 語言"Q用UTF表示?<u>\x</u><u>E8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80</u>"Q进行简J体~码转换后应该是两个相同?"<u>\x</u><u>E8\xAF\xAD\xE8\xA8\x80></u>"?br /> <br /> <br />  转蝲于:刘科?<a >Manufacturer.com</a> </p> <p class="MsoBodyTextIndent" style="text-indent: 21pt; text-align: right" align="right"></ST1:CHSDATE></ST1:PLACE> </p> <img src ="http://www.tkk7.com/ArcticOcean/aggbug/324841.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2010-06-30 09:08 <a href="http://www.tkk7.com/ArcticOcean/articles/324841.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>邮g历照片显C,试成功Q在BlogjavaQ?/title><link>http://www.tkk7.com/ArcticOcean/archive/2008/11/09/239543.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Sun, 09 Nov 2008 12:01:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/archive/2008/11/09/239543.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/239543.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/archive/2008/11/09/239543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/239543.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/239543.html</trackback:ping><description><![CDATA[<p>        最q比较忙。因为我马上p毕业了,正在扑ַ作。自己去|上下了html版的历。编辑了Q放入邮。在自己的机子上能看出来Q我以ؓ发出去别h也能看得到呢。后来我同学问我怎么才能在邮仉昄照片Q我把Ҏ告诉他,q且把他的照片传C我在JR的相册里。v初在他的邮g里(本地|络Q可以看到。我׃为成功了呢。改天他发了邮gl他同学看,却发现看不到?br />         我真是奇怪了。怎么会看不到呢?<br />         照片的地址Q单独点ȝ话可以看到。在别h的邮仉是看不刎ͼ除非那个Z点击了照片的地址Qƈ把照片显C出来后Q才能在邮g里显C。搞了好几次都是q个样子Q我无语了?br />         N说JR的相册不能被外h看到Q?br />         不应该啊Q别人是可以看到的呀。莫非JR的相册自动限制了Q照片的下蝲Q?br />         也许是这个原因,我想?br />         我换了BlogjavaQ找了我的同学测试。把JR的测试了3Q?ơ都不能昄。最后我试了BlogjavaQ成功了Q(Ҏ׃用我在啰嗦了吧:Q)<br />         看来q是Blogjava好啊。我后一定要在这里多写blogQ?br />         以前Q我很少写技术的blogQ因己想写的东西多数和公司的代码有关Q有时候想写却不能把代码脓出来。烦性就不写blog。只是去技术性的|站或开源的|站看最新的英文新闻。如果有新消息,把它翻译过来,攑ֈ自己的blog里?br />        Blogjaval我的感觉是Q功能比JR的强。但是h气似乎要׃些?br />        不关怎么P我以后会多到q里来的?br />        <br />         </p> <img src ="http://www.tkk7.com/ArcticOcean/aggbug/239543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2008-11-09 20:01 <a href="http://www.tkk7.com/ArcticOcean/archive/2008/11/09/239543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>好多天没来了Q因为在写论?/title><link>http://www.tkk7.com/ArcticOcean/archive/2008/09/21/230255.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Sun, 21 Sep 2008 05:46:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/archive/2008/09/21/230255.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/230255.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/archive/2008/09/21/230255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/230255.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/230255.html</trackback:ping><description><![CDATA[        好多天没来了。最q在忙论文的事情Q每天白天要上班。公司晚上又断线不能上网。所以每天只能查了资料保存v来晚上在看?br />         毕竟以前做了数据库的目Q相Ҏ说好写点。只是我做的那些东西被师兄给“?#8221;了。所以留l自q隑ֺ不小?br />         哎,公司现在q行的东西比较老了Q虽然有市场。多年都是q样的老架构。没有新东西出来Q将来会比较ȝ。现在是在公司,w不由己。既然公叔R目帮不上什么忙Q就自己动手了。采用现在的L框架Q结合IEC规约Q在整合上数据库集群Q服务器集群。。。似乎是多了Q但是不写,自己会觉得没有什么东ѝ学校那些老师Q都不知道现在外面的技术进展情况,是那老技术来写,他们可能q觉得挺新的。不q,不能骗自己啊。搞q么多架构的东西Q没有程序,没有实际的运行和试Q你能说服得了谁Q程序是写了Q把原来在学校研I的目拿来Q加上Spring攚w,DWR包装成JavaScriptQ在传给试界面。。?br />         真难啊,最隄也就是调试了。也是只能每天晚上搞,真篏Q?br />         q好我搞出来了,攑֜Apache和Tomcat集群下,q行q些E序抓了些图Q真爽啊Q?br />        只是我的服务器集是|上参考别人的Q还真没q行q。哎Q没机器啊,公司的机器又不能随便用。我最怕的是通信Q我没做q,只是用了公司以前做的通信lg拿来用,q行能用。要是连RTU的话,更好了Q可惜。。?br />        庆祝一下,我的服务器后台架构测试成功!感谢JavaQ感谢Spring和HibernateQ感谢PostgreSQLQ感谢开源!<br />        整理论文?Q) <img src ="http://www.tkk7.com/ArcticOcean/aggbug/230255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2008-09-21 13:46 <a href="http://www.tkk7.com/ArcticOcean/archive/2008/09/21/230255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>q么快,Hibernate3.3.1GA发布Q?/title><link>http://www.tkk7.com/ArcticOcean/archive/2008/09/12/228510.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Fri, 12 Sep 2008 01:50:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/archive/2008/09/12/228510.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/228510.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/archive/2008/09/12/228510.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/228510.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/228510.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-repeat: initial; background-attachment: initial; background-color: #ffffff; background-position: initial initial; "> <p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">    在距Hibernate3.3.0GA发布不到一个月的时间内Q?.3.1GA发布了。感觉真是快啊。原来是修正了bug?/p> <p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">    q次发布主要是修正了<span style="font-family: white-space: pre-wrap; ">CurrentSessionContext(SessionFactory.getCurrentSession())q行在IBM WebSphered的严重问题?span style="white-space: normal; ">它也包括了id发生器等不少改进。细节部分和全部变化Q请查看变化日志?/span></span></p> <p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">    <span style="font-family: 'Lucida Sans'; font-size: 13px; line-height: 19px; ">Hibernate Core 3.3.1 has just been <a target="" class="regularLink" style="color: #d75525; text-decoration: underline; ">released</a> with its artifacts published to the JBoss Maven <a target="" class="regularLink" style="color: #d75525; text-decoration: underline; ">Repository</a>. This release fixed a serious issue with CurrentSessionContext (SessionFactory.getCurrentSession()) when running on IBM WebSphere. It also includes quite a few improvements to the <a target="" class="regularLink" style="color: #d75525; text-decoration: underline; ">enhanced id generators</a>. For details about all the changes in this release, check out it's <a target="" class="regularLink" style="color: #d75525; text-decoration: underline; ">changelog</a></span></p> <p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">   </p> </div> <img src ="http://www.tkk7.com/ArcticOcean/aggbug/228510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2008-09-12 09:50 <a href="http://www.tkk7.com/ArcticOcean/archive/2008/09/12/228510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>新来的,安个家?/title><link>http://www.tkk7.com/ArcticOcean/archive/2008/09/11/228377.html</link><dc:creator>Cool Jazz</dc:creator><author>Cool Jazz</author><pubDate>Thu, 11 Sep 2008 08:07:00 GMT</pubDate><guid>http://www.tkk7.com/ArcticOcean/archive/2008/09/11/228377.html</guid><wfw:comment>http://www.tkk7.com/ArcticOcean/comments/228377.html</wfw:comment><comments>http://www.tkk7.com/ArcticOcean/archive/2008/09/11/228377.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/ArcticOcean/comments/commentRss/228377.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/ArcticOcean/services/trackbacks/228377.html</trackback:ping><description><![CDATA[<p>    ȝBlog不多Q偶然见了Blogjava。没什么想法,安个家吧。也许这里会僻静些?br />     写个首BlogQ发现这里的BlogҎ提示q有英文Q呵c不q,对于看API来说Q这些算意思?br />     乱涂Qؕ涂。。?br /> <span lang="EN-US" style="font-size: 10pt; font-family: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">  </v:shapetype></span><br />     </p> <img src ="http://www.tkk7.com/ArcticOcean/aggbug/228377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/ArcticOcean/" target="_blank">Cool Jazz</a> 2008-09-11 16:07 <a href="http://www.tkk7.com/ArcticOcean/archive/2008/09/11/228377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://wangquanai.com" target="_blank">һëƬƵѹۿ</a>| <a href="http://szicon.com" target="_blank">Ѿþþþþ</a>| <a href="http://pencilinside.com" target="_blank">һaëƬƵ</a>| <a href="http://masfd.com" target="_blank">߳Ķ </a>| <a href="http://avdaka.com" target="_blank">ƷŮ߳鴤վ</a>| <a href="http://gzqhit.com" target="_blank">ҹӰȫѿ</a>| <a href="http://8xxon8.com" target="_blank">þþþþav</a>| <a href="http://moushengguigz.com" target="_blank">ֻˬֳƵ</a>| <a href="http://kutuwo.com" target="_blank">avרavëƬ</a>| <a href="http://gzbaida.com" target="_blank">AVרAVJULIA</a>| <a href="http://lfpfjc.com" target="_blank">һƵ </a>| <a href="http://6wss.com" target="_blank">Ʒþһ</a>| <a href="http://4228970.com" target="_blank">һƵѹۿ</a>| <a href="http://www19977.com" target="_blank">ֻĻ</a>| <a href="http://www-9970.com" target="_blank">רһvavר</a>| <a href="http://565636.com" target="_blank">99Ƶ߾Ʒ</a>| <a href="http://asdfghjklzxcv.com" target="_blank">Ůվ</a>| <a href="http://977446.com" target="_blank">޾Ƶ߹ۿ</a>| <a href="http://sdyzzs.com" target="_blank">߹ۿ</a>| <a href="http://xamxx.com" target="_blank">þۺAVѹۿ</a>| <a href="http://zhuanjiao521.com" target="_blank">߻ɫӰ</a>| <a href="http://zhxydq.com" target="_blank">ӰԺҹײ</a>| <a href="http://www-63228.com" target="_blank">Ʒ޹AVƬý</a>| <a href="http://caoporg.com" target="_blank">޸Ʒһ </a>| <a href="http://8mav950.com" target="_blank">ëƬƵѹۿ</a>| <a href="http://mallmirror.com" target="_blank">a߹ۿַȫ</a>| <a href="http://okgou58.com" target="_blank">AVһһ</a>| <a href="http://3333kkkk.com" target="_blank">޹ƷԲӰ</a>| <a href="http://8833655.com" target="_blank">޹Ʒ߲</a>| <a href="http://ri9999.com" target="_blank">ҵС身߿Ѹ </a>| <a href="http://www84847.com" target="_blank">ģ߹ۿ</a>| <a href="http://louqibang.com" target="_blank">˳ɵӰվƷ</a>| <a href="http://1314xxx.com" target="_blank">ɫ7777Ƶ߹ۿ</a>| <a href="http://aqd1987.com" target="_blank">99þþƷëƬѲ</a>| <a href="http://bjlfggcm.com" target="_blank">AVһɫ</a>| <a href="http://dukane1688.com" target="_blank">»ɫַ</a>| <a href="http://zaideqin.com" target="_blank">AVһլɫӰ</a>| <a href="http://sdzhly.com" target="_blank">Ļר</a>| <a href="http://whknd.com" target="_blank">߹ۿƵ</a>| <a href="http://502274.com" target="_blank">Ѱvվ߹ۿg</a>| <a href="http://haha02.com" target="_blank">˳Ƶ߹ۿվ </a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>