??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美日韩视频一区二区,日韩精品免费一区二区三区,伊人久久大香线蕉午夜avhttp://www.aygfsteel.com/achan2bj/zh-cnTue, 17 Jun 2025 16:28:19 GMTTue, 17 Jun 2025 16:28:19 GMT60q用Jcaptcha做验证码ȝ http://www.aygfsteel.com/achan2bj/archive/2012/10/18/389790.htmlachan2bjachan2bjThu, 18 Oct 2012 02:16:00 GMThttp://www.aygfsteel.com/achan2bj/archive/2012/10/18/389790.htmlhttp://www.aygfsteel.com/achan2bj/comments/389790.htmlhttp://www.aygfsteel.com/achan2bj/archive/2012/10/18/389790.html#Feedback2http://www.aygfsteel.com/achan2bj/comments/commentRss/389790.htmlhttp://www.aygfsteel.com/achan2bj/services/trackbacks/389790.htmlhttp://my.oschina.net/jawava/blog/8574

发现q个C֌不错Q所以也凑个热闹?/p>

W一日志,一定要动手写才有诚意?/p> q两天要l刚做的外网pȝd面加验证码Q以前没做过。上|搜了一下,资料很多?br style="padding: 0px; margin: 0px;" />验证码校验称作captchaQ?br style="padding: 0px; margin: 0px;" />Completely Automated Public Test to tell Computers and Humans Apart
专业点儿的翻译是Q全自动区分计算机和人类的图灉|试?br style="padding: 0px; margin: 0px;" />CAPTCHA的目的很明确Q就是区分计机和hcȝ一U程序算法,
q种E序必须能生成ƈ评h(hun)人类能很Ҏ(gu)通过但计机却通不q的试?br style="padding: 0px; margin: 0px;" />
|上能查C实现方案,单的写个jspp了,技术含量不高。搜了一圈后Q?br style="padding: 0px; margin: 0px;" />感觉q是用个正规点儿比较合适,然后锁定了JCaptchaQ到其官方网站上看了看:(x)
http://jcaptcha.octo.com/confluence/display/general/Home

JCaptcha提供?br style="padding: 0px; margin: 0px;" />Provide robust and reliable CAPTCHA implementation framework for JAVA
Provide accessible CAPTCHA implementations
Provide multi-type challenge (text, sound, image)

