??xml version="1.0" encoding="utf-8" standalone="yes"?>
一个web中完全可以没有web.xml文gQ也是_web.xml文gq不是web工程必须的?/p>
那什么时候需要,什么时候可以不需要呢Q?/p>
要想回答上面的问题,得先了解web.xml文g使用来干什么的。web.xml文g是用来配|:Ƣ迎cservlet、filter{的。当你的web工程没用到这些时Q你可以不用web.xml文g来配|你的web工程?/p>
那么web.xml能做的所有事情都有那些?
其实Qweb.xml的模?Schema)文g中定义了多少U标{օ素,web.xml中就可以出现它的模式文g所定义的标{օ素,它就能拥有定义出来的那些功能。web.xml的模式文件是由Sun公司定义的,每个web.xml文g的根元素<web-app>中,都必L明这个web.xml使用的是哪个模式文g。如Q?br /><?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
</web-app>
而且web.xml的模式文件中定义的标{ƈ不是定死的,模式文g也是可以改变的,一般来_随着web.mxl模式文g的版本升U,里面定义的功能会来复杂,也即标签元素的种cM来多Q但有些是不常用的,我们只需C一些常用的可以了?/p>
下面列出web.xml常用的标{օ素及q些标签元素的功能:
1、指定欢q页面,例如Q?br /><welcome-file-list>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index1.jsp</welcome-file>
</welcome-file-list>
上面的例子指定了2个欢q页面,昄时按序从第一个找P如果W一个存在,显C第一个,后面的不起作用。如果第一个不存在Q就扄二个Q以此类推?/p>
关于Ƣ迎面Q?/p>
讉K一个网站时Q默认看到的W一个页面就叫欢q页Q一般情况下是由首页来充当欢q页的。一般情况下Q我们会在web.xml中指定欢q页。但web.xmlq不是一个Web的必要文Ӟ没有web.xmlQ网站仍然是可以正常工作的。只不过|站的功能复杂v来后Qweb.xml的确有非常大用处Q所以,默认创徏的动态web工程在WEB-INF文g夹下面都有一个web.xml文g?br />对于tomcat来说Q当你只指定一个web的根名,没有指定具体面Q去讉K时一个webӞ 如果web.xml文g中配|了Ƣ迎,那么p回指定的那个面作ؓƢ迎,而在文中没有web.xml文gQ或虽然有web.xmlQ但web.xml也没指定Ƣ迎늚情况下,它默认先查找index.html文gQ如果找CQ就把index.html作ؓƢ迎还回给览器。如果没扑ֈindex.htmlQtomcat去找index.jsp。找到index.jsp把它作为欢q页面返回。而如果index.html和index.jsp都没扑ֈQ又没有用web.xml文g指定Ƣ迎面Q那此时tomcat׃知道该返回哪个文件了Q它?yu)显CThe requested resource (/XXX) is not available的页面。其中XXX表示web的根名。但如果你指定了具体面Q是可以正常讉K的?/p>
2、命名与定制URL。我们可以ؓServlet和JSP文g命名q定制URL,其中定制URL是依赖一命名的,命名必须在定制URL前。下面拿serlet来D例:
(1)、ؓServlet命名Q?br /><servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>net.test.TestServlet</servlet-class>
</servlet>
(2)、ؓServlet定制URL?br /><servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3、定制初始化参数Q可以定制servlet、JSP、Context的初始化参数Q然后可以再servlet、JSP、Context中获取这些参数倹{下面哪servlet来D例:
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>net.test.TestServlet</servlet-class>
<init-param>
<param-name>userName</param-name>
<param-value>Tommy</param-value>
</init-param>
<init-param>
<param-name>E-mail</param-name>
<param-value>Tommy@163.com</param-value>
</init-param>
</servlet>
l过上面的配|,在servlet中能够调用getServletConfig().getInitParameter("param1")获得参数名对应的倹{?/p>
4、指定错误处理页面,可以通过“异常cd”?#8220;错误?#8221;来指定错误处理页面?br /><error-page>
<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
-----------------------------
<error-page>
<exception-type>java.lang.Exception<exception-type>
<location>/exception.jsp<location>
</error-page>
5、设|过滤器Q比如设|一个编码过滤器Q过滤所有资?br /><filter>
<filter-name>XXXCharaSetFilter</filter-name>
<filter-class>net.test.CharSetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XXXCharaSetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6、设|监听器Q?br /><listener>
<listener-class>net.test.XXXLisenet</listener-class>
</listener>
7、设|会?Session)q期旉Q其中时间以分钟为单位,假如讄60分钟时Q?br /><session-config>
<session-timeout>60</session-timeout>
</session-config>
除了q些标签元素之外Q还可以往web.xml中添加那些标{օ素呢Q那些标{օ素都能v什么作用呢Q我们只要去查看web.xml的模式文件就能知道。直接看模式文g看不懂,可以找一些中文教E来看看?/p>
首先我们先来看下Stringcȝ源码Q可以发现String是重写了ObjectcȝequalsҎ(gu)的,q且也重写了hashcodeҎ(gu)
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; } public int hashCode() { int h = hash; if (h == 0) { int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; }
那ؓ什么在重写equalsҎ(gu)旉要重写equalsҎ(gu)呢:
首先equals与hashcode间的关系是这L(fng)Q?/p>
1、如果两个对象相同(即用equals比较q回trueQ,那么它们的hashCodeg定要相同Q?/p>
2、如果两个对象的hashCode相同Q它们ƈ不一定相?即用equals比较q回false)
自我的理解:׃Z提高E序的效率才实现了hashcodeҎ(gu)Q先q行hashcode的比较,如果不同Q那没就不必在进行equals的比较了Q这样就大大减少了equals比较?/p>
ơ数Q这Ҏ(gu)需要比较的数量很大的效率提高是很明昄Q一个很好的例子是在集合中的用;
我们都知道java中的List集合是有序的Q因此是可以重复的,而set集合是无序的Q因此是不能重复的,那么怎么能保证不能被攑օ重复的元素呢Q但靠equalsҎ(gu)一h较的
话,如果原来集合中以后又10000个元素了Q那么放?0001个元素,N要将前面的所有元素都q行比较Q看看是否有重复Q欧码噶的,q个效率可想而知Q因此hashcode
应遇而生了,java采用了hash表,利用哈希法Q也叫散列算法)Q就是将对象数据Ҏ(gu)该对象的特征使用特定的算法将其定义到一个地址上,那么在后面定义进来的数据
只要看对应的hashcode地址上是否有|那么qequals比较Q如果没有则直接插入Q只要就大大减少了equals的用次敎ͼ执行效率大大提高了?/p>
l箋上面的话题,Z么必要重写hashcodeҎ(gu)Q其实简单的说就是ؓ了保证同一个对象,保证在equals相同的情况下hashcode值必定相同,如果重写了equals而未重写
hashcodeҎ(gu)Q可能就会出C个没有关pȝ对象equals相同的(因ؓequal都是Ҏ(gu)对象的特征进行重写的Q,但hashcode实不相同的
a.Hashtable是承自陈旧的DictionarycȝQHashMapl承自AbstractMapcd时是Java 1.2引进的Map接口的一个实现?br /> b.也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这意味着Q然你可以不用采取Q何特D的行ؓ可以在一?多线E的应用E序中用一个HashtableQ但你必d样地Z个HashMap提供外同步。一个方便的Ҏ(gu)是利用Collectionscȝ静态的synchronizedMap()Ҏ(gu)Q它创徏一个线E安全的Map对象Qƈ把它作ؓ一个封装的对象来返回。这个对象的Ҏ(gu)可以让你同步讉K潜在的HashMap。这么做的结果就是当你不需要同步时Q你不能切断Hashtable中的同步Q比如在一个单U程的应用程序中Q,而且同步增加了很多处理费用?br /> c.W三点不同是Q只有HashMap可以让你空gZ个表的条目的key或value。HashMap中只有一条记录可以是一个空的keyQ但L数量的条目可以是I的value。这是_如果在表中没有发现搜索键Q或者如果发C搜烦键,但它是一个空的|那么get()返回null。如果有必要Q用containKey()Ҏ(gu)来区别这两种情况?br /> d.HashMapL了Hashtable的containsҎ(gu)Q保留了containsValue和containsKeyҎ(gu)
e.Hashtable中h(hun)ash数组默认大小?1Q增加的方式?old*2+1。HashMap中h(hun)ash数组的默认大是16Q而且一定是2的指?br />
ArrayList和LinkedList区别
对于处理一列数据项,Java提供了两个类ArrayList和LinkedList,ArrayList的内部实现是Z内部数组Object[],所以从概念上讲,它更象数l,但LinkedList的内部实现是Z一l连接的记录,所?它更象一个链表结构,所?它们在性能上有很大的差别?br />从上面的分析可知,在ArrayList的前面或中间插入数据?你必d其后的所有数据相应的后移,q样必然要花费较多时_所?当你的操作是在一列数据的后面d数据而不是在前面或中?q且需要随机地讉K其中的元素时,使用ArrayList会提供比较好的性能
而访问链表中的某个元素时,必M链表的一端开始沿着q接方向一个一个元素地L?直到扑ֈ所需的元素ؓ止,所?当你的操作是在一列数据的前面或中间添加或删除数据,q且按照序讉K其中的元素时,应该用LinkedList了?br />如果在编E中,1Q?两种情Ş交替出现,q时,你可以考虑使用Listq样的通用接口,而不用关心具体的实现Q在具体的情形下,它的性能由具体的实现来保证?br />配置集合cȝ初始大小
在Java集合框架中的大部分类的大是可以随着元素个数的增加而相应的增加的,我们g不用兛_它的初始大小,但如果我们考虑cȝ性能问题?׃定要考虑可能地讄好集合对象的初始大小,q将大大提高代码的性能?br />比如,Hashtable~省的初始大ؓ101,载入因子?.75,卛_果其中的元素个数过75?它就必须增加大小q新组l元素,所?如果你知道在创徏一个新的Hashtable对象时就知道元素的确切数目如?10,那么,应其初始大小设ؓ110/0.75=148,q样,可以避免重新组l内存ƈ增加大小
2?strong>对于单个字符QISO-8859-1单字节编码,GBK双字节编码,UTF-8三字节编?/span>Q?strong>因此中文q_(中文q_默认字符集编码GBK)下一个中文字W占2个字节,而英文^?英文q_默认字符集编码Cp1252(cM于ISO-8859-1))?/span>
3?strong>getBytes()、getBytes(encoding)函数的作用是使用pȝ默认或者指定的字符集编码方式,字W串~码成字节数l?/span>?/strong>
~码方式军_字节长度Q?strong>在中文^CQ默认的字符集编码是GBKQ?/span>此时如果使用getBytes()或getBytes("GBK")Q?strong>则按照GBK的编码规则将每个中文字符?个byte表示?strong>所以我们看?中文"最lGBK~码l果是Q?-42 -48 -50 -60 ?42?48代表??字,?-50"?-60"则代表了"?字?/span>
在中文^CQ?span style="background-color: rgb(255,255,255)">如果指定的字W集~码是UTF-8Q那么按照UTF-8对中文的~码规则Q每个中文用3个字节表C,那么"中文"q两个字W最l被~码成:-28 -72 -83?26 -106 -121两组。每3个字节代表一个中文字W?/span>
在中文^CQ如果指定的字符集编码是ISO-8859-1Q由于此字符集是单字节编码,所以用getBytes("ISO-8859-1")Ӟ每个字符只取一个字节,每个汉字只取C一半的字符。另外一半的字节丢失了。由于这一半的字符在字W集中找不到对应的字W,所以默认用编?3代替Q也是??/strong>
在英文^CQ默认的字符集编码是Cp1252(cM于ISO-8859-1)Q?strong>如果使用GBK、UTF-8q行~码Q得到的字节数组依然是正的(GBK4个字节,UTF-8?个字?。因为在JVM内部是以Unicode存储字符串的Q用getBytes(encoding)会让JVMq行一ơUnicode到指定编码之间的转换?/span>对于GBKQJVM依然会{换成4个字节,对于UTF-8QJVM依然会{换成6个字节?strong>但是对于ISO-8859-1Q则׃无法转换(2个字?-->1个字节,截取了一半的字节)Q所以{换后的结果是错误的?/span>
在中文^CQ默认的字符集编码是GBKQ于是content.getBytes()得到的是什么呢Q就是下面这4个字节:
byte[0] = -42 hex string = ffffffd6
byte[1] = -48 hex string = ffffffd0
byte[2] = -50 hex string = ffffffce
byte[3] = -60 hex string = ffffffc4
如果新的encoding是GBKQ那么经q解码后Q由于一个字W用2个字节表C。于是最l的l果是Q?/span>
char[0]='? --- byte[0] + byte[1]
char[1]='? --- byte[2] + byte[3]
如果新的encoding是ISO-8859-1Q那么经q解码后Q由于一个字W用1个字节表C,于是原来本应?个字节一赯析的变成单个字节解析Q每个字节都代表了一个汉字字W的一半。这一半的字节在ISO-8859-1中找不到对应的字W,变成了"?"了,最l的l果Q?/span>
char[0]='?' ---- byte[0]
char[1]='?' ---- byte[1]
char[2]='?' ---- byte[2]
char[3]='?' ---- byte[3]
如果新的encoding是UTF-8Q那么经q解码后Q由于一个字W用3个字节表C,于是原来4个字节的数据无法正常的解析成UTF-8的数据,最l的l果也是每一个都变成"?"?/span>
char[0]='?' ---- byte[0]
char[1]='?' ---- byte[1]
char[2]='?' ---- byte[2]
char[3]='?' ---- byte[3]
如果是在英文q_下,׃默认的编码方式是Cp1252Q于是content.getBytes()得到的字节都是被截去一半的D留字符Q所以我们看到在英文q_下,不论指定的encoding是GBK、UTF-8Q其l果和ISO-8859-1都是一L(fng)?/span>
CQ这个方法再ơ证明了String的getBytes()Ҏ(gu)的危险性,如果我们使用new String(str.getBytes(), encoding)对字W串q行重新~码解码Ӟ我们一定要清楚str.getBytes()Ҏ(gu)q回的字节数l的长度、内容到底是什么,因ؓ在接下来使用新的encodingq行~码解码ӞJavaq不会自动地对字节数l进行扩展以适应新的encoding。而是按照新的~码Ҏ(gu)直接对该字节数组q行解析?/span>于是l果像上面的例子一P同样?个原始字节,有些?个一l进行解析,有些每个一l进行解析,有些?个一l进行解析。其l果只能看那种~码方式合适了?/span>
l论Q?/strong>相同的^CQ同一个中文字W,在不同的~码方式下,得到的是完全不同的字节数l。这些字节数l有可能是正的(只要该字W集支持中文)Q也可能是完全错误的(该字W集不支持中??/span>
CQ不要轻易地使用或滥用StringcȝgetBytes(encoding)Ҏ(gu)Q更要尽量避免用getBytes()Ҏ(gu)。因个方法是q_依赖的,在^C可预知的情况下完全可能得C同的l果?strong>如果一定要q行字节~码Q则用户要确保encoding的方法就是当初字W串输入时的encoding?/span>
———————————————————————————————————————————————————
和getBytes(encoding)不同QtoCharArray()q回的是"自然字符"。但是这?自然字符"的数目和内容却是由原始的~码方式军_?/span>?/span>
FileWriter是字W流输出,而OutputStreamWriter是字节流输出在中文q_下,如果使用FileWriterQ不Z如何讄字符集都不会起作用。因为它采用的是默认的系l字W集。即便你讄了System.setProperty("file.encoding", "ISO-8859-1")Q或者在q行时给予参?Dfile.encoding=UTF-8都不会v作用。你会发现它最l还是都?GB2312"或?GBK"的方式保存?/span>
在中文^CQ如果用OutputStreamWriterQ则在后台写入时会把字符{换成字节,此时指定的编码字W集pv作用了。可以看到在指定GBK、UTF-8的情况下中文可以正常的保存和dQ同时文件按照我们给定的方式保存了。而对于ISO-8859-1则变成了?Q这再次证明了采用ISO-8859-1是不能保存中文的Q而且会因Z文编码在ISO-8859-1的编码中找不到对应的字符而默认{换成??/span>
在英文^CQ如果用FileWriterQ不Z如何讄字符集同样都不会起作用。所有的文g都将按照ISO-8859-1的编码方式保存,毫无疑问地变成了?。在英文q_下,如果使用OutputStreamWriterQ则只有当我们把字符和文件的~码方式正确讄为GBK、UTF-8的情况下Q中文才能正的保存q显C?/span>
通过上述的实验证明,Z保在不同的q_下,客户端输入的中文可以被正地解析、保存、读取。最好的办法是使用OutputStreamWriter配合UTF-8~码?/span>如果不想使用UTF-8~码Q那么可以考虑使用GB2312Q不使用GBK、GB18030。因为对于某些老式的文本编辑器Q甚至不支持GBK、GB18030的编码,但是对于GB2312则是一定支持的。因为前两者都不是国标但后者是?/span>
关于String的getBytes()QgetBytes(encoding)和new String(bytes, encoding)q三个方法,非常值得注意QA.getBytes()Q用^台默认的~码方式(通过file.encoding属性获?方式来将字符串{换成byte[]。得到的是字W串最原始的字节编码倹{?/span>
B.getBytes(NAME_OF_CHARSET)Q?strong>使用指定的编码方式将字符串{换成byte[]Q如果想要得到正的字节数组Q程序员必须l出正确的NAME_OF_CHARSET。否则得到的׃会得到正的l果?/span>
C.new String(bytes, encoding)Q?strong>如果我们在客L(fng)使用UTF-8~码的JSP面发出hQ浏览器~码后的UTF-8字节会以ISO-8859-1的Ş式传递到服务器端。所以要得到lHTTP协议传输的原始字节,我们需要先调用getBytes("ISO-8859-1")得到原始的字节,但由于我们客L(fng)的原始编码是UTF-8Q如果l按照ISO-8859-1解码Q那么得到的不是一个中文字W,而是3个ؕ码的字符。所以我们需要再ơ调用new String(bytes,"UTF-8")Q将字节数组按照UTF-8的格式,?个一l进行解码,才能q原为客L(fng)的原始字W?/span>
D.String的getBytes()、getBytes(NAME_OF_CHARSET)Ҏ(gu)都是比较微妙的方法,原则上:传输旉用的是什么编码,我们需要按照这U编码得到字节。new String(bytes, NAME_OF_CHARSET)则更加需要小心,原则上:客户端采用的是什么编码,那么q里的NAME_OF_CHARSET必d客户端保持一致?strong>例如JSP面是GBKQ那么我们接攉面传递而来的参数时必M用new String(parameter.getBytes("ISO-8859-1"), "GBK");如果使用了错误的解码方式Q如使用了UTF-8Q那么得到的很有可能是q了。也是_GBK--->ISO-8859-1--->GBK、UTF-8--->ISO-8859-1--->UTF-8的{换过E是没有问题的。但是GBK--->ISO-8859-1--->UTF-8、UTF-8--->ISO-8859-1--->GBK的字节直接{码则可能DqQ需要另外的转换q程?/span>
CQ?/span>谨慎C用getBytes(NAME_OF_CHARSET)和new String(bytes, NAME_OF_CHARSET)Q除非你很清楚的知道原始的字W编码和传输协议使用的编码。推荐用基于服务器的配|、过滤器讄request/response的characterEncoding、content type属性。还有就是JSP面的pageEncoding属性、HTML meta元素的content type属性。尽量避免频J的在代码中q行字符串{码,即降低了效率又增加了风险?/span>
问题Q我们在web应用开发过E中l常遇到输出某种~码的字W,如iso8859-1{,如何输出一个某U编码的字符Ԍ
代码如下Q?/span>GBK 10 -50 utf-8 15 -26 ???????ú?? 我是中国?
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection接口
Collection是最基本的集合接口,一个Collection代表一lObjectQ即Collection的元素(ElementsQ。一?Collection允许相同的元素而另一些不行。一些能排序而另一些不行?a class="channel_keylink" target="_blank">Java SDK不提供直接承自Collection的类Q?Java SDK提供的类都是l承自Collection?#8220;子接?#8221;如List和Set?/p>
所有实现Collection接口的类都必L供两个标准的构造函敎ͼ无参数的构造函数用于创Z个空的CollectionQ有一?Collection参数的构造函数用于创Z个新?CollectionQ这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection?/p>
如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个P代子Q用该q代子即可逐一讉KCollection中每一个元素。典型的用法如下Q?/p>
Iterator it = collection.iterator(); // 获得一个P代子
while(it.hasNext()) {
Object obj = it.next(); // 得到下一个元?/p>
}
由Collection接口z的两个接口是List和Set?/p>
List接口
List是有序的CollectionQ用此接口能够_的控制每个元素插入的位置。用戯够用烦引(元素在List中的位置Q类g数组下标Q来讉KList中的元素Q这cM于Java的数l?/p>
和下面要提到的Set不同QList允许有相同的元素?/p>
除了hCollection接口必备的iterator()Ҏ(gu)外,Listq提供一个listIterator()Ҏ(gu)Q返回一?ListIterator接口Q和标准的Iterator接口相比QListIterator多了一些add()之类的方法,允许dQ删除,讑֮元素Q还能向前或向后遍历?/p>
实现List接口的常用类有LinkedListQArrayListQVector和Stack?/p>
LinkedListc?/p>
LinkedList实现了List接口Q允许null元素。此外LinkedList提供额外的getQremoveQinsertҎ(gu)?LinkedList的首部或N。这些操作LinkedList可被用作堆栈QstackQ,队列QqueueQ或双向队列QdequeQ?/p>
注意LinkedList没有同步Ҏ(gu)。如果多个线E同时访问一个ListQ则必须自己实现讉K同步。一U解x法是在创建List时构造一个同步的ListQ?/p>
List list = Collections.synchronizedList(new LinkedList(...));
ArrayListc?/p>
ArrayList实现了可变大的数组。它允许所有元素,包括null。ArrayList没有同步?/p>
sizeQisEmptyQgetQsetҎ(gu)q行旉为常数。但是addҎ(gu)开销为分摊的常数Q添加n个元素需要O(n)的时间。其他的Ҏ(gu)q行旉为线性?/p>
每个ArrayList实例都有一个容量(CapacityQ,即用?a class="channel_keylink" target="_blank">存储元素的数l的大小。这个容量可随着不断d新元素而自动增加,但是增长法q没有定义。当需要插入大量元素时Q在插入前可以调用ensureCapacityҎ(gu)来增加ArrayList的容量以提高插入效率?/p>
和LinkedList一PArrayList也是非同步的QunsynchronizedQ?/p>
Vectorc?/p>
Vector非常cMArrayListQ但是Vector是同步的。由Vector创徏的IteratorQ虽然和ArrayList创徏?Iterator是同一接口Q但是,因ؓVector是同步的Q当一个Iterator被创且正在被用,另一个线E改变了Vector的状态(例如Q添加或删除了一些元素)Q这时调用Iterator的方法时抛出ConcurrentModificationExceptionQ因此必L莯异常?/p>
Stack c?/p>
Stackl承自VectorQ实C个后q先出的堆栈。Stack提供5个额外的Ҏ(gu)使得 Vector得以被当作堆栈用。基本的push和popҎ(gu)Q还有peekҎ(gu)得到栈顶的元素,emptyҎ(gu)试堆栈是否为空QsearchҎ(gu)一个元素在堆栈中的位置。Stack刚创建后是空栈?/p>
Set接口
Set是一U不包含重复的元素的CollectionQ即L的两个元素e1和e2都有e1.equals(e2)=falseQSet最多有一个null元素?/p>
很明显,Set的构造函数有一个约束条Ӟ传入的Collection参数不能包含重复的元素?/p>
h意:必须心操作可变对象QMutable ObjectQ。如果一个Set中的可变元素改变了自w状态导致Object.equals(Object)=true导致一些问题?/p>
Map接口
h意,Map没有l承Collection接口QMap提供key到value的映。一个Map中不能包含相同的keyQ每个key只能映射一?value。Map接口提供3U集合的视图QMap的内容可以被当作一lkey集合Q一lvalue集合Q或者一lkey-value映射?/p>
Hashtablec?/p>
Hashtablel承Map接口Q实C个key-value映射的哈希表。Q何非I(non-nullQ的对象都可作ؓkey或者value?/p>
d数据使用put(key, value)Q取出数据用get(key)Q这两个基本操作的时间开销为常数?/p>
Hashtable 通过initial capacity和load factor两个参数调整性能。通常~省的load factor 0.75较好地实C旉和空间的均衡。增大load factor可以节省I间但相应的查找旉增大,q会影响像get和putq样的操作?/p>
使用Hashtable的简单示例如下,?Q?Q?攑ֈHashtable中,他们的key分别?#8221;one”Q?#8221;two”Q?#8221;three”Q?/p>
Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
要取Z个数Q比?Q用相应的keyQ?/p>
Integer n = (Integer)numbers.get(“two”);
System.out.println(“two = ” + n);
׃作ؓkey的对象将通过计算其散列函数来定与之对应的value的位|,因此M作ؓkey的对象都必须实现hashCode和equalsҎ(gu)。hashCode和equalsҎ(gu)l承自根cObjectQ如果你用自定义的类当作key的话Q要相当心Q按照散列函数的定义Q如果两个对象相同,即obj1.equals(obj2)=trueQ则它们的hashCode必须相同Q但如果两个对象不同Q则它们的hashCode不一定不同,如果两个不同对象的hashCode相同Q这U现象称为冲H,冲突会导致操作哈希表的时间开销增大Q所以尽量定义好的hashCode()Ҏ(gu)Q能加快哈希表的操作?/p>
如果相同的对象有不同的hashCodeQ对哈希表的操作会出现意想不到的l果Q期待的getҎ(gu)q回nullQ,要避免这U问题,只需要牢C条:要同时复写equalsҎ(gu)和hashCodeҎ(gu)Q而不要只写其中一个?/p>
Hashtable是同步的?/p>
HashMapc?/p>
HashMap和HashtablecMQ不同之处在于HashMap是非同步的,q且允许nullQ即null value和null key。,但是HashMap视ؓCollectionӞvalues()Ҏ(gu)可返回CollectionQ,其P代子操作旉开销和HashMap 的容量成比例。因此,如果q代操作的性能相当重要的话Q不要将HashMap的初始化定w讑־q高Q或者load factorq低?/p>
WeakHashMapc?/p>
WeakHashMap是一U改q的HashMapQ它对key实行“弱引?#8221;Q如果一个key不再被外部所引用Q那么该key可以被GC回收?/p>
ȝ
如果涉及到堆栈,队列{操作,应该考虑用ListQ对于需要快速插入,删除元素Q应该用LinkedListQ如果需要快速随问元素,应该使用ArrayList?/p>
如果E序在单U程环境中,或者访问仅仅在一个线E中q行Q考虑非同步的c,其效率较高,如果多个U程可能同时操作一个类Q应该用同步的cR?/p>
要特别注意对哈希表的操作Q作为key的对象要正确复写equals和hashCodeҎ(gu)?/p>
量q回接口而非实际的类型,如返回List而非ArrayListQ这样如果以后需要将ArrayList换成LinkedListӞ客户端代码不用改变。这是针对抽象~程?/p>
同步?/p>
Vector 是同步的。这个类中的一些方法保证了Vector中的对象是线E?a class="channel_keylink" target="_blank">安全的。而ArrayList则是异步的,因此ArrayList中的对象q不是线E?a class="channel_keylink" target="_blank">安全的。因为同步的要求会媄响执行的效率Q所以如果你不需要线E安全的集合那么使用ArrayList是一个很好的选择Q这样可以避免由于同步带来的不必要的性能开销?/p>
数据增长
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控刉合中的对象。当你向q两U类型中增加元素的时候,如果元素的数目超Z内部数组目前的长度它们都需要扩展内部数l的长度QVector~省情况下自动增长原来一倍的数组长度Q?ArrayList是原来的50%,所以最后你获得的这个集合所占的I间L比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用 Vector有一些优势,因ؓ你可以通过讄集合的初始化大小来避免不必要的资源开销?/p>
使用模式
在ArrayList和Vector中,从一个指定的位置Q通过索引Q查找数据或是在集合的末֢加、移除一个元素所p的时间是一L(fng)Q这个时间我们用 O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的旉会呈UŞ增长QO(n-i)Q其中n代表集合中元素的个数Qi代表元素增加或移除元素的索引位置。ؓ什么会q样呢?以ؓ在进行上q操作的时候集合中Wi和第i个元素之后的所有元素都要执行位Uȝ操作。这一切意味着什么呢Q?/p>
q意味着Q你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作Q你最好选择其他的集合操作类。比如,LinkList集合cd增加或移除集合中M位置的元素所p的时间都是一L(fng)?O(1)Q但它在索引一个元素的使用~比较慢QO (i),其中i是烦引的位置.使用 ArrayList也很Ҏ(gu)Q因Z可以单的使用索引来代替创建iterator对象的操作。LinkList也会为每个插入的元素创徏对象Q所有你要明白它也会带来额外的开销?/p>
最后,在《Practical Java》一书中Peter Haggar使用一个简单的数组QArrayQ来代替Vector或ArrayList。尤其是对于执行效率要求高的E序更应如此。因Z用数l?(Array)避免了同步、额外的Ҏ(gu)调用和不必要的重新分配空间的操作?/p>
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/cecoo/archive/2008/04/21/2311909.aspx
cd jdk1.6.0_13\jre\lib\security
keytool -import -alias cacerts -keystore cacerts -file ?$INSTALL/exchange_certnew.cer -trustcacerts
标红处ؓ证书的全路径
此时命o行会提示你输入cacerts证书库密?o:p>
java中cacerts证书库默认密码ؓchangeit
Y认卛_QOKQ认证已d至keystore
windows
W一步:
IE打开该网站,把要导入java证书库的证书下蝲在该|页安全警报弹出H口上查看证?-详细信息--复制到文件会弹出一个证书导出向导对话框Q按提示一直下一步直到完成。我把证书保存在C盘,test.cer
W二步:
q入C:\Program Files\Java\jre6\lib\security 目录下。注意观察Eclipse控制C调用哪个jreQ通常JDK中包?个jreQ一个是开发的Q一个是JAVA使用的,Eclipse通常是jre6而不是jre1.6.0_02
然后调用命oQ?/p>
keytool -import -alias cacerts -keystore cacerts -file C:\test.cer -trustcacerts
-alias后面是别名,可以随便写?
此时命o行会提示你输入cacerts证书库密?
java中cacerts证书库默认密码ؓchangeit
Y认卛_QOKQ认证已d至keystore
可以获取当前的年月时?也可以分开?
如果惌取当前的q月,则可以这样写(只获取时间或U种一?:
当然q有是可以指定时区的时??:
df=DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.CHINA);
System.out.println(df.format(new Date()));
CSV文g是一个计机数据文g用于执行审判和真正的l织工具Q逗号分隔的清单。常常被用于Ud表格数据之间的两个不同的计算机程序,例如关系数据库程序和?sh)子表格E序?/p>
本文以下面这个CSV文gZQ向大家要介lJava语言的CSVd操作的一U实现方法?/p>
writers.csv
张艺?1951,1114
沈?1981,0507
孙红?1970,0816
闫妮,1971,0310
CSVd操作
CSV文gd主要用到java.io.BufferedReadercdjava.util.StringTokenizerc,BufferedReader用来d文gQStringTokenizer用来一行数据分成多个字Dc?/p>
下面是用来读取CSV文g内容的类Q?/p>
package tip;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;
public class ReadCSV {
public static void main(String[] args) {
try {
File csv = new File("C:\\writers.csv"); // CSV文g
BufferedReader br = new BufferedReader(new FileReader(csv));
// d直到最后一?
String line = "";
while ((line = br.readLine()) != null) {
// 把一行数据分割成多个字段
StringTokenizer st = new StringTokenizer(line, ",");
while (st.hasMoreTokens()) {
// 每一行的多个字段用TAB隔开表示
System.out.print(st.nextToken() + "\t");
}
System.out.println();
}
br.close();
} catch (FileNotFoundException e) {
// 捕获File对象生成时的异常
e.printStackTrace();
} catch (IOException e) {
// 捕获BufferedReader对象关闭时的异常
e.printStackTrace();
}
}
}
执行l果如下所C:
CSV写操?br />CSV文gd主要用到java.io.BufferedWritercR?/p>
下面是写CSV文g的类Q?/p>
package tip;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
public class WriteCSV {
public static void main(String[] args) {
try {
File csv = new File("C:\\writers.csv"); // CSV文g
// q记模式
BufferedWriter bw = new BufferedWriter(new FileWriter(csv, true));
// 新增一行数?
bw.newLine();
bw.write("三枪拍案惊奇" + "," + "2009" + "," + "1212");
bw.close();
} catch (FileNotFoundException e) {
// 捕获File对象生成时的异常
e.printStackTrace();
} catch (IOException e) {
// 捕获BufferedWriter对象关闭时的异常
e.printStackTrace();
}
}
}
执行之后的writers.csv文g如下所C:
张艺?1951,1114
沈?1981,0507
孙红?1970,0816
闫妮,1971,0310
三枪拍案惊奇,2009,1212
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/aerchi/archive/2010/03/10/5364056.aspx
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
public class ReadFile {
public ReadFile() {
}
/**
* d某个文g夹下的所有文?/span>
*/
public static boolean readfile(String filepath) throws FileNotFoundException, IOException {
try {
File file = new File(filepath);
if (!file.isDirectory()) {
System.out.println("文g");
System.out.println("path=" + file.getPath());
System.out.println("absolutepath=" + file.getAbsolutePath());
System.out.println("name=" + file.getName());
} else if (file.isDirectory()) {
System.out.println("文g?/span>");
String[] filelist = file.list();
for (int i = 0; i < filelist.length; i++) {
File readfile = new File(filepath + "\\" + filelist[i]);
if (!readfile.isDirectory()) {
System.out.println("path=" + readfile.getPath());
System.out.println("absolutepath="
+ readfile.getAbsolutePath());
System.out.println("name=" + readfile.getName());
} else if (readfile.isDirectory()) {
readfile(filepath + "\\" + filelist[i]);
}
}
}
} catch (FileNotFoundException e) {
System.out.println("readfile() Exception:" + e.getMessage());
}
return true;
}
/**
* 删除某个文g夹下的所有文件夹和文?/span>
*/
/*public static boolean deletefile(String delpath)
throws FileNotFoundException, IOException {
try {
File file = new File(delpath);
if (!file.isDirectory()) {
System.out.println("1");
file.delete();
} else if (file.isDirectory()) {
System.out.println("2");
String[] filelist = file.list();
for (int i = 0; i < filelist.length; i++) {
File delfile = new File(delpath + "\\" + filelist[i]);
if (!delfile.isDirectory()) {
System.out.println("path=" + delfile.getPath());
System.out.println("absolutepath="
+ delfile.getAbsolutePath());
System.out.println("name=" + delfile.getName());
delfile.delete();
System.out.println("删除文g成功");
} else if (delfile.isDirectory()) {
deletefile(delpath + "\\" + filelist[i]);
}
}
file.delete();
}
} catch (FileNotFoundException e) {
System.out.println("deletefile() Exception:" + e.getMessage());
}
return true;
}*/
public static void main(String[] args) {
try {
readfile("e:/videos");
// deletefile("D:/file");
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
}
System.out.println("ok");
}
}
软g?javax.servlet 不存?/span>
软g包javax.servlet.http 不存?{错?/span>
׃servlet和JSP不是Javaq_JavaSEQ标准版Q的一部分Q而是Java EEQ企业版Q的一部分Q因此,必须告知~译器servlet的位|?/span>
解决“软g?javax.servlet不存?#8221;错误的方法:
1. 搜烦servlet-api.jar
所在文件夹QC:\Tomcat5.5\common\lib
2. 环境变量CLASSPATH的D|ؓQ?/span>
.;C:\Tomcat5.5\common\lib\servlet-api.jar
3. 除了讄classpath以及servlet-api.jar外,q有一点!Q!
把COMMON/LIB下的SERVLET-API.JAR 拯到JDK/jre\lib\ext?/p>