`
mysky1984
  • 浏览: 8872 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论
收藏列表
标题 标签 来源
通用分页算法
一般算法:
int row=200; //记录总数
int page=5;//每页数量
int count=row%5==0?row/page:row/page+1;

非判断的算法:
int row=21;
int pageCount=5;
int sum=(row-1)/pageCount+1;//这样就计算好了页码数量,逢1进1
System.out.println(sum);
jquery plugin
http://www.jqueryscript.net/

bootstrap: http://www.sharethemes.cn/demo/se7en/timeline.html
requestAnimationFrame
http://www.zhangxinxu.com/wordpress/2013/09/css3-animation-requestanimationframe-tween-%E5%8A%A8%E7%94%BB%E7%AE%97%E6%B3%95/

http://www.jiawin.com/requestanimationframe-animation-windmill

/* requestAnimationFrame.js
 * by zhangxinxu 2013-09-30
*/
(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||    // name has changed in Webkit
                                      window[vendors[x] + 'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
            var id = window.setTimeout(function() {
                callback(currTime + timeToCall);
            }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
    }
}());
标题截断处理(正则)
name.split("[-,;_.—,、((-]")
domain regex
1、^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,6}$
2、^([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}$


http://www.mkyong.com/regular-expressions/domain-name-regular-expression-example/
描述:
^			    #Start of the line
 (			    #Start of group #1
	(?! -)		    #Can't start with a hyphen
	[A-Za-z0-9-]{1,63}  #Domain name is [A-Za-z0-9-], between 1 and 63 long
	(?<!-)		    #Can't end with hyphen
	\\.		    #Follow by a dot "."
 )+			    #End of group #1, this group must appear at least 1 time, but allowed multiple times for subdomain 
 [A-Za-z]{2,6}		    #TLD is [A-Za-z], between 2 and 6 long
$			    #end of the line
正则包含等
Regex (Contains Word or not) 
Contains: ^.*regexp.*$
Not Contains: ^((?!regexp).)*$
Not contains more words: ^((?!regexp1|regexp2).)*$

Helper links:

http://www.regular-expressions.info/completelines.html
http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#getstarted
http://hugege.com/2008/11/29/regular-expression/
http://regexpal.com/
jQuery Marquee Plugin with CSS3 Support
http://aamirafridi.com/jquery/jquery-marquee-plugin#examples

https://github.com/aamirafridi/jQuery.Marquee
ie6相关问题及处理
1、IE6怪异解析之padding与border算入宽高
原因:未加文档声明造成非盒模型解析
解决方法:加入文档声明<!doctype html>

2、IE6在块元素、左右浮动、设定marin时造成margin双倍(双边距)
解决方法:display:inline

3、以下三种其实是同一种bug,其实也不算是个bug,举个例子:父标签高度20,子标签11,垂直居中,20-11=9,9要分给文字的上面与下面,怎么分?IE6就会与其它的不同,所以,尽量避免。
1)字体大小为奇数之边框高度少1px
解决方法:字体大小设置为偶数或line-height为偶数
2)line-height,文本垂直居中差1px
解决方法:padding-top代替line-height居中,或line-height加1或减1
3)与父标签的宽度的奇偶不同的居中造成1px的偏离
解决方法:如果父标签是奇数宽度,则子标签也用奇数宽度;如果是父标签偶数宽度,则子标签也用偶数宽度

4、内部盒模型超出父级时,父级被撑大
解决方法:父标签使用overflow:hidden

5、line-height默认行高bug
解决方法:line-height设值

6、行标签之间会有一小段空白
解决方法:float或结构并排(可读性差,不建议)

7、标签高度无法小于19px
解决方法:overflow: hidden;

8、左浮元素margin-bottom失效
解决方法:显示设置高度 or 父标签设置_padding-bottom代替子标签的margin-bottom or 再放个标签让父标签浮动,子标签
margin- bottom,即(margin-bottom与float不同时作用于一个标签)

9、img于块元素中,底边多出空白
解决方法:父级设置overflow: hidden; 或 img { display: block; } 或 _margin: -5px;

10、li之间会有间距
解决方法:float: left;

11、块元素中有文字及右浮动的行元素,行元素换行
解决方法:将行元素置于块元素内的文字前

12、position下的left,bottom错位
解决方法:为父级(relative层)设置宽高或添加*zoom:1

13、子级中有设置position,则父级overflow失效
解决方法:为父级设置position:relative

以下是补充:上面要先看

1、终极方法:条件注释
<!--[if lte IE 6]> 这段文字仅显示在 IE6及IE6以下版本。 <![endif]-->
<!--[if gte IE 6]> 这段文字仅显示在 IE6及IE6以上版本。 <![endif]-->
<!--[if gt IE 6]> 这段文字仅显示在 IE6以上版本(不包含IE6)。 <![endif]-->
<!--[if IE 5.5]> 这段文字仅显示在 IE5.5。 <![endif]-->
<!--在 IE6及IE6以下版本中加载css-->
<!--[if lte IE 6]> <link type="text/css" rel="stylesheet" href="css/ie6.css" mce_href="css/ie6.css" /><![endif]-->
缺点是在IE浏览器下可能会增加额外的HTTP请求数。

2、CSS选择器区分
IE6不支持子选择器;先针对IE6使用常规申明CSS选择器,然后再用子选择器针对IE7+及其他浏览器。

复制代码
代码如下:

/* IE6 专用 */
.content {color:red;}
/* 其他浏览器 */
div>p .content {color:blue;} -->

3、PNG半透明图片的问题
虽然可以通过JS等方式解决,但依然存在载入速度等问题,所以,这个在设计上能避免还是尽量避免为好。以达到网站最大优化。
4、IE6下的圆角
IE6不支持CSS3的圆角属性,性价比最高的解决方法就是用图片圆角来替代,或者放弃IE6的圆角。

5、IE6背景闪烁
如果你给链接、按钮用CSS sprites作为背景,你可能会发现在IE6下会有背景图闪烁的现象。造成这个的原因是由于IE6没有将背景图缓存,每次触发hover的时候都会重新加载,可以用JavaScript设置IE6缓存这些图片:

复制代码
代码如下:

document.execCommand("BackgroundImageCache",false,true);

6、最小高度
IE6 不支持min-height属性,但它却认为height就是最小高度。解决方法:使用ie6不支持但其余浏览器支持的属性!important。

复制代码
代码如下:

#container {min-height:200px; height:auto !important; height:200px;}

7、最大高度

复制代码
代码如下:

//直接使用ID来改变元素的最大高度
var container = document.getElementById('container');
container.style.height = (container.scrollHeight > 199) ? "200px" : "auto";
//写成函数来运行
function setMaxHeight(elementId, height){
var container = document.getElementById(elementId);
container.style.height = (container.scrollHeight > (height - 1)) ? height + "px" : "auto";
}
//函数示例
setMaxHeight('container1', 200);
setMaxHeight('container2', 500);

8、100% 高度
在IE6下,如果要给元素定义100%高度,必须要明确定义它的父级元素的高度,如果你需要给元素定义满屏的高度,就得先给html和body定义height:100%;。

9、最小宽度
同max-height和max-width一样,IE6也不支持min-width。

复制代码
代码如下:

//直接使用ID来改变元素的最小宽度
var container = document.getElementById('container');
container.style.width = (container.clientWidth < width) ? "500px" : "auto";
//写成函数来运行
function setMinWidth(elementId, width){
var container = document.getElementById(elementId);
container.style.width = (container.clientWidth < width) ? width + "px" : "auto";
}
//函数示例
setMinWidth('container1', 200);
setMinWidth('container2', 500);

10、最大宽度

复制代码
代码如下:

//直接使用ID来改变元素的最大宽度
var container = document.getElementById(elementId);
container.style.width = (container.clientWidth > (width - 1)) ? width + "px" : "auto";
//写成函数来运行
function setMaxWidth(elementId, width){
var container = document.getElementById(elementId);
container.style.width = (container.clientWidth > (width - 1)) ? width + "px" : "auto";
}
//函数示例
setMaxWidth('container1', 200);
setMaxWidth('container2', 500);

11、双边距Bug
当元素浮动时,IE6会错误的把浮动方向的margin值双倍计算。个人觉得较好解决方法是避免float和margin同时使用。

12、清除浮动
如果你想用div(或其他容器)包裹一个浮动的元素,你会发现必须给div(容器)定义明确的height、width、overflow之中一个属性(除了auto值)才能将浮动元素严实地包裹。

复制代码
代码如下:

#container {border:1px solid #333; overflow:auto; height:100%;}
#floated1 {float:left; height:300px; width:200px; background:#00F;}
#floated2 {float:right; height:400px; width:200px; background:#F0F;}
更多:http://www.twinsenliang.net/skill/20090413.html

13、浮动层错位
当内容超出外包容器定义的宽度时,在IE6中容器会忽视定义的width值,宽度会错误地随内容宽度增长而增长。
浮动层错位问题在IE6下没有真正让人满意的解决方法,虽然可以使用overflow:hidden;或overflow:scroll;来修正, 但hidden容易导致其他一些问题,scroll会破坏设计;JavaScript也没法很好地解决这个问题。所以建议是一定要在布局上避免这个问题发 生,使用一个固定的布局或者控制好内容的宽度(给内层加width)。

14、躲猫猫bug
在IE6和IE7下,躲猫猫bug是一个非常恼人的问题。一个撑破了容器的浮动元素,如果在他之后有不浮动的内容,并且有一些定义了:hover的链接,当鼠标移到那些链接上时,在IE6下就会触发躲猫猫。
解决方法很简单:
1.在(那个未浮动的)内容之后添加一个<span style="clear: both;"> </span>
2.触发包含了这些链接的容器的hasLayout,一个简单的方法就是给其定义height:1%;

15、绝对定位元素的1像素间距bug
IE6下的这个错误是由于进位处理误差造成(IE7已修复),当绝对定位元素的父元素高或宽为奇数时,bottom和right会产生错误。唯一的解决办法就是给父元素定义明确的高宽值,但对于液态布局没有完美的解决方法。

16、3像素间距bug
在IE6中,当文本(或无浮动元素)跟在一个浮动的元素之后,文本和这个浮动元素之间会多出3像素的间隔。
给浮动层添加 display:inline 和 -3px 负值margin
给中间的内容层定义 margin-right 以纠正-3px

17、IE下z-index的bug
在IE浏览器中,定位元素的z-index层级是相对于各自的父级容器,所以会导致z-index出现错误的表现。解决方法是给其父级元素定义z-index,有些情况下还需要定义position:relative。

18、Overflow Bug
在IE6/7中,overflow无法正确的隐藏有相对定位position:relative;的子元素。解决方法就是给外包容器.wrap加上position:relative;。

19、横向列表宽度bug
如果你使用float:left;把<li>横向摆列,并且<li>内包含的<a>(或其他)触发了 hasLayout,在IE6下就会有错误的表现。解决方法很简单,只需要给<a>定义同样的float:left;即可。

20、列表阶梯bug
列表阶梯bug通常会在给<li>的子元素<a>使用float:left;时触发,我们本意是要做一个横向的列表(通常 是导航栏),但IE却可能呈现出垂直的或者阶梯状。解决办法就是给<li>定义float:left;而非子元素<a>,或者 给<li>定义display:inline;也可以解决。

21、垂直列表间隙bug
当我们使用<li> 包含一个块级子元素时,IE6(IE7也有可能)会错误地给每条列表元素(<li>)之间添加空隙。
解决方法:把<a>flaot并且清除float来解决这个问题;另外一个办法就是触发<a>的hasLayout(如定 义高宽、使用zoom:1;);也可以给<li> 定义display:inline;来解决此问题;另外还有一个极有趣的方法,给包含的文本末尾添加一个空格。

22、IE6中的:hover
在IE6中,除了(需要有href属性)才能触发:hover行为,这妨碍了我们实现许多鼠标触碰效果,但还是有一些法子是可以解决它的。最好是不要用:hover来实现重要的功能,仅仅只用它来强化效果。

23、IE6调整窗口大小的 Bug
当把body居中放置,改变IE浏览器大小的时候,任何在body里面的相对定位元素都会固定不动了。解决办法:给body定义position:relative;就行了。

24、文本重复Bug
在IE6中,一些隐藏的元素(如注释、display:none;的元素)被包含在一个浮动元素里,就有可能引发文本重复bug。解决办法:给浮动元素添加display:inline;。

http://www.jb51.net/css/76894.html
盒子模型
ie 盒子模型的范围也包括 margin、border、padding、content,和标准 w3c 盒子模型不同的是:ie 盒子模型的 content 部分包含了 border 和 pading。

   例:一个盒子的 margin 为 20px,border 为 1px,padding 为 10px,content 的宽为 200px、高为 50px,假如用标准 w3c 盒子模型解释,那么这个盒子需要占据的位置为:宽 20*2+1*2+10*2+200=262px、高 20*2+1*2*10*2+50=112px,盒子的实际大小为:宽 1*2+10*2+200=222px、高 1*2+10*2+50=72px;假如用ie 盒子模型,那么这个盒子需要占据的位置为:宽 20*2+200=240px、高 20*2+50=70px,盒子的实际大小为:宽 200px、高 50px。

  那应该选择哪中盒子模型呢?当然是“标准 w3c 盒子模型”了。怎么样才算是选择了“标准 w3c 盒子模型”呢?很简单,就是在网页的顶部加上 doctype 声明。假如不加 doctype 声明,那么各个浏览器会根据自己的行为去理解网页,即 ie 浏览器会采用 ie 盒子模型去解释你的盒子,而 ff 会采用标准 w3c 盒子模型解释你的盒子,所以网页在不同的浏览器中就显示的不一样了。反之,假如加上了 doctype 声明,那么所有浏览器都会采用标准 w3c 盒子模型去解释你的盒子,网页就能在各个浏览器中显示一致了。

  再用 jquery 做的例子来证实一下。

  代码1:

    <html>
    <head>
    <title>你用的盒子模型是?</title>
    <script language="javascript" src="jquery.min.js"></script>
    <script language="javascript">
    var sbox = $.boxmodel ? "标准w3c":"ie";
    document.write("您的页面目前支持:"+sbox+"盒子模型");
    </script>
    </head>
    <body>
    </body>
    </html>

  上面的代码没有加上 doctype 声明,在 ie 浏览器中显示“ie盒子模型”,在 ff 浏览器中显示“标准 w3c 盒子模型”。

  代码2:

    <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
    <html>
    <head>
    <title>你用的盒子模型是标准w3c盒子模型</title>
    <script language="javascript" src="jquery.min.js"></script>
    <script language="javascript">
    var sbox = $.boxmodel ? "标准w3c":"ie";
    document.write("您的页面目前支持:"+sbox+"盒子模型");
    </script>
    </head>
    <body>
    </body>
    </html>

  代码2 与代码1 唯一的不同的就是顶部加了 doctype 声明。在所有浏览器中都显示“标准 w3c 盒子模型”。

  所以为了让网页能兼容各个浏览器,让我们用标准 w3c 盒子模型。

http://www.cnblogs.com/cchyao/archive/2010/07/12/1775846.html
js 闭包
闭包的简单概念:闭包就是能够读取其他函数内部变量的函数。

函数内部的函数闭包的两个最大的作用:
1、读取函数内部的变量
2、变量的值始终保持在内存中
   function A()
   {
    var n=999;
    nAdd=function(){
           n+=1 
       }
    function B(){
           alert(n);
       }
    return B;
  }
  var result=A();
  result(); // 999
  nAdd();
  result(); // 1000
js 倒计时
/**
* 倒计时通用设置
*/
function countdown(target, date, func) {
	var temp = target.countdown({
		hourText: ':',
		minText: ':',
		secText: '',
		hourSingularText: ':',
    	minSingularText: ':',
		secSingularText: '',
		leadingZero: true,
		date: date,
		template: '%i %s',
		onComplete: function(event) {
			func.call();
		}
	});
	return temp;
}

https://github.com/tomgrohl/jCountdown/
js 数字效果
function commaSeparateNumber(val) {
	    while (/(\d+)(\d{3})/.test(val.toString())){
	      val = val.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
	    }
	    return val;
	}
  
	function magic_number(target, value) {
	    target.animate({count: value}, { 
	        duration: 500, 
	        easing: 'swing',
	        step: function() { 
	            target.text(commaSeparateNumber(parseInt(this.count)));  // String(parseInt(this.count))
	        }
	    }); 
	}; 
	
	function magic_rationumber(target, value) {
	    target.animate({count: value}, { 
	        duration: 3000, 
	        easing: 'easeOutCubic',
	        step: function() { 
	            target.text(parseInt(this.count) + '%');  // String(parseInt(this.count))
	        }
	    }); 
	}; 
	
	
	setInterval(function() {
		magic_number($('#wetRequest'), Math.random() * 1000000000); 
		magic_number($('#webClick'), Math.random() * 1000000000); 
		magic_rationumber($('#webClickRatio'), Math.random() * 100); 
	}, 5000);
js 文本选择
var userSelection, text;
    if (window.getSelection) { 
        //现代浏览器
        userSelection = window.getSelection();
    } else if (document.selection) { 
        //IE浏览器 考虑到Opera,应该放在后面
        userSelection = document.selection.createRange();
    }
    if (!(text = userSelection.text)) {
        text = userSelection;
    }


http://www.zhangxinxu.com/wordpress/?p=1591
JS表格排序
appendChild:1、先把元素从原有的父级上删掉。2、添加到新的父级。

排序的原理:从一堆数里找出一个最小的数用appendChild插入到最后,再在剩下的数里找最小的数用appendChild插入到最后,如此重复就能找把所有的数实现排序。

表格排序思路:

1、获取元素。

2、创建一个空数组 var arr=[];

3、用for循环把表格的每行数赋值给数组 arr[i]=oTable.tBodies[0].rows[i];

4、用sort()把数组里面的元素进行排序。

5、用for循环把数组里排好序的数用appendChild插入到tBodies。

完整代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>排序</title>
<script>
window.onload=function()
{
    var oBtn=document.getElementById('btn');
    var oTable=document.getElementById('table');
    
    oBtn.onclick=function()
    {
        var arr=[];
        for(var i=0;i<oTable.tBodies[0].rows.length;i++)
        {
            arr[i]=oTable.tBodies[0].rows[i];
        };
        
        arr.sort(function(tr1,tr2){
            n1=parseInt(tr1.cells[0].innerHTML);
            n2=parseInt(tr2.cells[0].innerHTML);
            return n1-n2;
        });    
        
        for(var i=0;i<arr.length;i++)
        {
            oTable.tBodies[0].appendChild(arr[i]);
        };
    };
};
</script>
</head>

<body>
<input type="button" value="排序" id="btn" />
<table id="table" border="1" width="100%" cellpadding="0" cellspacing="0">
    <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>专业</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>58</td>
            <td>Simon</td>
            <td>网站设计</td>
        </tr>
        <tr>
            <td>20</td>
            <td>Melon</td>
            <td>网站设计</td>
        </tr>
        <tr>
            <td>98</td>
            <td>张三</td>
            <td>物流</td>
        </tr>
        <tr>
            <td>87</td>
            <td>李四三</td>
            <td>物流</td>
        </tr>
        <tr>
            <td>798</td>
            <td>张三</td>
            <td>物流</td>
        </tr>
    </tbody>
</table>
</body>
</html>
java 图片 尺寸
File file = new File("C:\\Koala.jpg");
BufferedImage bi = ImageIO.read(file);int width = bi.getWidth();int height = bi.getHeight();

这种方式代码很简单,但是效率是很差的,ImageIO将图片文件读入内存,以便进行更多的操作。java中还有ImageReader这个类,使用这个类避免将图片全部解码,这里是官方的文档说明。 要使用这个类,也需要ImageIO这个类得到ImageReader的迭代器,支持多种获取的方式,然后将图像文件设置为ImageReader的输入源。就可以通过ImageReader来获取图片的长宽信息了。  

//通过文件的类型获取
 Iterator readers = ImageIO.getImageReadersByFormatName("jpg");
//通过文件的后缀获取
 Iterator readers = ImageIO.getImageReadersBySuffix("jpg");
ImageReader reader = readers.next();
File file = new File("C:\\Koala.jpg");
ImageInputStream input = ImageIO.createImageInputStream(file);
reader.setInput(input, true);
int width = reader.getWidth(0);
int height = reader.getHeight(0);

select2 搜索 中文乱码
js: data: function (params) {
			      return {
			        input: encodeURI(decodeURIComponent(params.term, true)), // search term
			        type: '${type!""}'
			      };
			    },

java :input = java.net.URLDecoder.decode(new String(input.getBytes("ISO-8859-1" ),"UTF-8") , "UTF-8");
list 删除
for (Iterator<PosConf> it = list.iterator(); it.hasNext();) {
                PosConf posConf = it.next();
                if ("all".equals(posConf.getPosId()))
                    it.remove();
            }
js string format
var JQUERY4U = {};
JQUERY4U.UTIL = {
	formatVarString: function() {
        var args = [].slice.call(arguments);
        if(this.toString() != '[object Object]') {
            args.unshift(this.toString());
        }
        var pattern = new RegExp('{([1-' + args.length + '])}','g');
        return String(args[0]).replace(pattern, function(match, index) { return args[index]; });
    }
}
//JQUERY4U.UTIL.formatVarString('{1} is a {2} aimed to help you learn {3}.', 'jQuery4u', 'blog', 'jQuery')

String.format = function() {
    if (arguments.length == 0)
        return null;
    var str = arguments[0];
    for ( var i = 1; i < arguments.length; i++) {
        var re = new RegExp('\\{' + (i - 1) + '\\}', 'gm');
        str = str.replace(re, arguments[i]);
    }
    return str;
};
//String.format('{0} is a {1} aimed to help you learn {2}.', 'jQuery4u', 'blog', 'jQuery')
htmlparser.jar
 Parser parser = new Parser();
                parser.setURL(xx.getGoodsUrl());
                NodeFilter filter = new AndFilter(new TagNameFilter("dt"), new HasAttributeFilter("class", "subTit"));
                NodeList list = parser.parse(filter);
                if (list.size() == 1) {
                    String des = list.elementAt(0).toPlainTextString();
                    logger.info(xx.getAdid() + ":" + des);
                    if (!StringUtils.isBlank(des)) {
                        xx.setDescript(des);
                    }
                }
jQuery accordion hack
// hack
			$('#accordion h3').attr('class', 'ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-accordion-icons').off('click').click(function() {
				if($(this).next().is(':hidden')) {
					$(this).find('span').attr('class', 'ui-accordion-header-icon ui-icon ui-icon-triangle-1-s');
				} else {
					$(this).find('span').attr('class', 'ui-accordion-header-icon ui-icon ui-icon-triangle-1-e');
				}
		        $(this).next().toggle('fast');
		    });
JSON数组排序
JSONArray valueArray = JSONArray.parseArray("json array str");
ComparatorChain compChain = new ComparatorChain();
                Comparator comp = ComparableComparator.getInstance();
                comp = ComparatorUtils.reversedComparator(comp); // 降序排, 不调用则升序排
                compChain.addComparator(new BeanComparator("count", comp));
                Collections.sort(valueArray, compChain);
Calendar 类 format线程安全问题
http://bijian1013.iteye.com/blog/1873336

解决SimpleDateFormat的线程不安全问题的方法

    博客分类: java多线程 

javathreadSimpleDateFormat线程安全 

在Java项目中,我们通常会自己写一个DateUtil类,处理日期和字符串的转换,如下所示:
Java代码  收藏代码

    public class DateUtil01 {  
      
        private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
      
        public void format(Date date) {  
            System.out.println(dateformat.format(date));  
        }  
      
        public void parse(String str) {  
            try {  
                System.out.println(dateformat.parse(str));  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

 然而,由于SimpleDateFormat类不是线程安全的,所以在多线程的环境下,往往会出现意想不到的结果。
 如下是我写的测试其是否存在安全问题的实例:

1.日期工具处理类的接口
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.util.Date;  
      
    public interface DateUtilInterface {  
      
        public void format(Date date);  
        public void parse(String str);  
    }  

 

2.日期工具实现类
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
      
    public class DateUtil01 implements DateUtilInterface {  
      
        private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
      
        @Override  
        public void format(Date date) {  
            System.out.println(dateformat.format(date));  
        }  
      
        @Override  
        public void parse(String str) {  
            try {  
                System.out.println(dateformat.parse(str));  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

 

3.调用日期工具的线程类
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.util.Calendar;  
    import java.util.Date;  
      
    public class DateThread implements Runnable {  
      
        DateUtilInterface dateUtil = null;  
      
        public DateThread(DateUtilInterface dateUtil) {  
            this.dateUtil = dateUtil;  
        }  
      
        public void run() {  
            int year = 2000;  
            Calendar cal;  
            for (int i = 1; i < 100; i++) {  
                System.out.println("no." + i);  
                year++;  
                cal = Calendar.getInstance();  
                cal.set(Calendar.YEAR, year);  
                //Date date = cal.getTime();  
                //dateUtil.format(date);  
                dateUtil.parse(year + "-05-25 11:21:21");  
                try {  
                    Thread.sleep(1);  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  

 

4.测试主方法
Java代码  收藏代码

    package com.bijian.study.date;  
      
    public class DateMainTest {  
      
        public static void main(String[] args) {  
              
            DateUtilInterface dateUtil = new DateUtil01();  
            Runnable runabble = new DateThread(dateUtil);  
            for(int i=0;i<10;i++){  
                new Thread(runabble).start();  
            }  
        }  
    }  

 

运行结果:
Text代码  收藏代码

    no.1  
    no.1  
    no.1  
    Fri May 25 11:21:21 CST 2001  
    Fri May 25 11:21:21 CST 2001  
    Fri May 25 11:21:21 CST 2001  
    no.1  
    no.1  
    Fri May 25 11:21:21 CST 2001  
    Fri May 25 11:21:21 CST 2001  
    no.1  
    no.1  
    Fri May 25 11:21:21 CST 2001  
    no.1  
    Fri May 25 11:21:21 CST 2001  
    no.1  
    Fri May 25 11:00:21 CST 2001  
    Wed Sep 25 11:21:21 CST 2002  
    no.1  
    no.2  
    no.2  
    Sat May 25 11:21:21 CST 2002  
    no.2  
    no.2  
    no.2  
    Sat May 25 11:21:21 CST 2002  
    no.2  
    Sat May 25 11:21:21 CST 2002  
    Fri May 25 11:21:21 CST 2001  
    Sat May 25 11:21:21 CST 2002  
    no.2  
    Sat May 25 11:21:21 CST 2002  
    no.2  
    Sat May 25 11:21:21 CST 2002  
    no.2  
    Sat May 25 11:21:21 CST 2002  
    Exception in thread "Thread-2" java.lang.NumberFormatException: For input string: ".00221E.00221E4"  
        at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)  
        at java.lang.Double.parseDouble(Unknown Source)  
        at java.text.DigitList.getDouble(Unknown Source)  
        at java.text.DecimalFormat.parse(Unknown Source)  
        at java.text.SimpleDateFormat.subParse(Unknown Source)  
        at java.text.SimpleDateFormat.parse(Unknown Source)  
        at java.text.DateFormat.parse(Unknown Source)  
        at com.bijian.study.date.DateUtil01.parse(DateUtil01.java:19)  
        at com.bijian.study.date.DateThread.run(DateThread.java:24)  
        at java.lang.Thread.run(Unknown Source)  
    Exception in thread "Thread-5" java.lang.NumberFormatException: For input string: ".00221E.00221E44"  
        at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)  
        at java.lang.Double.parseDouble(Unknown Source)  
        at java.text.DigitList.getDouble(Unknown Source)  
        at java.text.DecimalFormat.parse(Unknown Source)  
        at java.text.SimpleDateFormat.subParse(Unknown Source)  
        at java.text.SimpleDateFormat.parse(Unknown Source)  
        at java.text.DateFormat.parse(Unknown Source)  
        at com.bijian.study.date.DateUtil01.parse(DateUtil01.java:19)  
        at com.bijian.study.date.DateThread.run(DateThread.java:24)  
        at java.lang.Thread.run(Unknown Source)  
    no.3  
    no.3  
    Sun May 25 11:21:21 CST 2003  
    no.3  
    no.3  
    no.3  
    Sun May 25 11:21:21 CST 2003  
    no.4  
    Sun May 25 11:21:21 CST 2003  
    no.3  
    Tue May 25 11:21:21 CST 2004  
    no.2  
    Sun May 25 11:21:21 CST 2003  
    no.3  
    Thu Jan 01 00:21:21 CST 1970  
    Exception in thread "Thread-7" Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "E212"  
        at java.lang.NumberFormatException.forInputString(Unknown Source)  
        at java.lang.Long.parseLong(Unknown Source)  
        at java.lang.Long.parseLong(Unknown Source)  
        at java.text.DigitList.getLong(Unknown Source)  
        at java.text.DecimalFormat.parse(Unknown Source)  
        at java.text.SimpleDateFormat.subParse(Unknown Source)  
        at java.text.SimpleDateFormat.parse(Unknown Source)  
        at java.text.DateFormat.parse(Unknown Source)  
        at com.bijian.study.date.DateUtil01.parse(DateUtil01.java:19)  
        at com.bijian.study.date.DateThread.run(DateThread.java:24)  
        at java.lang.Thread.run(Unknown Source)  
    java.lang.NumberFormatException: For input string: "E212"  
        at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)  
        at java.lang.Double.parseDouble(Unknown Source)  
        at java.text.DigitList.getDouble(Unknown Source)  
        at java.text.DecimalFormat.parse(Unknown Source)  
        at java.text.SimpleDateFormat.subParse(Unknown Source)  
        at java.text.SimpleDateFormat.parse(Unknown Source)  
        at java.text.DateFormat.parse(Unknown Source)  
        at com.bijian.study.date.DateUtil01.parse(DateUtil01.java:19)  
        at com.bijian.study.date.DateThread.run(DateThread.java:24)  
        at java.lang.Thread.run(Unknown Source)  
    Exception in thread "Thread-8" java.lang.NumberFormatException: For input string: ""  
        at java.lang.NumberFormatException.forInputString(Unknown Source)  
        at java.lang.Long.parseLong(Unknown Source)  
        at java.lang.Long.parseLong(Unknown Source)  
        at java.text.DigitList.getLong(Unknown Source)  
        at java.text.DecimalFormat.parse(Unknown Source)  
        at java.text.SimpleDateFormat.subParse(Unknown Source)  
        at java.text.SimpleDateFormat.parse(Unknown Source)  
        at java.text.DateFormat.parse(Unknown Source)  
        at com.bijian.study.date.DateUtil01.parse(DateUtil01.java:19)  
        at com.bijian.study.date.DateThread.run(DateThread.java:24)  
        at java.lang.Thread.run(Unknown Source)  
    no.4  
    no.4  
    ...  
    ...  
    ...  

 

      从如上运行结果来看,SimpleDateFormat的parse方法有线程安全问题。

   修改调用日期工具的线程类如下,测试SimpleDateFormat的format方法是否有线程安全问题:
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.util.Calendar;  
    import java.util.Date;  
      
    public class DateThread implements Runnable {  
      
        DateUtilInterface dateUtil = null;  
      
        public DateThread(DateUtilInterface dateUtil) {  
            this.dateUtil = dateUtil;  
        }  
      
        public void run() {  
            int year = 2000;  
            Calendar cal;  
            for (int i = 1; i < 100; i++) {  
                System.out.println("no." + i);  
                year++;  
                cal = Calendar.getInstance();  
                cal.set(Calendar.YEAR, year);  
                Date date = cal.getTime();  
                dateUtil.format(date);  
                //dateUtil.parse(year + "-05-25 11:21:21");  
                try {  
                    Thread.sleep(1);  
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  

 运行结果:
Text代码  收藏代码

    no.1  
    no.1  
    2001-05-22 13:07:22  
    2001-05-22 13:07:22  
    no.1  
    no.1  
    2001-05-22 13:07:22  
    2001-05-22 13:07:22  
    no.1  
    2001-05-22 13:07:22  
    no.1  
    no.1  
    2001-05-22 13:07:22  
    2001-05-22 13:07:22  
    no.1  
    no.1  
    2001-05-22 13:07:22  
    2001-05-22 13:07:22  
    no.1  
    2001-05-22 13:07:22  
    no.2  
    no.2  
    no.2  
    no.2  
    2002-05-22 13:07:22  
    no.2  
    2002-05-22 13:07:22  
    2002-05-22 13:07:22  
    no.2  
    2002-05-22 13:07:22  
    no.2  
    ...  
    ...  
    ...  

    多次运行,均未出现异常,因此个人预测,SimpleDateFormat的format方法没有线程安全的问题。 

      

        有三种方法可以解决以上安全问题。
  1).使用同步
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
      
    public class DateUtil02 implements DateUtilInterface {  
      
        private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
          
        @Override  
        public void format(Date date) {  
            System.out.println(dateformat.format(date));  
        }  
      
        @Override  
        public void parse(String str) {  
            try {  
                synchronized(dateformat){  
                    System.out.println(dateformat.parse(str));  
                }  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

 修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil01();为DateUtilInterface dateUtil = new DateUtil02();测试OK。

        不过,当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,这样的操作也会一定程度上影响性能。

 

  2).每次使用时,都创建一个新的SimpleDateFormat实例
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
      
    public class DateUtil03 implements DateUtilInterface {  
      
        @Override  
        public void format(Date date) {  
              
            SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
            System.out.println(dateformat.format(date));  
        }  
      
        @Override  
        public void parse(String str) {  
            try {  
                SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
                System.out.println(dateformat.parse(str));  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

 修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil02();为DateUtilInterface dateUtil = new DateUtil03();测试OK。

  

  3).借助ThreadLocal对象每个线程只创建一个实例

     借助ThreadLocal对象每个线程只创建一个实例,这是推荐的方法

     对于每个线程SimpleDateFormat不存在影响他们之间协作的状态,为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本,代码如下:
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.text.DateFormat;  
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
      
    public class DateUtil04 implements DateUtilInterface {  
      
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";  
      
        // 第一次调用get将返回null  
        private static ThreadLocal threadLocal = new ThreadLocal(){  
            protected Object initialValue() {    
                return null;//直接返回null    
            }   
        };  
          
        // 获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中  
        public static DateFormat getDateFormat() {  
            DateFormat df = (DateFormat) threadLocal.get();  
            if (df == null) {  
                df = new SimpleDateFormat(DATE_FORMAT);  
                threadLocal.set(df);  
            }  
            return df;  
        }  
      
        @Override  
        public void parse(String textDate) {  
      
            try {  
                System.out.println(getDateFormat().parse(textDate));  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
      
        @Override  
        public void format(Date date) {  
            System.out.println(getDateFormat().format(date));  
        }  
    }  

 创建一个ThreadLocal类变量,这里创建时用了一个匿名类,覆盖了initialValue方法,主要作用是创建时初始化实例。

         也可以采用下面方式创建。
Java代码  收藏代码

    package com.bijian.study.date;  
      
    import java.text.DateFormat;  
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
      
    public class DateUtil05 implements DateUtilInterface {  
      
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";  
          
        @SuppressWarnings("rawtypes")  
        private static ThreadLocal threadLocal = new ThreadLocal() {  
            protected synchronized Object initialValue() {  
                return new SimpleDateFormat(DATE_FORMAT);  
            }  
        };  
      
        public DateFormat getDateFormat() {  
            return (DateFormat) threadLocal.get();  
        }  
      
        @Override  
        public void parse(String textDate) {  
      
            try {  
                System.out.println(getDateFormat().parse(textDate));  
            } catch (ParseException e) {  
                e.printStackTrace();  
            }  
        }  
      
        @Override  
        public void format(Date date) {  
            System.out.println(getDateFormat().format(date));  
        }  
    }  

    修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil03();为DateUtilInterface dateUtil = new DateUtil04();或者DateUtilInterface dateUtil = new DateUtil05();测试OK。

 

      最后,当然也可以使用apache commons-lang包的DateFormatUtils或者FastDateFormat实现,apache保证是线程安全的,并且更高效。

 

     附:Oracle官方bug说明: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6178997
强制不缓存
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">   

// new
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="Fri, 30 Apr 2010 11:12:01 GMT" />
<meta http-equiv="Expires" content="0" />
<HTTP-EQUIV="PRAGMA" CONTENT="NO-STORE" />
sring util
public static final String regex = "(http:|https:)//[^[A-Za-z0-9\\._\\?%&+\\-=/#]]*";

	public static String extractBefore(String source, String identifier) {
		if (StringUtils.isBlank(source)) {
			return "";
		}
		int index = source.indexOf(identifier);
		if (index != -1) {
			return source.substring(0, index);
		}
		return source;
	}

	public static String getArrayString(String[] ss, String mark) {
		StringBuffer buffer = new StringBuffer();
		if (ss != null && ss.length > 0) {
			for (int i = 0; i < ss.length; i++) {
				if (i > 0)
					buffer.append(",");
				buffer.append(mark + ss[i] + mark);
			}
		}
		return buffer.toString();
	}

	public static String getArrayString(List<String> list, String mark) {
		StringBuffer buffer = new StringBuffer();
		if (list != null && list.size() > 0) {
			for (int i = 0; i < list.size(); i++) {
				if (i > 0)
					buffer.append(",");
				buffer.append(mark + list.get(i) + mark);
			}
		}
		return buffer.toString();
	}

	public static String getMsgHighLight(String message, String keyword) {
		if (StringUtils.isBlank(keyword)) {
			return message;
		}
		Pattern p = Pattern.compile(keyword, Pattern.CASE_INSENSITIVE);
		Matcher matcher = p.matcher(message);
		StringBuffer sb = new StringBuffer();
		boolean flag = false;
		while (matcher.find()) {
			flag = true;
			matcher.appendReplacement(sb, String.format("<msg>%s</msg>", matcher.group()));
		}
		matcher.appendTail(sb);
		if (!flag) {
			return message;
		}
		return sb.toString();
	}

	public static String getMsgLinkTrue(String message) {
		if (StringUtils.isBlank(message)) {
			return message;
		}
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(message);
		StringBuffer sb = new StringBuffer();
		while (matcher.find()) {
			String urlStr = matcher.group();
			StringBuffer replace = new StringBuffer();
			replace.append("<a href=\"").append(urlStr);
			replace.append("\" target=\"_blank\">" + urlStr + "</a>");
			matcher.appendReplacement(sb, replace.toString());
		}
		matcher.appendTail(sb);
		return sb.toString();
	}
spring mvc 多个文件
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();  
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) { 
     MultipartFile file = entity.getValue();
     file.getOriginalFilename());
}
mybatis cache
http://www.iteye.com/topic/1112327
js string format
String.prototype.format = function() {
	var args = arguments;
	return this.replace(/{(\d+)}/g, function(match, i) {
		return typeof args[i] != 'undefined' ? args[i] : match;
	});
};

String.format = function(template) {
	if (0 == arguments.length)
		return null;
	var args = Array.prototype.slice.call(arguments, 1);
	return String.prototype.format.apply(template, args);
}

if (typeof jQuery != 'undefined') {
	jQuery.extend({
		format : function(template) {
			return String.format.apply(template, arguments);
		}
	});
}

// console.log('{0} {1}'.format('hello', 'world'));
// console.log(String.format('{0} {1}', 'hello', 'world'));
// console.log($.format('{0} {1}', 'hello', 'jQuery'));
简单按中文拼音排序
/**
 * 中文字符排序
 * 
 * @date 2015年5月6日
 * @author hzcuijie@corp.netease.com
 */
class SortChineseName implements Comparator<AdIndustryInfo> {
    Collator cmp = Collator.getInstance(java.util.Locale.CHINA);

    @Override
    public int compare(AdIndustryInfo o1, AdIndustryInfo o2) {
        if (cmp.compare(o1.getCategory(), o2.getCategory()) > 0) {
            return 1;
        } else if (cmp.compare(o1.getCategory(), o2.getCategory()) < 0) {
            return -1;
        }
        return 0;
    }

}
Linux java 执行 python
//exec(String[] cmd) - cmd[0]:path of python-3.x cmd[1]:path of your python code cmd[2],[3]:arguments  
    //if you only invoke python code without arguments, `Process p = r.exec("python path-of-your-code");` instead. 
	public static void main(String[] args) {
		try {
			Runtime r = Runtime.getRuntime();
//			String[] cmd = { "/usr/bin/python", "/styx/home/hzcuijie/ConceptNetSimilarity.py", "cat", "dog" };
			String[] cmd = { "cmd", "/c", "D:\\ConceptNetSimilarity.py", "cat", "dog" };
			Process p = r.exec(cmd); //"cmd /c D:\\ConceptNetSimilarity.py cat dog"
			p.waitFor();
			BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line = "";
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}
			p.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
Linux 生成图片文字乱码问题
File f = new File(fontFile);
logger.info("file content..." + f.getAbsoluteFile());
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, f));

在应用启动时设置
Global site tag (gtag.js) - Google Analytics