它用上百个类来实C如此单的功能Q这是ؓ(f)什么呢Q官方给的解释是
1、学术界能不断的发明Q或发现Q一些hcd易处理而机器不能很好处理的问题?br style="padding: 0px; margin: 0px;" />JCaptcha高屋建瓴的给Z一U通用的定义和表达q种问题q用于识别的Ҏ(gu)?br style="padding: 0px; margin: 0px;" />也就是识别方案的可扩展性?br style="padding: 0px; margin: 0px;" />2、实C若干引擎和组Ӟ通过配置q些引擎和组Ӟ可以方便的修改自q?br style="padding: 0px; margin: 0px;" />captcha构g的算法。这P在抵御恶意访问时Q可以不用改变代码,灉|快速的
改变captcha{略Q从而更好的保护pȝ?br style="padding: 0px; margin: 0px;" />
个h觉的说的挺好Q第一点对于我们来说倒是ơ要的,主要W二Ҏ(gu)较有意义?br style="padding: 0px; margin: 0px;" />然后p了试。下面是具体需要做的工作:(x)

一Q从官网上下个jcaptcha-1.0-all.jarQ加入到目中,
官方?.0q没有正式版Q所以先?.0吧?br style="padding: 0px; margin: 0px;" />
二,官网上介l了几种和项目结合的具体Ҏ(gu)Q最单的方式很快走通,囄很难看,
而且不具有可配置性,肯定不行。所以选择通过spring来整合的方式Q?br style="padding: 0px; margin: 0px;" />spring是整合和配置的^収ͼ把jcaptcha的服务和引擎q有lg配置成spring的bean?br style="padding: 0px; margin: 0px;" />CZ如下Q?br style="padding: 0px; margin: 0px;" />
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans.dtd">
<beans  default-autowire="byName">

    <bean id="captchaServlet" class="com.jawava.XXXX.XXX.TopImageCaptchaServlet" />

<bean id="captchaService" class="com.octo.captcha.service.multitype.GenericManageableCaptchaService">
<description>验证码服?lt;/description>
<constructor-arg index="0"><ref bean="imageEngine"/></constructor-arg>
<constructor-arg index="1"><value>300</value></constructor-arg><!--时旉 U?->
<constructor-arg index="2"><value>20000</value></constructor-arg><!--最大ƈ发数-->
<constructor-arg index="3"><value>20000</value></constructor-arg>& lt;!--W四个参数官|示例上没有l出Q会(x)报错Q后来看了API才知道少了个参数-->
</bean>

<bean id="imageEngine" class="com.octo.captcha.engine.GenericCaptchaEngine">
<description>囄引擎</description>
<constructor-arg index="0">
<list>
<ref bean="CaptchaFactory"/>
</list>
</constructor-arg>
</bean>

<bean id="CaptchaFactory" class="com.octo.captcha.image.gimpy.GimpyFactory" >
<description>验证码工?lt;/description>
<constructor-arg><ref bean="wordgen"/></constructor-arg>
<constructor-arg><ref bean="wordtoimage"/></constructor-arg>
</bean>

<bean id="wordgen" class= "com.octo.captcha.component.word.wordgenerator.RandomWordGenerator" >
<description>文字产生器,提供了好几种实现Q经q比较选用了这U?lt;/description>
<constructor-arg index="0"><value>0123456789</value></constructor-arg>
</bean>

<bean id="wordtoimage" class="com.octo.captcha.component.image.wordtoimage.ComposedWordToImage" >
<description>囄生成?lt;/description>
<constructor-arg index="0"><ref bean="fontGenRandom"/></constructor-arg>
<constructor-arg index="1"><ref bean="backGenUni"/></constructor-arg>
<constructor-arg index="2"><ref bean="simpleWhitePaster"/></constructor-arg>
</bean>

<bean id="fontGenRandom" class="com.octo.captcha.component.image.fontgenerator.RandomFontGenerator" >
<description>文字转换囄</description>
<constructor-arg index="0"><value>20</value></constructor-arg><!--字体最尺?->
<constructor-arg index="1"><value>20</value></constructor-arg><!--字体最大尺?->
</bean> 

<bean id="backGenUni" class="com.octo.captcha.component.image.backgroundgenerator.GradientBackgroundGenerator" >
<constructor-arg index="0"><value>62</value></constructor-arg><!--背景囄宽度-->
<constructor-arg index="1"><value>22</value></constructor-arg><!--背景囄高度-->
<constructor-arg type="java.awt.Color" index="2">
<ref bean="colorGrey"/>
</constructor-arg> 
<constructor-arg type="java.awt.Color" index="3">
<ref bean="colorGreen"/>
</constructor-arg>

</bean>

<bean id="simpleWhitePaster" class="com.octo.captcha.component.image.textpaster.SimpleTextPaster" >
<constructor-arg type="java.lang.Integer" index="0">
<value>4</value><!--字符最个?->
</constructor-arg>
<constructor-arg type="java.lang.Integer" index="1">
<value>4</value><!--字符最多个?->
</constructor-arg>
<constructor-arg type="java.awt.Color" index="2">
<ref bean="colorFont"/>
</constructor-arg>
</bean>

<bean id="colorGrey" class="java.awt.Color" >
<constructor-arg index="0"><value>200</value></constructor-arg>
<constructor-arg index="1"><value>255</value></constructor-arg>
<constructor-arg index="2"><value>200</value></constructor-arg>
</bean>
<bean id="colorGreen" class="java.awt.Color" >
<constructor-arg index="0"><value>110</value></constructor-arg>
<constructor-arg index="1"><value>120</value></constructor-arg>
<constructor-arg index="2"><value>200</value></constructor-arg>
</bean>
<bean id="colorFont" class="java.awt.Color" >
<constructor-arg index="0"><value>60</value></constructor-arg>
<constructor-arg index="1"><value>60</value></constructor-arg>
<constructor-arg index="2"><value>60</value></constructor-arg>
</bean>
</beans>



q里面具体用哪个component,需要看ApIQ我把包里提供的现成的组件基本上试了大半Q?br style="padding: 0px; margin: 0px;" />最后选择了如上的配置Q选择的标准一是美观,二是识别率。识别率太低了,用户体验?x)下降?br style="padding: 0px; margin: 0px;" />
三、配|好后,JCaptchaq边的工作就完成了。下面就是和目的结合?br style="padding: 0px; margin: 0px;" />1、首先专门写个CaptcahServlet用来获取验证码,׃要在servlet里注入spring的beanQ?br style="padding: 0px; margin: 0px;" />所以用了代理的方式。代理类|上有,都是固定写法Q这里就不脓(chung)了?br style="padding: 0px; margin: 0px;" />CaptcahServlet主要部分如下Q?br style="padding: 0px; margin: 0px;" />
@Override
public void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws ServletException, IOException, RuntimeException {

byte[] captchaChallengeAsJpeg = null;
//输出jpg的字节流
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// get the session id that will identify the generated captcha.
//the same id must be used to validate the response, the session id is a good candidate!
String captchaId = httpServletRequest.getSession().getId();
// call the ImageCaptchaService getChallenge method
BufferedImage challenge =
(BufferedImage) captchaService.getChallengeForID(captchaId,
            httpServletRequest.getLocale());

// a jpeg encoder
    JPEGImageEncoder jpegEncoder =
            JPEGCodec.createJPEGEncoder(jpegOutputStream);
    jpegEncoder.encode(challenge);

} catch (IllegalArgumentException e) {
    httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
    return;
} catch (CaptchaServiceException e) {
    httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    return;
}

