﻿<?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-Change Dir-随笔分类-好代码分享</title><link>http://www.blogjava.net/changedi/category/50895.html</link><description>先知cd——热爱生活是一切艺术的开始</description><language>zh-cn</language><lastBuildDate>Thu, 31 May 2012 20:06:11 GMT</lastBuildDate><pubDate>Thu, 31 May 2012 20:06:11 GMT</pubDate><ttl>60</ttl><item><title>分享一个LRUMap的实现&amp;mdash;&amp;mdash;来自apache common-collections框架</title><link>http://www.blogjava.net/changedi/archive/2012/05/31/379658.html</link><dc:creator>changedi</dc:creator><author>changedi</author><pubDate>Thu, 31 May 2012 05:16:00 GMT</pubDate><guid>http://www.blogjava.net/changedi/archive/2012/05/31/379658.html</guid><wfw:comment>http://www.blogjava.net/changedi/comments/379658.html</wfw:comment><comments>http://www.blogjava.net/changedi/archive/2012/05/31/379658.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/changedi/comments/commentRss/379658.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/changedi/services/trackbacks/379658.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 今天主要分享一个LRUmap的实现。我们经常会用到需要使用map来保存数据的时候，由于map本身的映射高效，最适合做随机读取的存储结构。当然LRU算法是在有限大小的存储集合下的一种调度算法，即最近最少使用。对于一个给定大小限制的容器，如何分配资源就涉及到调度，而LRU就是一种经典的调度了，在容器中定义一个最后使用时间，当容器满时，再来新的元素，那么淘汰最近最少使用的元素，把新的元素替换之，这是最直...&nbsp;&nbsp;<a href='http://www.blogjava.net/changedi/archive/2012/05/31/379658.html'>阅读全文</a><img src ="http://www.blogjava.net/changedi/aggbug/379658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/changedi/" target="_blank">changedi</a> 2012-05-31 13:16 <a href="http://www.blogjava.net/changedi/archive/2012/05/31/379658.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分享代码系列——vlist</title><link>http://www.blogjava.net/changedi/archive/2012/04/15/374226.html</link><dc:creator>changedi</dc:creator><author>changedi</author><pubDate>Sun, 15 Apr 2012 04:29:00 GMT</pubDate><guid>http://www.blogjava.net/changedi/archive/2012/04/15/374226.html</guid><wfw:comment>http://www.blogjava.net/changedi/comments/374226.html</wfw:comment><comments>http://www.blogjava.net/changedi/archive/2012/04/15/374226.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/changedi/comments/commentRss/374226.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/changedi/services/trackbacks/374226.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: vlist是一种列表的实现。结构如下图：&nbsp;（图来源wikipedia）类似链接表的结构，但是，不是线性的。它的结构基于一种2的幂次扩展，第一个链接节点包含了列表的前一半数据，第二个包含了剩下一半的一半，依次递归。节点的基本结构不像LinkedList的节点是双端队列，每个VListCell包含了下个节点的指针mNext和前一个节点的指针mPrev，同时内置一个数组mElems用来...&nbsp;&nbsp;<a href='http://www.blogjava.net/changedi/archive/2012/04/15/374226.html'>阅读全文</a><img src ="http://www.blogjava.net/changedi/aggbug/374226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/changedi/" target="_blank">changedi</a> 2012-04-15 12:29 <a href="http://www.blogjava.net/changedi/archive/2012/04/15/374226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分享代码系列&amp;mdash;&amp;mdash;parseInt(包含java和c语言的atoi方法）</title><link>http://www.blogjava.net/changedi/archive/2012/04/06/373454.html</link><dc:creator>changedi</dc:creator><author>changedi</author><pubDate>Fri, 06 Apr 2012 04:20:00 GMT</pubDate><guid>http://www.blogjava.net/changedi/archive/2012/04/06/373454.html</guid><wfw:comment>http://www.blogjava.net/changedi/comments/373454.html</wfw:comment><comments>http://www.blogjava.net/changedi/archive/2012/04/06/373454.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/changedi/comments/commentRss/373454.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/changedi/services/trackbacks/373454.html</trackback:ping><description><![CDATA[<p>jdk中的Integer类是int对象的包装类，正常的Integer占用内存开销要比int大，比例大概是1:4 。今天分享的代码是Integer类中的静态方法parseInt(String, int)。这个方法众所周知，甚至在我们一开始学习编程时就尝试的写过这样的代码，一个正常的思路：遍历输入的字符数组（java的字符串就是一个字符数组），然后parse每个char，依据参数给定的进制，判断每个char是否满足，满足则继续，否则抛出异常或中断，直到处理完毕所有字符，返回结果。</p> <p>那么我们看看jdk给出的实现：</p> <p>&nbsp;&nbsp;&nbsp; public static int parseInt(String s, int radix)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws NumberFormatException<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s == null) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new NumberFormatException("null");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p> <p>&nbsp;&nbsp;&nbsp; if (radix &lt; Character.MIN_RADIX) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new NumberFormatException("radix " + radix +<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " less than Character.MIN_RADIX");<br />&nbsp;&nbsp;&nbsp; }</p> <p>&nbsp;&nbsp;&nbsp; if (radix &gt; Character.MAX_RADIX) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new NumberFormatException("radix " + radix +<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " greater than Character.MAX_RADIX");<br />&nbsp;&nbsp;&nbsp; }</p> <p>&nbsp;&nbsp;&nbsp; int result = 0;<br />&nbsp;&nbsp;&nbsp; boolean negative = false;<br />&nbsp;&nbsp;&nbsp; int i = 0, max = s.length();<br />&nbsp;&nbsp;&nbsp; int limit;<br />&nbsp;&nbsp;&nbsp; int multmin;<br />&nbsp;&nbsp;&nbsp; int digit;</p> <p>&nbsp;&nbsp;&nbsp; if (max &gt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s.charAt(0) == '-') {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; negative = true;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; limit = Integer.MIN_VALUE;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; limit = -Integer.MAX_VALUE;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; multmin = limit / radix;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i &lt; max) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; digit = Character.digit(s.charAt(i++),radix);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (digit &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw NumberFormatException.forInputString(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = -digit;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (i &lt; max) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Accumulating negatively avoids surprises near MAX_VALUE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; digit = Character.digit(s.charAt(i++),radix);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (digit &lt; 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw NumberFormatException.forInputString(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (result &lt; multmin) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw NumberFormatException.forInputString(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result *= radix;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (result &lt; limit + digit) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw NumberFormatException.forInputString(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result -= digit;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw NumberFormatException.forInputString(s);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; if (negative) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i &gt; 1) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp; /* Only got "-" */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw NumberFormatException.forInputString(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -result;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }</p> <p>过程就是按照思路来的，但是更全面一些，首先做一些参数检查，然后定义了局部变量用于计算：result是对应的int结果，negative对应是否是负数的判断，i是遍历用的索引指针，max代表字符串的长度，limit是合法数字的上限（下限），digit是当前扫描到的字符对应的数字，multmin是在做乘法计算时能走到的合法下限。</p> <p>严谨是这段程序最大的特点，因为有符号int的上下限是-2147483648~2147483647，可见负数表达的范围比正数多一个，这样就好理解为什么在开头要把limit全部表达为负数（下限），这样的操作减少了后续的判断，可以一步到位，相当于二者选择取其大一样，大的包含了小的。同理，那么multmin也就是负数了，而且可以认为是只和进制参数radix有关系。接着每个char的扫描计算digit利用到了Character.digit(char,int) 方法，这个方法就是在调用CharacterDataLatin1.digit(codePoint, radix) 方法，而这个新的方法其实只是去静态数组中取个映射而已。最后当顺利的执行完while循环后，result结果也就计算好了。</p> <p>作为程序设计人员，我最初接触的语言是C++，当初用到的库函数是atoi，那么我们看看atoi的库标准实现：</p><pre>int
atoi(str)
	const char *str;
{
	_DIAGASSERT(str != NULL);

	return((int)strtol(str, (char **)NULL, 10));
}</pre><pre><font face="微软雅黑">其中调用了strtol方法，参数传递的radix是10，也就是说我们常用的atoi是默认转化字符串到10进制的。其中开始时还进行了一个trim的操作，而且支持16进制的0x开头，可谓完全的尽善尽美啊。</font></pre><pre><font face="微软雅黑">strtol方法：</font></pre><pre>#define	_FUNCNAME	strtol
#define	__INT		long
#define	__INT_MIN	LONG_MIN
#define	__INT_MAX	LONG_MAX</pre><pre>__INT
_FUNCNAME(const char *nptr, char **endptr, int base)
{
	const char *s;
	__INT acc, cutoff;
	char c;
	int i, neg, any, cutlim;

	_DIAGASSERT(nptr != NULL);
	/* endptr may be NULL */

	/* check base value */
	if (base &amp;&amp; (base &lt; 2 || base &gt; 36)) {
		errno = EINVAL;
		return(0);
	}

	/*
	 * Skip white space and pick up leading +/- sign if any.
	 * If base is 0, allow 0x for hex and 0 for octal, else
	 * assume decimal; if base is already 16, allow 0x.
	 */
	s = nptr;
	do {
		c = *s++;
	} while (isspace(c));
	if (c == '-') {
		neg = 1;
		c = *s++;
	} else {
		neg = 0;
		if (c == '+')
			c = *s++;
	}
	if ((base == 0 || base == 16) &amp;&amp;
	    c == '0' &amp;&amp; (*s == 'x' || *s == 'X')) {
		c = s[1];
		s += 2;
		base = 16;
	}
	if (base == 0)
		base = c == '0' ? 8 : 10;

	/*
	 * Compute the cutoff value between legal numbers and illegal
	 * numbers.  That is the largest legal value, divided by the
	 * base.  An input number that is greater than this value, if
	 * followed by a legal input character, is too big.  One that
	 * is equal to this value may be valid or not; the limit
	 * between valid and invalid numbers is then based on the last
	 * digit.  For instance, if the range for longs is
	 * [-2147483648..2147483647] and the input base is 10,
	 * cutoff will be set to 214748364 and cutlim to either
	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
	 * a value &gt; 214748364, or equal but the next digit is &gt; 7 (or 8),
	 * the number is too big, and we will return a range error.
	 *
	 * Set any if any `digits' consumed; make it negative to indicate
	 * overflow.
	 */
	cutoff = neg ? __INT_MIN : __INT_MAX;
	cutlim = (int)(cutoff % base);
	cutoff /= base;
	if (neg) {
		if (cutlim &gt; 0) {
			cutlim -= base;
			cutoff += 1;
		}
		cutlim = -cutlim;
	}
	for (acc = 0, any = 0;; c = *s++) {
		if (!isascii(c))
			break;
		if (isdigit(c))
			i = c - '0';
		else if (isalpha(c))
			i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
		else
			break;
		if (i &gt;= base)
			break;
		if (any &lt; 0)
			continue;
		if (neg) {
			if (acc &lt; cutoff || (acc == cutoff &amp;&amp; i &gt; cutlim)) {
				any = -1;
				acc = __INT_MIN;
				errno = ERANGE;
			} else {
				any = 1;
				acc *= base;
				acc -= i;
			}
		} else {
			if (acc &gt; cutoff || (acc == cutoff &amp;&amp; i &gt; cutlim)) {
				any = -1;
				acc = __INT_MAX;
				errno = ERANGE;
			} else {
				any = 1;
				acc *= base;
				acc += i;
			}
		}
	}
	if (endptr != 0)
		/* LINTED interface specification */
		*endptr = __DECONST(char *, (any ? s - 1 : nptr));
	return(acc);
}</pre><pre>&nbsp;</pre><pre><font face="微软雅黑">当然，类似的代码还有很多，这里只列出了两大语言的库实现，总体思路是一致的，当我们设计api时，这种编程思路和风格以及功能的考虑是我们需要学习的。</font></pre><pre><font face="微软雅黑">下面这两篇stackoverflow的问答给出了一些比较全面的c风格代码，可以参考，这里不贴全文只给link：</font></pre><pre><a href="http://stackoverflow.com/questions/194465/how-to-parse-a-string-to-an-int-in-c">http://stackoverflow.com/questions/194465/how-to-parse-a-string-to-an-int-in-c</a></pre><pre><a href="http://stackoverflow.com/questions/4442658/c-parse-int-from-string">http://stackoverflow.com/questions/4442658/c-parse-int-from-string</a></pre><pre><font face="微软雅黑">参考文献：</font></pre><pre><font face="微软雅黑">jdk文档及源码</font></pre><pre><font face="微软雅黑">c库函数源码及文档</font></pre><img src ="http://www.blogjava.net/changedi/aggbug/373454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/changedi/" target="_blank">changedi</a> 2012-04-06 12:20 <a href="http://www.blogjava.net/changedi/archive/2012/04/06/373454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分享一个ThreadMonitor</title><link>http://www.blogjava.net/changedi/archive/2012/02/20/370359.html</link><dc:creator>changedi</dc:creator><author>changedi</author><pubDate>Mon, 20 Feb 2012 11:36:00 GMT</pubDate><guid>http://www.blogjava.net/changedi/archive/2012/02/20/370359.html</guid><wfw:comment>http://www.blogjava.net/changedi/comments/370359.html</wfw:comment><comments>http://www.blogjava.net/changedi/archive/2012/02/20/370359.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/changedi/comments/commentRss/370359.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/changedi/services/trackbacks/370359.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 分享一个ThreadMonitor，来自commons-io的一段小程序，感觉会有用，拿来分享一下&nbsp;&nbsp;<a href='http://www.blogjava.net/changedi/archive/2012/02/20/370359.html'>阅读全文</a><img src ="http://www.blogjava.net/changedi/aggbug/370359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/changedi/" target="_blank">changedi</a> 2012-02-20 19:36 <a href="http://www.blogjava.net/changedi/archive/2012/02/20/370359.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>