征途2毁灭道士加点
2011-06-17 10:18
| 征途2中的道士,其实他就是老征途的召唤职业,需要通知玩家的是,征途2中道士已经没有无敌这个技能了,道士共分为自然系和毁灭系,自然系是血较高,而毁灭就名如其实了,是一个攻击性的职业,高攻宝宝攻击高,但是血和防御相对就没那么高了,而自然系宝宝就是个血牛了,血多的吓人; 关于道士的属性加点,智力、敏捷、精神体质,目前就这几种属性点适合道士,攻击性道士也就是毁灭系道士,想再追求攻击的话那就智力吧,血防不够的话,适当补充点体质,防御不够的话也可补点精神 如果是自然系道士,血够高了吧,那就补防御吧,精神,或加攻。 对于召唤很多人都是新手或者说是绿色或者怀旧过来的,因此有必要解析下征途2的召唤。 特别注意:在前期我建议大家别学召唤,因为召唤只有一个攻击技能【罗汉棍法】。所以在93级之前最好别学。 1:召唤毁灭系技能加点: 基础没事加满就可以的。【召唤狐妖】过渡、【控制】加满、【快马加鞭】过渡、【强化合体】加满、【天魔步】加满、【召唤鬼狼】过渡、【玄冥真气】加满、【黑暗之力】加满、【黑暗之力】加满、【无边法力】过渡、【精准训练】加满、【真元修炼】加满、【召唤鬼狼】加满、【召唤火凤凰】1点。 上面的无边法力为啥说是过渡呢?因为黑暗之力能直接加防御,考虑到先期技能点的问题,无边法力只能在合体状态下有效果,因此就变的有点鸡肋了。 2:对于召唤的装备: 个人认为召唤装备可以穿物防套,马装备换成魔防魔攻套。为啥这么说呢?因为按照现在的征途2的各职业来看,召唤可以说是守护的克星,因此召唤PK时往往是对付守护的。这我会在下面的职业PK中提到。 3:如何加属性点: 对于毁灭系的召唤我想还是应该加智力,因为毁灭系召唤的宝宝攻击是根据自身魔法攻击而来决定招出来的宝宝的物理攻击的大小,而且在召唤合体的时候,攻击是魔法攻击。可以说召唤的宝宝攻击中所谓的物理攻击是一种误导。 4:召唤合守护的PK 一个真正好的召唤,PK在注重装备的同时还更多是技巧。召唤在对付魔防守护的时候先招宝宝攻击,因为宝宝是物理攻击的,在宝宝攻击的时候就不停的和守护绕圈,直到耗死,要是守护开不动如山,就要洗了,在合体前最好是能把守护的不动如山cd时间给用完。不能硬抗,在合体之后就能和守护硬抗了。也就是说召唤打守护不是打死的是耗死的。 |
人的30岁分界点!
2010-01-06 09:52
| 1. 一定要相信30岁很快就会到来,无论你是在魔兽、cs还是蹦迪泡吧, 就算装得再嫩,岁月总会在你的心里留下烙印,掩饰永远都不能改变事实, 办法只有一个:提前做好准备,即使你现在只有18岁,脸皮还能掐出水来。 30岁一过,一样是人老珠黄一根草而已,所以要是不能提前装填自己的心理 内涵,等着人见人烦吧。 2. 勿以善小而不为,勿以恶小而为之。不管你对生活已经有了多深的认识, 在许多方面最好听听父母的建议,甚至最好完全按照他们的吩咐去做,抛开老 祖宗遗留下来的传统以外,他们毕竟比我们早活了几十年,对这个残酷社会的 认识远远超过我们,哪怕大字 认不了几筐。30岁一过,你看任何事和他们当 年看你是基本一致的,那时候肠子悔青都已经无济于事。 3. 一定要知道自己有几个朋友是能帮助自己的,有几个朋友只是混吃混喝 的,还有几个朋友是可有可无的,还有几个朋友是要小心提防的,最好搞清楚 他(她)们的家人是干吗的,因为不管是什么样的朋友,你总有用得着的一天。 30岁以后你会发现,那些成功人士,身边都会有一个或者一批很大的关系网, 而维系它们的几乎都是朋友。 4. 30岁以前的未婚男人可以多交几个女朋友,这样你可以学到许多东西。 但是关系一定要保持稳定,同一个月的几个周末的晚上,在你身边的最好不要 出现不同的女人,不要认为男人的名声就不重要,香蕉要是烂了,和苹果一个 德行。等人尽皆知的时候,你会后悔生在这个城市或者国家(女人同上)。 5.初恋永远都是最好的。所以不管你的初恋有多么多么的不堪,不管对方有 多么多么的青涩,哪怕是鼻涕已经过了黄河,记住一定不要伤害他(她),哪 怕最后还是要分手,30岁以后他(她)将是你心中那条唯一清澈见底的溪流。 而你的伤害往往会左右了一个人今后的交友取向。 6. 第一次亲密接触最好不要看得太重。这是很难做到但必须做到的,这并 不是告诉你你可以乱来,原因可以参看第4条,说这句话主要是这个世界**实 在太多,而你又实在太年轻,很可能会在第二天醒来的时候发现身边躺着的不 是最爱的人,这个醒来的时 间可能会延迟很久,假如你不懂得及时看清现实, 非要计较自己的第一次给了谁,当第二次来的时候,等待你的将是更大的伤害。 这一条你可以理解为把第一次留给最爱你的人(请注意:不是你最爱的人)。 7. 30岁以前一定要在家庭和自己条件允许并且有节制的情况下,尽可能 地多花点 钱,尽可能地多了解点这世上的新鲜事,尽可能地多买点书,尽可 能地多吃点各式各样的食物,尽可能地多为自己添置点衣服,说这一点不是 告诉你可以穷奢极欲,30岁以后你会发现钱多少都不够,会发现这世界你不 懂的东西实在太多太多,你会后悔书读得太少,你会发现对许多食物已经没 有胃口,你会发现你已经穿不上很多看上去非常好看的衣服。 8. 30岁以前这个世上最可能不会背叛你的就是你自己的身体,而30岁以 后最可能 会背叛你的也是你自己的身体。30岁以前你可以胡吃海喝,可以灯 红酒绿,可以坐在电脑前cs一宿不睡把眼珠子熬得通红。30岁以后,你的身 体就会用各种疾病告诉你,当年一定是脑子被驴踢了,才会那么折腾自己。 9. 一定要学会做饭,一定要学会洗衣服,一定要学会自己照顾自己,一 定要学会最起码的生存之道, 在这方面父母是最好的老师,他们也会非常乐 意地教导你这些,最好清楚男人和女人最基本的卫生和健康之道,最好知道 几条生活中的小窍门,最好掌握一个或者几个拿手菜。谁都有独自面对生 活的那一天。30岁以后,要是你连个袜子都不会洗,做的菜连猪都能咸死的 话,除非比尔·盖茨是你干爹,否则你再有钱也一样会被人鄙视(总有一天)。 10.遇到自己爱的人一定要勇敢的去争取,假如他(她)真的值得你去争 取,到手了不要把他(她) 揣兜里时间太长,经常拿出来在阳光底下晾一晾, 此举不仅能昭告天下名花有主,更可以对你们的爱情进行一番考验,不要把 爱情谈得太久,不要等对对方的身体熟悉到屁股上有几个痦子都清楚的地步, 在没达到最热烈的时候该结婚就结婚,豆腐都是好豆腐,时间长了一样变质, 王致和虽然味道不错,但毕竟不是人人都能接受的,什么单身主义,什么惧 怕围城,30岁以后,你会发现哪怕是年少时那个留着清鼻涕蹲在你家楼后面 痴痴等你一宿的傻东西向你求婚,你都愿意答应他,你会发现条件会越来越 低,有时你的念头会让自己都看不起自己,有时你会痛哭这世界真变态,连 个值得爱的人都找不到。酒是陈的香,可是相信我,你绝对成不了法国庄园 里的波尔多。 人生如一盘棋,执黑执白都无所谓,能一举成名的是极个别的少数,许多 人都在半截 了了账,每一步都是选择,只不过有些无关痛痒,有些却马虎不得, 一着失误,满盘皆输的人比比皆是,等某一天你对身边围着的人说:我这一盘 棋终于下完了,而自我感觉没有什么遗憾的时候,那么恭喜你,你赢了。 30而立,对有些人来说,30岁以前向左,30岁以后向右。30而立,对有些人 来说,30岁以前是因,30岁以后是果。 |
java代码优化注意事项
2010-01-04 16:49
| 可供程序利用的资源(内存、CPU时间、网络带宽等)是有限的,优化的目的就是让程序用尽可能少的资源完成预定的任务。优化通常包含两方面的内容:减小代码的体积,提高代码的运行效率。本文讨论的主要是如何提高代码的效率。 在Java程序中,性能问题的大部分原因并不在于Java语言,而是在于程序本身。养成好的代码编写习惯非常重要,比如正确地、巧妙地运用java.lang.String类和java.util.Vector类,它能够显著地提高程序的性能。下面我们就来具体地分析一下这方面的问题。 1、 尽量指定类的final修饰符 带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了人们覆盖length()方法。另外,如果指定一个类为final,则该类所有的方法都是final。Java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50% 。 2、 尽量重用对象。特别是String 对象的使用中,出现字符串连接情况时应用StringBuffer或者StringBuilder 代替。由于系统不仅要花时间生成对象,以后可能还需花时间对这些对象进行垃圾回收和处理。因此,生成过多的对象将会给程序的性能带来很大的影响。 3、 尽量使用局部变量,调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能得到进一步优化。 4、 不要重复初始化变量 默认情况下,调用类的构造函数时, Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类继承时,这一点尤其应该注意,因为用new关键词创建一个对象时,构造函数链中的所有构造函数都会被自动调用。 5、 在JAVA + ORACLE 的应用系统开发中,java中内嵌的SQL语句尽量使用大写的形式,以减轻ORACLE解析器的解析负担。(之前我没注意这个,哈哈!) 6、 Java 编程过程中,进行数据库连接、I/O流操作时务必小心,在使用完毕后,即使关闭以释放资源。因为对这些大对象的操作会造成系统大的开销,稍有不慎,会导致严重的后果。 7、 由于JVM的有其自身的GC机制,不需要程序开发者的过多考虑,从一定程度上减轻了开发者负担,但同时也遗漏了隐患,过分的创建对象会消耗系统的大量内存,严重时会导致内存泄露,因此,保证过期对象的及时回收具有重要意义。JVM回收垃圾的条件是:对象不在被引用;然而,JVM的GC并非十分的机智,即使对象满足了垃圾回收的条件也不一定会被立即回收。所以,建议我们在对象使用完毕,应手动置成null。 8、 在使用同步机制时,应尽量使用方法同步代替代码块同步。 9、 尽量减少对变量的重复计算 例如:for(int i = 0;i < list.size; i ++) { … } 应替换为: for(int i = 0,int len = list.size();i < len; i ++) { … } 10、尽量采用lazy loading 的策略,即在需要的时候才开始创建。 例如: String str = “aaa”; 应替换为:if(i == 1) { if(i == 1) { String str = “aaa”; list.add(str); list.add(str); } } 11、慎用异常 异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。 异常只能用于错误处理,不应该用来控制程序流程 12、不要在循环中使用: Try { } catch() { } 应把其放置在最外层。 13、StringBuffer 的使用: StringBuffer表示了可变的、可写的字符串。 有三个构造方法 : StringBuffer (); //默认分配16个字符的空间 StringBuffer (int size); //分配size个字符的空间 StringBuffer (String str); //分配16个字符+str.length()个字符空间 你可以通过StringBuffer的构造函数来设定它的初始化容量,这样可以明显地提升性能。这里提到的构造函数是StringBuffer(int length),length参数表示当前的StringBuffer能保持的字符数量。你也可以使用ensureCapacity(int minimumcapacity)方法在StringBuffer对象创建之后设置它的容量。首先我们看看StringBuffer的缺省行为,然后再找出一条更好的提升性能的途径。 StringBuffer在内部维护一个字符数组,当你使用缺省的构造函数来创建StringBuffer对象的时候,因为没有设置初始化字符长度,StringBuffer的容量被初始化为16个字符,也就是说缺省容量就是16个字符。当StringBuffer达到最大容量的时候,它会将自身容量增加到当前的2倍再加2,也就是(2*旧值+2)。如果你使用缺省值,初始化之后接着往里面追加字符,在你追加到第16个字符的时候它会将容量增加到34(2*16+2),当追加到34个字符的时候就会将容量增加到70(2*34+2)。无论何事只要StringBuffer到达它的最大容量它就不得不创建一个新的字符数组然后重新将旧字符和新字符都拷贝一遍――这也太昂贵了点。所以总是给StringBuffer设置一个合理的初始化容量值是错不了的,这样会带来立竿见影的性能增益。 (现在有了StringBuilder,它比StringBuffer更快) 14、合理的使用Java类 java.util.Vector。 简单地说,一个Vector就是一个java.lang.Object实例的数组。Vector与数组相似,它的元素可以通过整数形式的索引访问。但是,Vector类型的对象在创建之后,对象的大小能够根据元素的增加或者删除而扩展、缩小。请考虑下面这个向Vector加入元素的例子: Object obj = new Object(); Vector v = new Vector(100000); for(int I=0; I<100000; I++) { v.add(0,obj); } 除非有绝对充足的理由要求每次都把新元素插入到Vector的前面,否则上面的代码对性能不利。在默认构造函数中,Vector的初始存储能力是10个元素,如果新元素加入时存储能力不足,则以后存储能力每次加倍。Vector类就象StringBuffer类一样,每次扩展存储能力时,所有现有的元素都要复制到新的存储空间之中。下面的代码片段要比前面的例子快几个数量级: Object obj = new Object(); Vector v = new Vector(100000); for(int I=0; I<100000; I++) { v.add(obj); } 同样的规则也适用于Vector类的remove()方法。由于Vector中各个元素之间不能含有“空隙”,删除除最后一个元素之外的任意其他元素都导致被删除元素之后的元素向前移动。也就是说,从Vector删除最后一个元素要比删除第一个元素“开销”低好几倍。 假设要从前面的Vector删除所有元素,我们可以使用这种代码: for(int I=0; I<100000; I++) { v.remove(0); } 但是,与下面的代码相比,前面的代码要慢几个数量级: for(int I=0; I<100000; I++) { v.remove(v.size()-1); } 从Vector类型的对象v删除所有元素的最好方法是:v.removeAllElements(); 假设Vector类型的对象v包含字符串“Hello”。考虑下面的代码,它要从这个Vector中删除“Hello”字符串: String s = "Hello"; int i = v.indexOf(s); if(I != -1) v.remove(s); 这些代码看起来没什么错误,但它同样对性能不利。在这段代码中,indexOf()方法对v进行顺序搜索寻找字符串“Hello”,remove(s)方法也要进行同样的顺序搜索。改进之后的版本是: String s = "Hello"; int i = v.indexOf(s); if(I != -1) v.remove(i); 这个版本中我们直接在remove()方法中给出待删除元素的精确索引位置,从而避免了第二次搜索。一个更好的版本是: String s = "Hello"; v.remove(s); 最后,我们再来看一个有关Vector类的代码片段: for(int I=0; I++;I < v.length) 如果v包含100,000个元素,这个代码片段将调用v.size()方法100,000次。虽然size方法是一个简单的方法,但它仍旧需要一次方法调用的开销,至少JVM需要为它配置以及清除堆栈环境。在这里,for循环内部的代码不会以任何方式修改Vector类型对象v的大小,因此上面的代码最好改写成下面这种形式: int size = v.size(); for(int I=0; I++;I<size) 虽然这是一个简单的改动,但它仍旧赢得了性能。毕竟,每一个CPU周期都是宝贵的。 15、当复制大量数据时,使用System.arraycopy()命令。 16、代码重构:增强代码的可读性。 例如: public class ShopCart { private List carts ; … public void add (Object item) { if(carts == null) { carts = new ArrayList(); } carts.add(item); } public void remove(Object item) { if(carts. contains(item)) { carts.remove(item); } } public List getCarts() { //返回只读列表 return Collections.unmodifiableList(carts); } //不推荐这种方式 //this.getCarts().add(item); } carts.remove(item); } } public List getCarts() { //返回只读列表 return Collections.unmodifiableList(carts); } //不推荐这种方式 //this.getCarts().add(item); } 17、不用new关键词创建类的实例 用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。 在使用设计模式(Design Pattern)的场合,如果用Factory模式创建对象,则改用clone()方法创建新的对象实例非常简单。例如,下面是Factory模式的一个典型实现: public static Credit getNewCredit() { return new Credit(); } 改进后的代码使用clone()方法,如下所示: private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() { return (Credit) BaseCredit.clone(); } 上面的思路对于数组处理同样很有用。 18、乘法和除法 用位移<< >> 考虑下面的代码: for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; } 用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码: for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; } 修改后的代码不再做乘以8的操作,而是改用等价的左移3位操作,每左移1位相当于乘以2。相应地,右移1位操作相当于除以2。值得一提的是,虽然移位操作速度快,但可能使代码比较难于理解,所以最好加上一些注释。 19、在JSP页面中关闭无用的会话。 一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用HttpServletRequest.getSession(true)这样的语句时才被创建,注意如果JSP没有显示的使用 <%@page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。 对于那些无需跟踪会话状态的页面,关闭自动创建的会话可以节省一些资源。 使用如下page指令:<%@ page session="false"%> (一般不要吧,要是从 有——无——有 这中间会不会丢到什么?还需检验一下。) 20、JDBC与I/O 如果应用程序需要访问一个规模很大的数据集,则应当考虑使用块提取方式。默认情况下,JDBC每次提取32行数据。举例来说,假设我们要遍历一个5000行的记录集,JDBC必须调用数据库157次才能提取到全部数据。如果把块大小改成512,则调用数据库的次数将减少到10次。(没该过不知道怎么该?) 21、Servlet与内存使用 许多开发者随意地把大量信息保存到用户会话之中。一些时候,保存在会话中的对象没有及时地被垃圾回收机制回收。从性能上看,典型的症状是用户感到系统周期性地变慢,却又不能把原因归于任何一个具体的组件。如果监视JVM的堆空间,它的表现是内存占用不正常地大起大落。 解决这类内存问题主要有二种办法。第一种办法是,在所有作用范围为会话的Bean中实现HttpSessionBindingListener接口。这样,只要实现valueUnbound()方法,就可以显式地释放Bean使用的资源。 另外一种办法就是尽快地把会话作废。大多数应用服务器都有设置会话作废间隔时间的选项。另外,也可以用编程的方式调用会话的setMaxInactiveInterval()方法,该方法用来设定在作废会话之前,Servlet容器允许的客户请求的最大间隔时间,以秒计。 22、使用缓冲标记 一些应用服务器加入了面向JSP的缓冲标记功能。例如,BEA的WebLogic Server从6.0版本开始支持这个功能,Open Symphony工程也同样支持这个功能。JSP缓冲标记既能够缓冲页面片断,也能够缓冲整个页面。当JSP页面执行时,如果目标片断已经在缓冲之中,则生成该片断的代码就不用再执行。页面级缓冲捕获对指定URL的请求,并缓冲整个结果页面。对于购物篮、目录以及门户网站的主页来说,这个功能极其有用。对于这类应用,页面级缓冲能够保存页面执行的结果,供后继请求使用。 23、选择合适的引用机制 在典型的JSP应用系统中,页头、页脚部分往往被抽取出来,然后根据需要引入页头、页脚。当前,在JSP页面中引入外部资源的方法主要有两种:include指令,以及include动作。 include指令:例如<%@ include file="copyright.html" %>。该指令在编译时引入指定的资源。在编译之前,带有include指令的页面和指定的资源被合并成一个文件。被引用的外部资源在编译时就确定,比运行时才确定资源更高效。 include动作:例如<jsp:include page="copyright.jsp" />。该动作引入指定页面执行后生成的结果。由于它在运行时完成,因此对输出结果的控制更加灵活。但时,只有当被引用的内容频繁地改变时,或者在对主页面的请求没有出现之前,被引用的页面无法确定时,使用include动作才合算。 24、及时清除不再需要的会话 为了清除不再活动的会话,许多应用服务器都有默认的会话超时时间,一般为30分钟。当应用服务器需要保存更多会话时,如果内存容量不足,操作系统会把部分内存数据转移到磁盘,应用服务器也可能根据“最近最频繁使用”(Most Recently Used)算法把部分不活跃的会话转储到磁盘,甚至可能抛出“内存不足”异常。在大规模系统中,串行化会话的代价是很昂贵的。当会话不再需要时,应当及时调用HttpSession.invalidate()方法清除会话。HttpSession.invalidate()方法通常可以在应用的退出页面调用。 25、不要将数组声明为:public static final 。 26、HashMap的遍历效率讨论 经常遇到对HashMap中的key和value值对的遍历操作,有如下两种方法:Map<String, String[]> paraMap = new HashMap<String, String[]>(); ................//第一个循环 Set<String> appFieldDefIds = paraMap.keySet(); for (String appFieldDefId& nbsp;: appFieldDefIds) { String[] values = paraMap.get(appFieldDefId); ...... } //第二个循环 for(Entry<String, String[]> entry : paraMap.entrySet()){ String appFieldDefId = entry.getKey(); String[] values = entry.getValue(); ....... } 第一种实现明显的效率不如第二种实现。 分析如下 Set<String> appFieldDefIds = paraMap.keySet(); 是先从HashMap中取得keySet 代码如下: public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); } private class KeySet extends AbstractSet<K> { public Iterator<K> iterator() { return newKeyIterator(); } public int size() { return size; } public boolean contains(Object o) { return containsKey(o); } public boolean remove(Object o) { return HashMap.this.removeEntryForKey(o) != null; } public void clear() { HashMap.this.clear(); } } 其实就是返回一个私有类KeySet, 它是从AbstractSet继承而来,实现了Set接口。 再来看看for/in循环的语法 for(declaration : expression) statement 在执行阶段被翻译成如下各式 for(Iterator<E> #i = (expression).iterator(); #i.hashNext();){ declaration = #i.next(); statement } 因此在第一个for语句for (String appFieldDefId : appFieldDefIds) 中调用了HashMap.keySet().iterator() 而这个方法调用了newKeyIterator() Iterator<K> newKeyIterator() { return new KeyIterator(); } private class KeyIterator extends HashIterator<K> { public K next() { return nextEntry().getKey(); } } 所以在for中还是调用了 在第二个循环for(Entry<String, String[]> entry : paraMap.entrySet())中使用的Iterator是如下的一个内部类 private class EntryIterator extends HashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } } 此时第一个循环得到key,第二个循环得到HashMap的Entry 效率就是从循环里面体现出来的第二个循环此致可以直接取key和value值 而第一个循环还是得再利用HashMap的get(Object key)来取value值 现在看看HashMap的get(Object key)方法 public V get(Object key) { Object k = maskNull(key); int hash = hash(k); int i = indexFor(hash, table.length); //Entry[] table Entry<K,V> e = table; while (true) { if (e == null) return null; if (e.hash == hash && eq(k, e.key)) return e.value; e = e.next; } } 其实就是再次利用Hash值取出相应的Entry做比较得到结果,所以使用第一中循环相当于两次进入HashMap的Entry中 而第二个循环取得Entry的值之后直接取key和value,效率比第一个循环高。其实按照Map的概念来看也应该是用第二个循环好一点,它本来就是key和value的值对,将key和value分开操作在这里不是个好选择。 27、array(数组) 和 ArryList的使用 array([]):最高效;但是其容量固定且无法动态改变; ArrayList:容量可动态增长;但牺牲效率; 基于效率和类型检验,应尽可能使用array,无法确定数组大小时才使用ArrayList! ArrayList是Array的复杂版本 ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。 ArrayList存入对象时,抛弃类型信息,所有对象屏蔽为Object,编译时不检查类型,但是运行时会报错。 注:jdk5中加入了对泛型的支持,已经可以在使用ArrayList时进行类型检查。 从这一点上看来,ArrayList与数组的区别主要就是由于动态增容的效率问题了 28、尽量使用HashMap 和ArrayList ,除非必要,否则不推荐使用HashTable和Vector ,后者由于使用同步机制,而导致了性能的开销。 29、StringBuffer 和StringBuilder的区别: java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。 StringBuilder。与该类相比,通常应该优先使用 java.lang.StringBuilder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。 为了获得更好的性能,在构造 StirngBuffer 或 StirngBuilder 时应尽可能指定它的容量。当然,如果你操作的字符串长度不超过 16 个字符就不用了。 相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%-15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非你能确定你的系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,否则还是用 StringBuffer 吧。 文章出处:DIY部落(http://www.diybl.com/course/3_program/java/javajs/20090305/158198.html) |
struts2的国际化!配置心得
2009-12-31 13:56
| struts2的国际化!配置心得 有一段时间没有看strust2的国际化了,今天突然想起来做了以下!发现都快忘记了,以便再次忘记就在这里做一个日记同时也给大家分享一下! 首先建一个strut2的项目这就不多说! 1.在struts.properties中加入如下代码 Java代码 1.#国际化文件 2.struts.custom.i18n.resources=messageResources(这个是资源文件的前缀) #国际化文件 struts.custom.i18n.resources=messageResources(这个是资源文件的前缀) 或者在struts.xml里面加上 Java代码 1.<constant name="struts.custom.i18n.resources" value="messageResources"></constant> <constant name="struts.custom.i18n.resources" value="messageResources"></constant> 2.建一个languageAction Java代码 1.package com.hopsun.strust2.action; 2. 3.import java.util.Locale; 4. 5.import com.opensymphony.xwork2.ActionContext; 6. 7.public class InternationalAction { 8. 9. private String languageName; 10. //这个是测试直接用request_locale=zh_CN/* 11. public String ChangeLanguage() { 12. 13. return "success"; 14. } 15. //这个是测试 用我们自定义一个页面参数,更换语言类型 16. public String ChangeLanguage2() { 17. 18. Locale l = Locale.getDefault(); 19. if (this.languageName.equals("ft")) { 20. l = new Locale("zh", "TW"); 21. } else if (this.languageName.equals("en")) { 22. l = new Locale("en", "US"); 23. } else { 24. l = new Locale("zh", "CN"); 25. } 26. // ActionContext.getContext().getSession().put("WW_TRANS_I18N_LOCALE", 27. // l); 28. ActionContext.getContext().setLocale(l); 29. return "success"; 30. } 31. 32. public String getLanguageName() { 33. return languageName; 34. } 35. 36. public void setLanguageName(String languageName) { 37. this.languageName = languageName; 38. } 39. 40.} package com.hopsun.strust2.action; import java.util.Locale; import com.opensymphony.xwork2.ActionContext; public class InternationalAction { private String languageName; //这个是测试直接用request_locale=zh_CN/* public String ChangeLanguage() { return "success"; } //这个是测试 用我们自定义一个页面参数,更换语言类型 public String ChangeLanguage2() { Locale l = Locale.getDefault(); if (this.languageName.equals("ft")) { l = new Locale("zh", "TW"); } else if (this.languageName.equals("en")) { l = new Locale("en", "US"); } else { l = new Locale("zh", "CN"); } // ActionContext.getContext().getSession().put("WW_TRANS_I18N_LOCALE", // l); ActionContext.getContext().setLocale(l); return "success"; } public String getLanguageName() { return languageName; } public void setLanguageName(String languageName) { this.languageName = languageName; } } 3.struts.xml配置 Java代码 1.<action name="Change" class="Inter" method="ChangeLanguage"> 2.<result>/Internationalization.jsp</result> 3.</action> 4.<action name="Chan" class="Inter" method="ChangeLanguage2"> 5.<result>/Internationalization.jsp</result> 6.</action> <action name="Change" class="Inter" method="ChangeLanguage"> <result>/Internationalization.jsp</result> </action> <action name="Chan" class="Inter" method="ChangeLanguage2"> <result>/Internationalization.jsp</result> </action> 4.资源文件 放在classes下面,即项目/src/ messageResources_zh_CN.properties Java代码 1.#messageResources_zh_CN.properties 2.language=语言 3.name=姓名 4.age=年龄 5.sex=性别 #messageResources_zh_CN.properties language=语言 name=姓名 age=年龄 sex=性别 messageResources_en_US.properties Java代码 1.#messageResources_en_US.properties 2.language=language(re) 3.name=name(re) 4.age=age(re) 5.sex=sex(re) #messageResources_en_US.properties language=language(re) name=name(re) age=age(re) sex=sex(re) messageResources_zh_TW.properties Java代码 1.#messageResources_zh_TW.properties 2.language=語言 3.name=姓名 4.age=年齡不是問題 5.sex=性別 #messageResources_zh_TW.properties language=語言 name=姓名 age=年齡不是問題 sex=性別 5.jsp页面 Java代码 1.<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> 2.<%@ taglib prefix="s" uri="/struts-tags" %> 3.<% 4.String path = request.getContextPath(); 5.String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 6.%> 7. 8. 9.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 10.<html> 11. <head> 12. <title>My JSP 'Internationalization.jsp' starting page</title> 13. 14. <meta http-equiv="pragma" content="no-cache"> 15. <meta http-equiv="cache-control" content="no-cache"> 16. <meta http-equiv="expires" content="0"> 17. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 18. <meta http-equiv="description" content="This is my page"> 19. 20. </head> 21. 22. <body> 23.<!-- 测试第一种 对应action 方法ChangeLanguage() request_locale--> 24. <a href="<%=basePath%>Change.do?request_locale=zh_CN">中文简体</a> 25. <a href="<%=basePath%>Change.do?request_locale=zh_TW">中文繁体</a> 26. <a href="<%=basePath%>Change.do?request_locale=en_US">English</a><br> 27. 28.<!-- 测试测试自定义参数 对应action 方法ChangeLanguage2() languageName--> 29. <a href="<%=basePath%>Change.do">中文简体</a> 30. <a href="<%=basePath%>Change.do?languageName=ft">中文繁体</a> 31. <a href="<%=basePath%>Change.do?languageName=en">English</a><br> 32. 33. <s:label key="language"/><input name="language"> 34. <s:label key="name"/><input name="name"> 35. <s:label key="age"/><input name="age"> 36. <s:label key="sex"/><input name="sex"> 37. </body> 38.</html> <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'Internationalization.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <!-- 测试第一种 对应action 方法ChangeLanguage() request_locale--> <a href="<%=basePath%>Change.do?request_locale=zh_CN">中文简体</a> <a href="<%=basePath%>Change.do?request_locale=zh_TW">中文繁体</a> <a href="<%=basePath%>Change.do?request_locale=en_US">English</a><br> <!-- 测试测试自定义参数 对应action 方法ChangeLanguage2() languageName--> <a href="<%=basePath%>Change.do">中文简体</a> <a href="<%=basePath%>Change.do?languageName=ft">中文繁体</a> <a href="<%=basePath%>Change.do?languageName=en">English</a><br> <s:label key="language"/><input name="language"> <s:label key="name"/><input name="name"> <s:label key="age"/><input name="age"> <s:label key="sex"/><input name="sex"> </body> </html> 上面步骤可以互换,只要记得不要少了配置就行! 项目切图 如果有需要例子的可以留下邮箱!我给他发过去! |