captchaChallengeAsJpeg = jpegOutputStream.toByteArray();

// flush it in the response
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream =
        httpServletResponse.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
    }



然后在web.xml配置Q?br style="padding: 0px; margin: 0px;" />
<servlet>
<servlet-name>CaptchaProxy</servlet-name>
<servlet-class>com.jawava.XXXXX.XXX.TopHttpServletProxy</servlet-class>
<init-param>
<param-name>targetServlet</param-name>
<param-value>captchaServlet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>CaptchaProxy</servlet-name>
<url-pattern>/topJcaptcha</url-pattern>
</servlet-mapping>



2、目前项目的d面是jspQ结合很方便Q在原有面上加?br style="padding: 0px; margin: 0px;" /><img src="/topJcaptcha" /> <input type="text" name="jcaptcha" value="" />
那个img是校验码?br style="padding: 0px; margin: 0px;" />需要的话,再加上个换图片的功能Q很单?br style="padding: 0px; margin: 0px;" />
3、验证环节。我是在原来的验证用户密码的逻辑前,加上了验证码的校验逻辑?br style="padding: 0px; margin: 0px;" />很简单的几句话,代码如下Q?br style="padding: 0px; margin: 0px;" />
Boolean isResponseCorrect =Boolean.FALSE;
        //需要sessionId 来验证校验码
        String sessionId = request.getSession().getId();
//首先校验验证?br style="padding: 0px; margin: 0px;" />        try {
            isResponseCorrect = captchaService.validateResponseForID(sessionId,
             captcha_input);
            if(!isResponseCorrect) {
             throw new RuntimeException("输入的验证码有误Q请重新输入");
            }
        } catch (CaptchaServiceException e) {
             //should not happen, may be thrown if the id is not valid
         throw new RuntimeException("校验验证码时出现不明错误",e);
        }



四、如此就可以试了。通过反复调整参数Q达C比较观的效果,但是文字始终
不在囄的正中,而是靠上Q甚至都把文字掩盖了一半。翻看了半天APIQ也看不?br style="padding: 0px; margin: 0px;" />个端倪。只好去L代码了。问题出?br style="padding: 0px; margin: 0px;" />com.octo.captcha.component.image.textpaster.SimpleTextPasterq个c,它把文字
囄往背景囄放时Q把文字的位|放在了背景囄一半的高度上,q就是问题所在?br style="padding: 0px; margin: 0px;" />修改代码重新打了个jar包。替换一下,重启后一切ok?/div>

achan2bj 2012-10-18 10:16 发表评论
]]>ArrayList和Vector的比较【{?/title><link>http://www.aygfsteel.com/achan2bj/archive/2012/09/29/388819.html</link><dc:creator>achan2bj</dc:creator><author>achan2bj</author><pubDate>Sat, 29 Sep 2012 01:38:00 GMT</pubDate><guid>http://www.aygfsteel.com/achan2bj/archive/2012/09/29/388819.html</guid><description><![CDATA[<p><strong>Vector q是ArrayList――哪一个更好,Z么?</strong></p><p><strong><br /></strong>要回{这个问题不能一概而论Q有时候用Vector比较好;有时是ArrayListQ有时候这两个都不?nbsp; </p><p>最好的选择。你别指望能够获得一个简单肯定答案,因ؓ(f)q要看你用它们干什么。下面有4个要考虑  </p><p>的因素:(x)  </p><p>l API  </p><p>l 同步处理  </p><p>l 数据增长?nbsp; </p><p>l 使用模式  </p><p>下面针对q?个方面进行一一探讨  </p><p><strong>API </strong> </p><p>在由Ken Arnold{编著的《Java Programming Language?Addison-Wesley, June 2000)一书中有这  </p><p>L(fng)描述QVectorcM于ArrayList.。所有从API的角度来看这两个c非常相[b]伹{但他们之间也还  </p><p>是有一些主要的区别的?br /><strong>同步?/strong></p><p>Vector是同步的。这个类中的一些方法保证了Vector中的对象是线E安全的。而ArrayList则是异步  </p><p>的,因此ArrayList中的对象q不是线E安全的。因为同步的要求?x)?jing)响执行的效率Q所以如果你?nbsp; </p><p>需要线E安全的集合那么使用ArrayList是一个很好的选择Q这样可以避免由于同步带来的不必要的  </p><p>性能开销?nbsp; </p><p><strong>数据增长</strong></p><p>从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控刉合中的对象。当你向q两U类  </p><p>型中增加元素的时候,如果元素的数目超Z内部数组目前的长度它们都需要扩展内部数l的长度Q?nbsp; </p><p>Vector~省情况下自动增长原来一倍的数组长度QArrayList是原来的50%,所以最后你获得的这个集  </p><p>合所占的I间L比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一  </p><p>些优势,因ؓ(f)你可以通过讄集合的初始化大小来避免不必要的资源开销?nbsp; </p><p><strong>使用模式</strong></p><p>在ArrayList和Vector中,从一个指定的位置Q通过索引Q查找数据或是在集合的末֢加、移除一  </p><p>个元素所p的时间是一L(fng)Q这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移?nbsp; </p><p>元素那么p的时间会(x)呈线形增长:(x)O(n-i)Q其中n代表集合中元素的个数Qi代表元素增加或移除元  </p><p>素的索引位置。ؓ(f)什么会(x)q样呢?以ؓ(f)在进行上q操作的时候集合中Wi和第i个元素之后的所有元?nbsp; </p><p>都要执行位移的操作。这一切意味着什么呢Q?nbsp; </p><p>q意味着Q你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector?nbsp; </p><p>ArrayList都可以。如果是其他操作Q你最好选择其他的集合操作类。比如,LinkList集合cd增加  </p><p>或移除集合中M位置的元素所p的时间都是一L(fng)—O(1)Q但它在索引一个元素的使用~比较慢  </p><p>QO(i),其中i是烦(ch)引的位置.使用ArrayList也很Ҏ(gu)Q因Z可以单的使用索引来代替创?nbsp; </p><p>iterator对象的操作。LinkList也会(x)为每个插入的元素创徏对象Q所有你要明白它也会(x)带来额外的开  </p><p>销?nbsp; </p><p>最后,在《Practical Java》一书中Peter Haggar使用一个简单的数组QArrayQ来代替Vector  </p><p>或ArrayList。尤其是对于执行效率要求高的E序更应如此。因Z用数l?Array)避免了同步、额?nbsp; </p><p>的方法调用和不必要的重新分配I间的操作?/p><img src ="http://www.aygfsteel.com/achan2bj/aggbug/388819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/achan2bj/" target="_blank">achan2bj</a> 2012-09-29 09:38 <a href="http://www.aygfsteel.com/achan2bj/archive/2012/09/29/388819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java面试题及(qing){案Q基?22道,代码?9道)(j) [转]http://www.aygfsteel.com/achan2bj/archive/2012/09/29/388818.htmlachan2bjachan2bjSat, 29 Sep 2012 01:31:00 GMThttp://www.aygfsteel.com/achan2bj/archive/2012/09/29/388818.html阅读全文

achan2bj 2012-09-29 09:31 发表评论
]]>
JAVA的多U程实现http://www.aygfsteel.com/achan2bj/archive/2012/09/24/388422.htmlachan2bjachan2bjMon, 24 Sep 2012 03:18:00 GMThttp://www.aygfsteel.com/achan2bj/archive/2012/09/24/388422.html1.JAVA多线E实现方?br />JAVA多线E实现方式主要有三种Q承ThreadcR实现Runnable接口、用ExecutorService、Callable、Future实现有返回结果的多线E。其中前两种方式U程执行完后都没有返回|只有最后一U是带返回值的?p>2.l承Threadcd现多U程
l承ThreadcȝҎ(gu)管被我列ؓ(f)一U多U程实现方式Q但Thread本质上也是实CRunnable接口的一个实例,它代表一个线E的实例Qƈ且,启动U程的唯一Ҏ(gu)是通过Threadcȝstart()实例Ҏ(gu)。start()Ҏ(gu)是一个nativeҎ(gu)Q它?yu)启动一个新U程Qƈ执行run()Ҏ(gu)。这U方式实现多U程很简单,通过自己的类直接extend ThreadQƈ复写run()Ҏ(gu)Q就可以启动新线Eƈ执行自己定义的run()Ҏ(gu)。例如:(x)
public class MyThread extends Thread {
  public void run() {
   System.out.println("MyThread.run()");
  }
}
在合适的地方启动U程如下Q?br />MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();

3.实现Runnable接口方式实现多线E?br />如果自己的类已经extends另一个类Q就无法直接extends ThreadQ此Ӟ必须实现一个Runnable接口Q如下:(x)
public class MyThread extends OtherClass implements Runnable {
  public void run() {
   System.out.println("MyThread.run()");
  }
}
Z启动MyThreadQ需要首先实例化一个ThreadQƈ传入自己的MyThread实例Q?br />MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
事实上,当传入一个Runnable target参数lThread后,Thread的run()Ҏ(gu)׃(x)调用target.run()Q参考JDK源代码:(x)
public void run() {
  if (target != null) {
   target.run();
  }
}

4.使用ExecutorService、Callable、Future实现有返回结果的多线E?/strong>
ExecutorService、Callable、Futureq个对象实际上都是属于Executor框架中的功能cR想要详l了解Executor框架的可以访?a >http://www.javaeye.com/topic/366591 Q这里面对该框架做了很详l的解释。返回结果的U程是在JDK1.5中引入的新特征,实很实用,有了q种特征我就不需要再Z得到q回D大费周折了Q而且即便实现了也可能漏洞癑և?br />可返回值的d必须实现Callable接口Q类似的Q无q回值的d必须Runnable接口。执行Callabled后,可以获取一个Future的对象,在该对象上调用get可以获取到Callabledq回的Object了,再结合线E池接口ExecutorService可以实C说中有返回结果的多线E了。下面提供了一个完整的有返回结果的多线E测试例子,在JDK1.5下验证过没问题可以直接用。代码如下:(x)

import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;

/**
* JavaU程Q有q回值的U程
*
* @author wb_qiuquan.ying
*/
@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,
    InterruptedException {
   System.out.println("----E序开始运?---");
   Date date1 = new Date();

   int taskSize = 5;
   // 创徏一个线E池
   ExecutorService pool = Executors.newFixedThreadPool(taskSize);
   // 创徏多个有返回值的d
   List<Future> list = new ArrayList<Future>();
   for (int i = 0; i < taskSize; i++) {
    Callable c = new MyCallable(i + " ");
    // 执行dq获取Future对象
    Future f = pool.submit(c);
    // System.out.println(">>>" + f.get().toString());
    list.add(f);
   }
   // 关闭U程?br />   pool.shutdown();

   // 获取所有ƈ发Q务的q行l果
   for (Future f : list) {
    // 从Future对象上获取Q务的q回|q输出到控制?br />    System.out.println(">>>" + f.get().toString());
   }

   Date date2 = new Date();
   System.out.println("----E序l束q行----Q程序运行时间?
     + (date2.getTime() - date1.getTime()) + "毫秒?);
}
}

class MyCallable implements Callable<Object> {
private String taskNum;

MyCallable(String taskNum) {
   this.taskNum = taskNum;
}

public Object call() throws Exception {
   System.out.println(">>>" + taskNum + "d启动");
   Date dateTmp1 = new Date();
   Thread.sleep(1000);
   Date dateTmp2 = new Date();
   long time = dateTmp2.getTime() - dateTmp1.getTime();
   System.out.println(">>>" + taskNum + "dl止");
   return taskNum + "dq回q行l果,当前d旉? + time + "毫秒?;
}
}


代码说明Q?br />上述代码中Executorsc,提供了一pd工厂Ҏ(gu)用于创先U程池,q回的线E池都实CExecutorService接口?br />public static ExecutorService newFixedThreadPool(int nThreads)
创徏固定数目U程的线E池?br />public static ExecutorService newCachedThreadPool()
创徏一个可~存的线E池Q调用execute 重用以前构造的U程Q如果线E可用)(j)。如果现有线E没有可用的Q则创徏一个新U程q添加到池中。终止ƈ从缓存中U除那些已有 60 U钟未被使用的线E?br />public static ExecutorService newSingleThreadExecutor()
创徏一个单U程化的Executor?br />public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创徏一个支持定时及(qing)周期性的d执行的线E池Q多数情况下可用来替代TimercR?/p>

ExecutoreService提供了submit()Ҏ(gu)Q传递一个CallableQ或RunnableQ返回Future。如果Executor后台U程池还没有完成Callable的计,q调用返回Future对象的get()Ҏ(gu)Q会(x)d直到计算完成?/p>

achan2bj 2012-09-24 11:18 发表评论
]]>
String,StringBuffer?qing)StringBuilderhttp://www.aygfsteel.com/achan2bj/archive/2012/09/24/388410.htmlachan2bjachan2bjMon, 24 Sep 2012 01:44:00 GMThttp://www.aygfsteel.com/achan2bj/archive/2012/09/24/388410.htmlString和StringBuffer的区别,|上资料可以说是C胜数Q但是看到这文章,感觉里面做的例子很有代表性,所以{一下,q自己做了一Ҏ(gu)ȝ?/p>

在java中有3个类来负责字W的操作?

1.Character 是进行单个字W操作的Q?/p>

2.String 对一串字W进行操作。不可变cR?/p>

3.StringBuffer 也是对一串字W进行操作,但是可变cR?/p>

String:
是对象不是原始类?
Z可变对象,一旦被创徏,׃能修改它的?
对于已经存在的String对象的修攚w是重新创Z个新的对?然后把新的g存进?
String 是finalc?即不能被l承.

StringBuffer:
是一个可变对?当对他进行修改的时候不?x)像String那样重新建立对象
它只能通过构造函数来建立,
StringBuffer sb = new StringBuffer();
note:不能通过付值符号对他进行付?
sb = "welcome to here!";//error
对象被徏立以?在内存中׃(x)分配内存I间,q初始保存一个null.向StringBuffer
中付值的时候可以通过它的appendҎ(gu).
sb.append("hello");

字符串连接操作中StringBuffer的效率要比String?

String str = new String("welcome to ");
str += "here";
的处理步骤实际上是通过建立一个StringBuffer,让侯调用append(),最?br />再将StringBuffer toSting();
q样的话String的连接操作就比StringBuffer多出了一些附加操?当然效率上要打折?

q且׃String 对象是不可变对象,每次操作Sting 都会(x)重新建立新的对象来保存新的?
q样原来的对象就没用?p被垃圑֛?q也是要影响性能?

看看以下代码Q?br />?6个英文字母重复加?000ơ,

  1.         String tempstr = "abcdefghijklmnopqrstuvwxyz";
  2.         int times = 5000;
  3.         long lstart1 = System.currentTimeMillis();
  4.         String str = "";
  5.         for (int i = 0; i < times; i++) {
  6.             str += tempstr;
  7.         }
  8.         long lend1 = System.currentTimeMillis();
  9.         long time = (lend1 - lstart1);
  10.         System.out.println(time);

可惜我的计算Z是超U计机Q得到的l果每次不一定一样一般ؓ(f) 46687左右?br />也就?6U?br />我们再看看以下代?/p>

  1.         String tempstr = "abcdefghijklmnopqrstuvwxyz";
  2.         int times = 5000;
  3.         long lstart2 = System.currentTimeMillis();
  4.         StringBuffer sb = new StringBuffer();
  5.         for (int i = 0; i < times; i++) {
  6.             sb.append(tempstr);
  7.         }
  8.         long lend2 = System.currentTimeMillis();
  9.         long time2 = (lend2 - lstart2);
  10.         System.out.println(time2);

得到的结果ؓ(f) 16 有时q是 0
所以结论很明显QStringBuffer 的速度几乎是String 上万倍。当然这个数据不是很准确。因为@环的ơ数?00000ơ的时候,差异更大。不信你试试?/p>

Ҏ(gu)上面所_(d)(x)

str += "here";
的处理步骤实际上是通过建立一个StringBuffer,让侯调用append(),最?br />再将StringBuffer toSting();

所以str += "here";可以{同?/p>

StringBuffer sb = new StringBuffer(str);

sb.append("here");

str = sb.toString();

所以上面直接利?+"来连接String的代码可以基本等同于以下代码

  1.         String tempstr = "abcdefghijklmnopqrstuvwxyz";
  2.         int times = 5000;
  3.         long lstart2 = System.currentTimeMillis();
  4.         String str = "";
  5.         for (int i = 0; i < times; i++) {
  6.             StringBuffer sb = new StringBuffer(str);
  7.             sb.append(tempstr);
  8.             str = sb.toString();
  9.         }
  10.         long lend2 = System.currentTimeMillis();
  11.         long time2 = (lend2 - lstart2);
  12.         System.out.println(time2);

q_执行旉?6922左右Q也是46U?/p>

ȝ: 如果在程序中需要对字符串进行频J的修改q接操作的话.使用StringBuffer性能?x)更?br />
===========================================================================================


自从Java 5.0发布以后Q我们的比较列表上将多出一个对象了Q这是StringBuildercRStringcL不可变类QQ何对String的改变都?x)引发新的String对象的生成;而StringBuffer则是可变c,M对它所指代的字W串的改变都不会(x)产生新的对象Q可变和不可变类q一对对象已l齐全了Q那么ؓ(f)什么还要引入新的StringBuildercd吗?怿大家都有此疑问,我也如此。下面,我们来看看引入该类的原因?

      Z么会(x)出现那么多比较String和StringBuffer的文章?

      原因在于当改变字W串内容Ӟ采用StringBuffer能获得更好的性能。既然是Z获得更好的性能Q那么采用StringBuffer能够获得最好的性能吗?

      {案是NOQ?

      Z么?

      如果你读q《Think in Java》,而且寚w面描qHashTable和HashMap区别的那部分章节比较熟?zhn)的话Q你一定也明白了原因所在。对Q就是支持线E同步保证线E安全而导致性能下降的问题?span style="color: red;">HashTable是线E安全的Q很多方法都是synchronizedҎ(gu)Q而HashMap不是U程安全的,但其在单U程E序中的性能比HashTable要高。StringBuffer和StringBuildercȝ区别也在于此Q?span style="color: red;">新引入的StringBuildercM是线E安全的Q但其在单线E中的性能比StringBuffer?/span>。如果你Ҏ(gu)不太怿Q可以试试下面的例子Q?/p>

package com.hct.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* @author: chengtai.he
* @created:2009-12-9 上午09:59:57
*/
public class StringBuilderTester {
private static final String base = " base string. ";
private static final int count = 2000000;

public static void stringTest() {
  long begin, end;
  begin = System.currentTimeMillis();
  String test = new String(base);
  for (int i = 0; i < count/100; i++) {
   test = test + " add ";
  }
  end = System.currentTimeMillis();
  System.out.println((end - begin)
    + " millis has elapsed when used String. ");
}

public static void stringBufferTest() {
  long begin, end;
  begin = System.currentTimeMillis();
  StringBuffer test = new StringBuffer(base);
  for (int i = 0; i < count; i++) {
   test = test.append(" add ");
  }
  end = System.currentTimeMillis();
  System.out.println((end - begin)
    + " millis has elapsed when used StringBuffer. ");
}

public static void stringBuilderTest() {
  long begin, end;
  begin = System.currentTimeMillis();
  StringBuilder test = new StringBuilder(base);
  for (int i = 0; i < count; i++) {
   test = test.append(" add ");
  }
  end = System.currentTimeMillis();
  System.out.println((end - begin)
    + " millis has elapsed when used StringBuilder. ");
}

public static String appendItemsToStringBuiler(List list) {
  StringBuilder b = new StringBuilder();

  for (Iterator i = list.iterator(); i.hasNext();) {
   b.append(i.next()).append(" ");
  }

  return b.toString();
}

public static void addToStringBuilder() {
  List list = new ArrayList();
  list.add(" I ");
  list.add(" play ");
  list.add(" Bourgeois ");
  list.add(" guitars ");
  list.add(" and ");
  list.add(" Huber ");
  list.add(" banjos ");

  System.out.println(StringBuilderTester.appendItemsToStirngBuffer(list));
}

public static String appendItemsToStirngBuffer(List list) {
  StringBuffer b = new StringBuffer();

  for (Iterator i = list.iterator(); i.hasNext();) {
   b.append(i.next()).append(" ");
  }

  return b.toString();
}

public static void addToStringBuffer() {
  List list = new ArrayList();
  list.add(" I ");
  list.add(" play ");
  list.add(" Bourgeois ");
  list.add(" guitars ");
  list.add(" and ");
  list.add(" Huber ");
  list.add(" banjos ");

  System.out.println(StringBuilderTester.appendItemsToStirngBuffer(list));
}

public static void main(String[] args) {
  stringTest();
  stringBufferTest();
  stringBuilderTest();
  addToStringBuffer();
  addToStringBuilder();
}
}

上面的程序结果如下:(x)
5266 millis has elapsed when used String.
375 millis has elapsed when used StringBuffer.
281 millis has elapsed when used StringBuilder.
I   play   Bourgeois   guitars   and   Huber   banjos 
I   play   Bourgeois   guitars   and   Huber   banjos
从上面的l果来看Q这三个cd单线E程序中的性能差别一目了?dng)采用String对象Ӟ即ɘq行ơ数仅是采用其他对象?/100Q其执行旉仍然比其他对象高?5倍以上;而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显Q前者是后者的1.5倍左叟뀂由此可见,如果我们的程序是在单U程下运行,或者是不必考虑到线E同步问题,我们应该优先使用StringBuilderc;当然Q如果要保证U程安全Q自焉StringBuffer莫属了?/p>

除了对多U程的支持不一样外Q这两个cȝ使用几乎没有M差别Q上面的例子是个很好的说明。appendItemsToStringBuiler和appendItemsToStirngBuffer两个Ҏ(gu)除了采用的对象分别ؓ(f)StringBuilder和StringBuffer外,其他完全相同Q而效果也完全相同?/p>




achan2bj 2012-09-24 09:44 发表评论
]]>
新开通BlogJavahttp://www.aygfsteel.com/achan2bj/archive/2012/09/24/388405.htmlachan2bjachan2bjMon, 24 Sep 2012 00:42:00 GMThttp://www.aygfsteel.com/achan2bj/archive/2012/09/24/388405.htmlhttp://www.aygfsteel.com/achan2bj/comments/388405.htmlhttp://www.aygfsteel.com/achan2bj/archive/2012/09/24/388405.html#Feedback0http://www.aygfsteel.com/achan2bj/comments/commentRss/388405.htmlhttp://www.aygfsteel.com/achan2bj/services/trackbacks/388405.html

achan2bj 2012-09-24 08:42 发表评论
]]>
վ֩ģ壺 ˮ| | | | | | | | ޻| пǰ| ϰ| | ɽ| | | | ½| ̨ɽ| ƽ| | | | | ƽ| | | Ƹ| ̫ԭ| | | | | ̨| | | ¤| | ͩ| | | ֬|