屬性 |
描述 |
onreadystatechange |
每次狀態改變所觸發事件的事件處理程序 |
readyState |
對象狀態值:
|
responseText |
從服務器進程返回的數據的字符串形式 |
responseXML |
從服務器進程返回的DOM兼容的文檔數據對象 |
status |
從服務器返回的數字代碼,比如404(未找到)或200(就緒) |
statusText |
伴隨狀態碼的字符串信息 |
BOOKS GENERAL
Jolt Winner: Prefactoring by Ken Pugh (O''Reilly)
Productivity Winners:
? Innovation Happens Elsewhere: Open Source as Business Strategy by Ron Goldman, Richard P. Gabriel (Morgan Kaufmann)
? Producing Open Source Software: How to Run a Successful Free Software Project by Karl Fogel (O''Reilly)
? The Art of Project Management by Scott Berkun (O''Reilly)
BOOKS TECHNICAL
Jolt Winner: Agile Web Development with Rails by Dave Thomas, David Hansson, Leon Breedt and Mike Clark (Pragmatic Bookshelf)
Productivity Winners:
? Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries by Krzysztof Cwalina and Brad Abrams (Addison-Wesley)
? Practical Common Lisp by Peter Seibel (Apress)
? Why Programs Fail: A Guide to Systematic Debugging by Andreas Zeller (Morgan Kaufmann)
ENTERPRISE PROJECT MANAGEMENT
Jolt Winner: WelcomRisk 2.6 (Welcom)
Productivity Winners:
? Corticon Business Rules Management 4.0 (Corticon)
? JBoss 2 Portal (JBoss)
? Visual Studio Team System 2005 (Microsoft)
DATABASE ENGINES AND DATA TOOLS
Jolt Winner: Microsoft SQL Server 2005 (Microsoft)
Productivity Winners:
? Berkeley DB 4.4 (Sleepycat Software)
? Google Maps API 2005 (Google)
? MySQL 5.0 (MySQL)
DEFECT TRACKING, CHANGE AND CONFIGURATION MANAGEMENT
Jolt Winner: Perforce SCM 2005 (Perforce)
Productivity Winners:
? FogBugz 4.0 (Fog Creek)
? Guiffy SureMerge 7.0 (Guiffy Software)
? JIRA 3.4 (Atlassian Software)
DESIGN TOOLS AND MODELING
Jolt Winner: Lattix LDM 2.0 (Lattix)
Productivity Winners:
? Borland Together 2006 for Eclipse (Borland)
? Enterprise Architect 6.0 (Sparx Systems)
? MindManager Pro 6.0 (Mindjet)
DEVELOPMENT ENVIRONMENTS
Jolt Winner: Visual Studio Team System 2005 (Microsoft)
Productivity Winners:
? Eclipse SDK 3.1 (Eclipse.org)
? IntelliJ IDEA 5.0 (JetBrains)
? Komodo 3.5 (ActiveState)
LIBRARIES, FRAMEWORKS AND COMPONENTS
Jolt Winner: .NET Framework 2.0 (Microsoft)
Productivity Winners:
? Dundas Chart for .NET 5.0 (Dundas Software)
? Qt 4.0 (Trolltech)
? Spring Framework 1.2.6 (SpringFramework.org)
MOBILE DEVELOPMENT TOOLS
Jolt Winner: Crossfire 5.6 (AppForge)
Productivity Winners:
? Carbide.c++ Express (Nokia)
? Flash Lite 2.0 (Adobe)
? NetBeans IDE 4.1 (Sun Microsystems)
QUALITY PROJECT MANAGEMENT
Jolt Winner: Rally 5.6 (Rally Software Development)
Productivity Winners:
? CollabNet Enterprise Edition with Project Dashboard/Task Management 2005 (CollabNet)
? QACenter Enterprise Edition 5.1 (Compuware)
? TargetProcess Suite 1.4 (TargetProcess)
SECURITY TOOLS
Jolt Winner: Elemental Compliance System 1.4 (Elemental)
Productivity Winners:
? CodeAssure 2.0 (Secure Software)
? DevPartner SecurityChecker 1.0 (Compuware)
? Fortify Security Tester 1.0 (Fortify)
TESTING TOOLS
Jolt Winner: VMTN Subscription 2005 (VMware)
Productivity Winners:
? Agitator 3.0 (Agitar Software)
? AQtime 4.7 (AutomatedQA)
? Clover 1.3 (Cenqua)
UTILITIES
Jolt Winner: Camtasia Studio 3.0 (TechSmith)
Productivity Winners:
? DevPartner Studio 8 (Compuware)
? Fog Creek Copilot 1.2 (Fog Creek Software)
? ReSharper 1.5 (JetBrains)
WEB DEVELOPMENT TOOLS
Jolt Winner: Rails 1.0 (rubyonrails.org)
Productivity Winners:
? JBoss Application Server 4x (JBoss)
? Macromedia Studio 8 2005 (Adobe)
? Zend Studio - Enterprise Edition 5.0 (Zend)
HALL OF FAME WINNER:
? Visual Studio Professional Edition (Microsoft)
如何用Script語言訪問網頁的某個元素及其相關的應用 作者:時の卵
A.例子一:如何獲得頁面中的所有HTML元素?
<HTML>
<HEAD><TITLE>顯示頁面中所有的HTML元素</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function showElements() {
var tag_names = "";
for (i=0; i<document.all.length; i++)
tag_names = tag_names + document.all(i).tagName + " ";
alert("本頁面中的元素有 " + tag_names);
}
</SCRIPT>
</HEAD>
<BODY onload="showElements()">
<H1>歡迎</H1>
<P>這是一個 <B>測試</B> 文件.</P>
</BODY>
</HTML>
B.例子二:如何獲得元素的子元素?
<HTML id=theHTML>
<HEAD>
<TITLE>顯示所有元素及theHTML的子元素</TITLE>
<SCRIPT language=JavaScript>
function showme() {
alert('theHTML下共有 ' + window.theHTML.all.length+' 個HTML的元素');
for (i=0; i < theHTML.all.length;i++)
{
alert(theHTML.all[i].tagName);
}
alert('theHTML下的子元素共有 ' + window.theHTML.children.length+' 個')
;
for (i=0; i < theHTML.children.length;i++)
{
alert(theHTML.children[i].tagName);
}
}
</SCRIPT>
</HEAD>
<BODY onload=showme()>
<DIV></DIV>
</BODY>
</HTML>
C.例子三:如何獲得頁面內某個元素的內容和改變它的某些屬性?
<html>
<head>
<title>Untitled Document</title>
<script language="JavaScript">
function getTags(){
var get_tables = document.all.tags("TABLE");
for (i=0; i<get_tables.length; i++)
alert('第'+(i+1)+'個TABLE元素內的內容為:\n'+get_tables(i).innerHTML
+'\n'+'當你按下確定后這個TABLE的屬性之一[BORDER]的值將變為1');
get_tables(i-1).border = 1;
}
</script>
</head>
<body onLoad=getTags()>
<table width="200" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<a href=">
</tr>
</table>
</body>
</html>
D.例子四:用另一種方法來改變元素的屬性的值
<HTML>
<HEAD><TITLE>改改改!</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function showAndSetAlignment() {
alert(MyHeading.getAttribute("align"));
MyHeading.setAttribute("align","center");
}
</SCRIPT>
</HEAD>
<BODY onload="showAndSetAlignment()">
<H1 ID=MyHeading ALIGN="left">歡迎光臨</H1>
<P>HTTP://WWW.FLASHABC.COM
</BODY>
</HTML>
E.例子五:顯示出頁中的元素結構
<HTML>
<HEAD><TITLE>Elements: Hierarchy</TITLE>
<SCRIPT LANGUAGE="JScript">
function showHierarchy() {
var depth = 0;
var msg = document.all(0).tagName;
for (i=1; i<document.all.length; i++) {
if (document.all(i-1).contains(document.all(i))==true) {
depth = depth + 1;
} else {
var elParent = document.all(i-1).parentElement;
for ( ; depth>0; depth--) {
if (elParent.contains(document.all(i))==true)
break;
elParent = elParent.parentElement;
}
}
msg = msg + "\n";
for (j=1; j<=depth; j++)
msg = msg + " ";
msg = msg + document.all(i).tagName;
}
alert("這個頁面中包含的元素為\n" + msg);
}
</SCRIPT>
</HEAD>
<BODY onload="showHierarchy()">
<H1>歡迎光臨</H1>
<P>你看到預想的<B>結果</B> 了嗎.
</BODY>
</HTML>
還有幾個小例子,你自己看看就會明白是做什么用途啦
var coll = document.all.tags("H1");
if (coll.length>0)
coll(0).align="center";
var coll = document.all.tags("IMG");
if (coll.length>0)
coll(0).src="newimage.gif";
var coll = document.all.tags("H1");
for (i=0; i<coll.length; i++)
coll[i].style.color = "green";
下一篇:用showModalDialog來打開頁面 作者:時の卵
?
?
1.Hashtable是Dictionary的子類,HashMap是Map接口的一個實現類;
2.Hashtable中的方法是同步的,而HashMap中的方法在缺省情況下是非同步的。即是說,在多線程應用程序中,不用專門的操作就安全地可以使用Hashtable了;而對于HashMap,則需要額外的同步機制。但HashMap的同步問題可通過Collections的一個靜態方法得到解決:
Map?Collections.synchronizedMap(Map?m)
這個方法返回一個同步的Map,這個Map封裝了底層的HashMap的所有方法,使得底層的HashMap即使是在多線程的環境中也是安全的。
3.在HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,即可以表示HashMap中沒有該鍵,也可以表示該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵,而應該用containsKey()方法來判斷。
《最后期限》-項目管理重要原則
優質管理的四大要素:
??? 選擇正確的人。
??? 為他們分配正確的工作。
??? 保持他們的積極性。
??? 幫助團隊凝聚起來并保持團隊的凝聚力。
??? (其他一切都只是"文案"。)
安全和變化
??? 除非感到安全,否則人們就不能去迎接變化。
??? 在所有成功的工程中(以及在絕大多數其他有價值的工作中),變化都是基本的要素之一。
??? 安全感的缺乏會讓人們反對變化。
??? 逃避風險是致命的,因為這會讓你也得不到與風險同在的利益。
??? 人們可能會因為來自客觀世界的直接的恐嚇而覺得沒有安全感,但是如果察覺到管理者可能濫用權力來懲罰自己,他們也會覺得沒有安全感。
負面效應
??? 威脅不是提高業績最好的方法。
??? 如果分配的時間一開始就不夠,不管威脅有多么嚇人,工作也無法按時完成。
??? 更糟糕的是,如果目標沒有實現,你就必須兌現你的威脅。
管理者必需的身體部位
??? 管理涉及到心、腸胃、靈魂和鼻子。
??? 因此……用心來領導,相信你的腸胃(相信你的預感),構筑團隊的靈魂,訓練一個能嗅出謊言的鼻子。
用指揮戰爭來作為管理的一個比喻
??? 在戰役開始的時候,管理者真正的工作已經完成了。
面試和招聘
??? 招聘涉及到所有與管理相關的身體部位:心、靈魂、鼻子和腸胃(但是主要是腸胃)。
??? 不要試圖單獨去招聘——兩副腸胃遠比一副腸胃的兩倍要好。
??? 對于新的雇員,讓他們承擔與以前曾經成功過的同樣難度的項目,把有挑戰性的目標推遲到下一次。
??? 征求提示:你最希望雇的那個人可能還知道其他很好的人選。
??? 多聽,少說。
??? 如果先把材料整理好,那么所有的事情都會進行得更好。
生產力的提高
??? 沒有"短期生產力提高"這樣的東西。
??? 生產力的提高是來自長期投資的。
??? 任何承諾立刻見效的東西都很可能是江湖游醫所賣的萬靈油。
風險控制
??? 通過控制風險來管理項目。
??? 為每個項目創建并維護風險統計表。
??? 跟蹤根源性的風險,而不只是最后那討厭的結果。
??? 評估每種風險具體化的概率和可能造成的開銷。
??? 對于每種風險,預測標志其具體化的早期征兆。
??? 任命一個風險控制官,這個人不應該維護組織內部"我能行"的態度。
??? 建立簡單的(可能是匿名的)通道,讓壞消息能傳遞到高層。
防止失敗
??? 壯士斷腕。
??? 控制住失敗比優化成功更能提高你全面的成績。
??? 要有闖勁,盡早取消失敗的工作。
??? 除非必要,否則就不要自己去凝聚一個團隊:出去找一個已經成型的團隊來用。
??? 保持好的團隊在一起(只要他們自己愿意),以幫助你的繼任者避免團隊凝聚得慢或者不能凝聚的問題。
??? 把凝聚在一起的團隊--準備好、并且也愿意接受新的工作--作為項目的收獲之一。
??? 項目開始時浪費的一天和最后階段浪費的一天對項目造成的傷害是同等的。
??? 有無數種方法可以浪費一天的時間……但是沒有任何一種方法可以拿回一天的時間。
開發過程的建模和模擬
??? 將你關于完成工作過程的直覺建模。
??? 在同事的交流中使用這些模型,以便交流、提煉關于項目運轉的思想。
??? 用模型來模擬項目的結果。
??? 根據實際的結果來調整模型。
"病態的政治"
??? 每一天,你都必須準確度拿自已的工作去打賭......
??? ......但是這也不能保證"病態的政治"不會影響你。
??? "病態的政治"可能在任何地方出現,哪怕是在最健康的組織里面。
??? "病態的政治"的特征:對個人權勢的渴望超過了組織本身的目標。
??? 即使這種不合理的目標與組織的目標背道而馳,它也可能出現。
??? "病態的政治"的副作用:它使精簡的項目變得危險。
度量
??? 度量每個產品的規模。
??? 不要執著于單位——在等待客觀度量的時候,先用你自己的主觀單位。
??? 從所有能得到的原始數據(可計算的軟件特征)自己構造度量單位。
??? 不斷完善你的度量方程式,直到它的計算結果與原始數據庫中的項目工作量有最好的對應關系。
??? 借助數據庫畫一條趨勢線,把預期的工作量作為人造度量單位值的函數顯示出來。
??? 現在,針對每個要度量的項目,計算出人造度量單位值,并根據這個值在趨勢線上找到預期工作量值。
??? 用生產力趨勢周圍的干擾水平作為映射的公差指示。
過程和過程改進
??? 好的過程和持續的過程是絕好的目標。
??? 它們也是非常自然的目標:優秀的技術工作者一定會關注它們,而不管你是否告訴他們。
??? 正式的過程改進程序需要花錢、花時間;特定的過程改進工作還會延緩項目進度。盡管最終體現出生產力上的收獲,它們也不可能抵消花在過程改進上的時間。
??? 但是項目有希望從單個的、正確選擇的方法改進中得到足夠的收益,并贏回為這次改變付出的時間和金錢。
??? 在項目進行過程中,不要希望在超過一個地方的范圍內實施必改進。多種技術的改進程序(比如說提高整整一個CMM等級)很可能讓項目比不實施這些程序完成得更晚。
??? 標準過程的危險就在于人們可能失去重要的走捷徑的機會。
??? 特別是對于人員超編的項目,標準的過程看去會很嚴謹,因為它們制造出了足夠的工作(有用的和無用的),讓所有人都忙于不停。
改變完成工作的方式
??? 如果不大幅減少調試時間,就沒有辦法讓項目大幅度提前完成。
??? 高速完成的項目用在調試上的時間成比例地少得多。
??? 高速完成的項目用在設計上的時間也成比例地多得多。
??? 如果你不關心別人, 不照顧別人,就別想讓他們做一些不同尋常的事情。如果要讓他們改變,就必須去了解(并贊賞)他們的過去。
壓力的效果
??? 壓力之下的人無法更快的思考。
??? 增加加班時間只會降低生產力。
??? 短期的壓力乃至于加班可能是有用的策略,因為它們能使員工集中精力,并且讓他們感到工作的重要性。但是長期的壓力肯定是錯誤的。
??? 經理們之所以會施加那么多壓力,也許是因為他們不知道該做什么,或者因為其他辦法的困難而感到氣餒。
??? 最壞的猜想:使用壓力和加班的真正原因是為了在項目失敗的時候讓所有人看上去能好一點。
???
憤怒的經理
??? 管理中的憤怒和羞辱是會傳染的。如果高級管理者喜歡罵人,低級管理者也會有樣學樣(就象經常被罵的小孩很容易變成愛罵人的父母)。
??? 管理中的辱罵常被認為是一種刺激,可以讓員工提高效率。在" 胡蘿卜加大棒"的管理策略中,辱罵是最常見的"大棒"。但是,哪有人被辱罵之后還能做得更好的?
??? 如果經理使用辱罵的方法來刺激員工,這就表現經理的無能,而不是員工的無能。
含糊的規格文檔
??? 規格文檔中的含糊標志著不同的系統參與者之間存在未解決的沖突。
??? 如果一份規格文檔不包含完整的輸入輸出列表,那么它就是毫無希望的:它根本就沒有開始說明任何東西。
??? 沒有人會告訴你一份規格文檔是不是糟糕。人們往往傾向于責備自己,而不責備文檔。
沖突
??? 只要在開發過程中有多個參與者,就一定會有沖突存在。
??? 創建、安裝系統的業務中特別容易出現沖突。
??? 絕大多數系統開發團隊都缺乏解決沖突的能力。
??? 沖突應當引起重視。沖突并不是缺乏職業道德的行為。
??? 應當提前聲明:所有人的"贏"都是受重視的。確保每個級別的人都能贏。
??? 談判困難,調解容易。
??? 如果兩個人的利益是完全或者部分相斥的,預先做好安排,準備好請雙方通過調解來解決沖突。
??? 記住:我們都站在同一邊;跟我們對立的,是我們要解決的問題。
???
催化劑的角色
??? 有這樣一種催化劑式的人格。這樣的人會幫助團隊成型并凝聚,保持團隊的健康和生產力,從而對項目作出貢獻。就算"催化劑"別的什么都不干(其實,通常他們還會干很多別的事),這種催化劑的角色也是重要而有價值的。
??? 調解是"催化劑"的一項特殊工作。調解是可以學的,而且只需要很小的投資就能學會。
??? 調解應該從一個小小的儀式開始。"我能幫你們調解一下嗎?"在解決沖突的時候,這是必要的第一個步驟。
人類的錯誤
??? 將你置于死的,不是你不知道的東西……而正是你"知道"絕不會置你于死地的東西。
人員安排
??? 在早期,人員超編會迫使項目跨過關鍵的設計階段(這是為了讓所有的人都有事可做)。
??? 如果在設計完成之前, 工作先被分給了許多人,那么人與人之間、工作與工作之間的接口就會很復雜。
??? 這會使團隊內部耦合度提高,會議時間、重復勞動和無效的工作都會增加。
??? 理想的人員安排是這樣的:在項目的大部分時間內由小型核心團隊來做設計工作,在開發的最后階段(時間安排的最后1/6)加入大量的人手。
??? 可怕的猜想:時間安排緊迫的項目,與時間安排比較合理的項目比起來,完成的時間反而會更長。
項目社會學
??? 讓不必與會的人可以放心離開,從而保持會議的精簡。有一份公開的議程,并嚴格執行,這是最簡單的辦法。
??? 項目需要儀式。
??? 用小小的儀式來使人們注意項目的目標的理想狀態:小規模會議、零缺陷工作等等。
??? 采取行動,防止人們隨便發怒。
??? 記住:憤怒=恐懼。隨便對下級發怒的經理一定是因為恐懼才會這樣做的。
??? 意見:如果所有人都懂得"憤怒=恐懼"這個道理,就能明顯看出發怒的人是在害怕。由于無法隱瞞自己的恐懼,他也就不會再生氣了。(這不能解決這些生氣的人的問題,但是肯定可以讓其他人好受一些。)
???
"病態的政治"(舊話重提)
??? 別想根治一個病態的人。
??? 不要浪費時間,也不要因為嘗試治療上司的病態而使自己受到威脅。
??? 有時候,你唯一的的選擇就是等待,等問題自己解決,或者等一個讓你繼續前進的機會。
??? 奇跡是有可能發生的(但是千萬別去指望它)。
精兵簡政
??? 精兵簡政是失敗公司使用的辦法,它使員工負但失敗的責任。
??? 公司的目標應該正好相反:興旺而人性化。
??? 當你聽到"精兵簡政"這個詞的時候,請記住它的弦外之音:失敗和恐嚇。
基本常識
??? 項目既需要目標,也需要計劃。
??? 而且這兩者應該不同。
?? 在jsp規范里,標簽具有比javabean更豐富的運行時協議。它可以非常機密的和jsp的表示邏輯聯系在一起,同時,又具有javabean相同業務處理能力。所以,標簽的學習成為迫切的需要,但為了滿足實際項目的開發,自定義標簽的學習是不容錯過的。
?? 通過實現接口或者繼承現有的類,我們就可以開發自定義的標簽。
?? 常用的接口有:?????????????JspTag
???????????????????????Tag?????? SimpleTag<----SimpleTagSupport
???????????????IterationTag?<----TagSupport???????????
????????????????????BodyTag<----BodyTagSupport
?? 自定義標簽的開發包括兩個部分的開發:
(1)、開發標簽的處理程序(java類)
(2)、標簽描述文件(.tld文件)
?? 自定義標簽的種類有許多,可以根據實際項目的需要進行編寫。但為了不重復的開發輪子,jsp標準推出JSTL(標準標簽庫)。
?? 開始我們的旅行吧,只要是快樂的,誰都想干,做的好與不好就另當別論了。
(1)從Hello World開始吧,自定義一個類它實現Tag接口,Tag接口主要定義的是標簽聲明周期的方法,比如:doStartTag(),doEndTag()等,通過PageContext對象來訪問Jsp頁面的上下文:
package com.xmddl.tag.demo;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
public class HelloTag implements Tag {
?private PageContext context;
?private Tag parent;
?public void setPageContext(PageContext ctx) {
??this.context=ctx;
?}
?public void setParent(Tag tag) {
??this.parent=tag;
?}
?public Tag getParent() {
??return this.parent;
?}
?public int doStartTag() throws JspException {
??System.out.println("doStartTag");
??return Tag.SKIP_BODY;
?}
?public int doEndTag() throws JspException {
??System.out.println("doStartTag");
??try {
???this.context.getOut().write("Hello World");
??} catch (Exception e) {
???e.printStackTrace();
??}
??return Tag.EVAL_PAGE;
?}
?public void release() {
??// TODO Auto-generated method stub
?}
}
?Tag接口中靜態常量:
Tag.SKIP_BODY
Tag.EVAL_PAGE
Tag.EVAL_BODY_INCLUDE
Tag.SKIP_PAGE
(2)編寫標簽描述文件(.tld):
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="
http://java.sun.com/xml/ns/j2ee
"
??? xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance
"
??? xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd
"
??? version="2.0">
? <description>xmddl 1.1 hello library</description>
? <display-name>xmddl hello</display-name>
? <tlib-version>1.1</tlib-version>
? <short-name>hello</short-name>
? <uri>http://www.xmddl.com/tag</uri>
?
?
<tag>
??? <description>我的Hello World</description>
??? <name>hello</name>
??? <tag-class>com.xmddl.tag.demo.HelloTag</tag-class>
??? <body-content>empty</body-content>
? </tag>
</taglib>
(3)、在web.xml中對標簽的引用:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "
http://java.sun.com/dtd/web-app_2_3.dtd
">
<web-app>
?<taglib>
??
<taglib-uri>http://www.xmddl.com/tag</taglib-uri>
??<taglib-location>/WEB-INF/mytag.tld</taglib-location>
?</taglib>
</web-app>
(4)、編寫測試頁面:
<%@ page language="java" pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib uri="http://www.xmddl.com/tag" prefix="lu"%>
<html>
? <head>
??? <title>MyJsp.jsp</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>
??? <h1>This is a test tag page for person.</h1> <br>
??
<lu:hello/>
? </body>
</html>
下面看看標簽中的屬性是如何使用的,我們直接繼承TagSupport類來編寫:
?package com.xmddl.tag.demo;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
public class HelloSupport extends TagSupport {
?private String value;
?private static final long serialVersionUID = 1L;
?public HelloSupport(){
??super();
?}
?public int doStartTag() throws JspException {
??System.out.println("doStartTag");
??return TagSupport.EVAL_BODY_INCLUDE;
?}
?public int doEndTag() throws JspException {
??System.out.println("doEndTag");
??try {
???this.pageContext.getOut().write("標簽的屬性值:"+this.value);
??} catch (Exception e) {
???e.printStackTrace();
??}
??return Tag.EVAL_PAGE;
?}
?public int doAfterBody() throws JspException{
??System.out.println("doAfterBody");
??try {
???this.pageContext.getOut().write("<br>以上為標簽的內容<br>");
??} catch (Exception e) {
???e.printStackTrace();
??}
??return TagSupport.EVAL_BODY_INCLUDE;
??
?}
?public String getValue() {
??return value;
?}
?public void setValue(String value) {
??this.value = value;
?}
}
======================
...
<tag>
??? <name>hellosupport</name>
??? <tag-class>com.xmddl.tag.demo.HelloSupport</tag-class>
??? <body-content>JSP</body-content>
??? <attribute>
??????? <name>value</name>
??????? <required>true</required>
??????? <rtexprvalue>false</rtexprvalue>
??? </attribute>
? </tag>
...
=======================
<%@ page language="java" pageEncoding="gb2312" import="java.util.*"%>
<%@ taglib prefix="lu" uri="
http://www.xmddl.com/tag
" %>
<html>
? <head>
? </head>
? <body>
??? <h1>This is a test tag page for person.</h1> <br>
??<lu:hellosupport value="red">xmddl</lu:hellosupport>
? </body>
</html>
?利用TagSupport帶來很大的方便,只要重寫其中的部分方法即可實現一個標簽處理程序,以上開發的標簽程序和JSTL1.1標簽庫一起使用時出現一些疑問,原來標簽的uri=" http://java.sun.com/jsp/jstl/core ",但是,在如下的測試中會發現c:out中的值輸不出來,所以,只能改為uri=" http://java.sun.com/jstl/core ",
<%@ page language="java" pageEncoding="gb2312" import="java.util.*"%>
<%@ taglib prefix="lu" uri="
http://www.xmddl.com/tag
" %>
<%@ taglib prefix="c" uri="
http://java.sun.com/jstl/core
" %>
<html>
? <head>
? </head>
? <body>
??? <h1>This is a test tag page for person.</h1> <br>
??? <%request.setAttribute("name","xmddl"); %>
??? <%session.setAttribute("names","xmddls"); %>
???
??<lu:hellosupport value="red">xmddl</lu:hellosupport><hr>
??<c:forEach begin="1" end="5" step="1">
???name=<c:out value="${name}"></c:out>
???names=<c:out value="${names}"></c:out><br>
??</c:forEach>
? </body>
</html>
輸出如下:
This is a test tag page for person.
xmddl
以上為標簽的內容
標簽的屬性值:red
name=xmddl names=xmddls
name=xmddl names=xmddls
name=xmddl names=xmddls
name=xmddl names=xmddls
name=xmddl names=xmddls
接著看看迭代標簽的開發,首先,我們關注的是接口IterationTag,還有它的實現類TagSupport,接口BodyTag對IterationTag的擴展,還有BodyTag的實現類BodyTagSupport。
package com.xmddl.tag.demo;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class MyIteratorSupport extends BodyTagSupport {
?private static final long serialVersionUID = 1L;
?public String count;
?public String strColor;
?private int cou;
?
?public void setCount(String count) {
??this.count = count;
??cou=Integer.parseInt(count);
?}
?
?public int doAfterBody() throws JspException {
??try {
???this.pageContext.getOut().write("<br>");
??} catch (IOException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??if(cou>1){
???cou--;
???return MyIteratorTag.EVAL_BODY_AGAIN;
??}else{
???return MyIteratorTag.SKIP_BODY;
??}
?}
?public int doStartTag() throws JspException {
??try {
???this.pageContext.getOut().write("<font color='"+this.strColor+"'>");
??} catch (IOException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??return MyIteratorTag.EVAL_BODY_INCLUDE;
?}
?public int doEndTag() throws JspException {
??try {
???this.pageContext.getOut().write("</font>");
??} catch (IOException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??return MyIteratorTag.EVAL_PAGE;
?}
?public int getCou() {
??return cou;
?}
?public void setCou(int cou) {
??this.cou = cou;
?}
?public String getCount() {
??return count;
?}
?public String getStrColor() {
??return strColor;
?}
?public void setStrColor(String strColor) {
??this.strColor = strColor;
?}
}
==============
。。。
<tag>
?? ?<description>對顏色的設置</description>
??? <name>myColor</name>
??? <tag-class>com.xmddl.tag.demo.MyIteratorSupport</tag-class>
??? <body-content>JSP</body-content>
??? <attribute>
??????? <name>count</name>
??????? <required>true</required>
??? </attribute>
??? <attribute>
??????? <name>strColor</name>
??????? <required>false</required>
??? </attribute>
?? </tag>
。。。
==============
<%@ page language="java" pageEncoding="gb2312" import="java.util.*"%>
<%@ taglib prefix="lu" uri="<html>
? <head>
? </head>
? <body>
??? <h1>This is a test tag page for person.</h1> <br>
??? <lu:myColor count="3" strColor="blue">xmddl</lu:myColor>
? </body>
</html>
輸出如下
This is a test tag page for person.
xmddl
xmddl
xmddl
<html locale="true">
<head>
<title><bean:message key="hrUsers.maint" /></title>
<script language="javascript">
var textId;
var text;
function calendarDefalut(name) //定義dateSelector的display方法,它將實現一個日歷形式的日期選擇框。
{
var myDate=new Date();
this.year=myDate.getFullYear(); //定義year屬性,年份,默認值為當前系統年份。
this.month=myDate.getMonth()+1; //定義month屬性,月份,默認值為當前系統月份。
calendar('default',name,this.year+'/'+this.month);
}
function calendar(id,name,value) //定義dateSelector的display方法,它將實現一個日歷形式的日期選擇框。
{
textId = id;
document.write("<style type=text/css>");
document.write(" .ds_font td,span { font: normal 12px 宋體; color: #000000; }");
document.write(" .ds_border { border: 1px solid #000000; cursor: hand; background-color: #F7F7F7 }");
document.write(" .ds_border2 { border: 1px solid #000000; cursor: hand; background-color: #F7F7F7 }");
document.write("</style>");
document.write(" <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subYear() title='減小年份'><< </span>");
document.write(" <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subMonth() title='減小月份'><</span>");
document.write(" <span width=52%><input id='"+id+"' type='text' name='"+name+"' value="+value+" readonly='readonly' size='3' style='border-style: solid; border-color: #FFFFFF;border: 0px solid #000000; background-color: #F7F7F7'></span>");
document.write(" <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addMonth() title='增加月份'>> </span>");
document.write(" <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addYear() title='增加年份'>>></span>");
text= document.getElementById(textId);
}
function subYear() //減小年份
{
var value = text.value;
text.value = (eval(value.substr(0,4))-1)+'/'+value.substr(5,2);
}
function addYear() //增加年份
{
var value = text.value;
text.value = (eval(value.substr(0,4))+1)+'/'+value.substr(5,2);
}
function subMonth() //減小月份
{
var value = text.value;
var month=eval(value.substr(5,2))-1;
var year = value.substr(0,4)
if(month==0)
{
month=12;
year = eval(year)-1;
}
text.value = year+'/'+month;
}
function addMonth() //增加月份
{
var value = text.value;
var month=eval(value.substr(5,2))+1;
var year = value.substr(0,4)
if(month==13)
{
month=1;
year = eval(year)+1;
}
text.value = eval(year)+'/'+month;
}
</script>
</HEAD>
ssss:<script language=javascript>calendarDefalut('hrUsers.userNo');</script>
</html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>New Page 1</title>
<script language=javascript>
var DS_x,DS_y;
function dateSelector() //構造dateSelector對象,用來實現一個日歷形式的日期輸入框。
{
var myDate=new Date();
this.year=myDate.getFullYear(); //定義year屬性,年份,默認值為當前系統年份。
this.month=myDate.getMonth()+1; //定義month屬性,月份,默認值為當前系統月份。
this.date=myDate.getDate(); //定義date屬性,日,默認值為當前系統的日。
this.inputName=''; //定義inputName屬性,即輸入框的name,默認值為空。注意:在同一頁中出現多個日期輸入框,不能有重復的name!
this.display=display; //定義display方法,用來顯示日期輸入框。
}
function display() //定義dateSelector的display方法,它將實現一個日歷形式的日期選擇框。
{
var week=new Array('日','一','二','三','四','五','六');
document.write("<style type=text/css>");
document.write(" .ds_font td,span { font: normal 12px 宋體; color: #000000; }");
document.write(" .ds_border { border: 1px solid #000000; cursor: hand; background-color: #DDDDDD }");
document.write(" .ds_border2 { border: 1px solid #000000; cursor: hand; background-color: #DDDDDD }");
document.write("</style>");
var M=new String(this.month);
var d=new String(this.date);
if(M.length==1&&d.length==1){
document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-0"+this.month+"-0"+this.date+"' title=雙擊可進行編緝 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
else if(M.length==1&&d.length==2){
document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-0"+this.month+"-"+this.date+"' title=雙擊可進行編緝 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
else if(M.length==2&&d.length==1){
document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-"+this.month+"-0"+this.date+"' title=雙擊可進行編緝 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
else if(M.length==2&&d.length==2){
document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-"+this.month+"-"+this.date+"' title=雙擊可進行編緝 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
document.write("<button style='width:60px;height:18px;font-size:12px;margin:1px;border:1px solid #A4B3C8;background-color:#DFE7EF;' type=button onclick=this.nextSibling.style.display='block' onfocus=this.blur()>選擇日期</button>");
document.write("<div style='position:absolute;display:none;text-align:center;width:0px;height:0px;overflow:visible' onselectstart='return false;'>");
document.write(" <div style='position:absolute;left:-60px;top:20px;width:142px;height:165px;background-color:#F6F6F6;border:1px solid #245B7D;' class=ds_font>");
document.write(" <table cellpadding=0 cellspacing=1 width=140 height=20 bgcolor=#CEDAE7 onmousedown='DS_x=event.x-parentNode.style.pixelLeft;DS_y=event.y-parentNode.style.pixelTop;setCapture();' onmouseup='releaseCapture();' onmousemove='dsMove(this.parentNode)' style='cursor:move;'>");
document.write(" <tr align=center>");
document.write(" <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subYear(this) title='減小年份'><<</td>");
document.write(" <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subMonth(this) title='減小月份'><</td>");
document.write(" <td width=52%><b>"+this.year+"</b><b>年</b><b>"+this.month+"</b><b>月</b></td>");
document.write(" <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addMonth(this) title='增加月份'>></td>");
document.write(" <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addYear(this) title='增加年份'>>></td>");
document.write(" </tr>");
document.write(" </table>");
document.write(" <table cellpadding=0 cellspacing=0 width=140 height=20 onmousedown='DS_x=event.x-parentNode.style.pixelLeft;DS_y=event.y-parentNode.style.pixelTop;setCapture();' onmouseup='releaseCapture();' onmousemove='dsMove(this.parentNode)' style='cursor:move;'>");
document.write(" <tr align=center>");
for(i=0;i<7;i++)
document.write(" <td>"+week[i]+"</td>");
document.write(" </tr>");
document.write(" </table>");
document.write(" <table cellpadding=0 cellspacing=2 width=140 bgcolor=#EEEEEE>");
for(i=0;i<6;i++)
{
document.write(" <tr align=center>");
for(j=0;j<7;j++)
document.write(" <td width=10% height=16 onmouseover=if(this.innerText!=''&&this.className!='ds_border2')this.className='ds_border' onmouseout=if(this.className!='ds_border2')this.className='' onclick=getValue(this,document.all('DS_"+this.inputName+"'))></td>");
document.write(" </tr>");
}
document.write(" </table>");
document.write(" <span style=cursor:hand onclick=this.parentNode.parentNode.style.display='none'>【關閉】</span>");
document.write(" </div>");
document.write("</div>");
dateShow(document.all("DS_"+this.inputName).nextSibling.nextSibling.childNodes[0].childNodes[2],this.year,this.month)
}
function subYear(obj) //減小年份
{
var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
myObj[0].innerHTML=eval(myObj[0].innerHTML)-1;
dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}
function addYear(obj) //增加年份
{
var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
myObj[0].innerHTML=eval(myObj[0].innerHTML)+1;
dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}
function subMonth(obj) //減小月份
{
var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
var month=eval(myObj[2].innerHTML)-1;
if(month==0)
{
month=12;
subYear(obj);
}
myObj[2].innerHTML=month;
dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}
function addMonth(obj) //增加月份
{
var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
var month=eval(myObj[2].innerHTML)+1;
if(month==13)
{
month=1;
addYear(obj);
}
myObj[2].innerHTML=month;
dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}
function dateShow(obj,year,month) //顯示各月份的日
{
var myDate=new Date(year,month-1,1);
var today=new Date();
var day=myDate.getDay();
var selectDate=obj.parentNode.parentNode.previousSibling.previousSibling.value.split('-');
var length;
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
length=31;
break;
case 4:
case 6:
case 9:
case 11:
length=30;
break;
case 2:
if((year%4==0)&&(year%100!=0)||(year%400==0))
length=29;
else
length=28;
}
for(i=0;i<obj.cells.length;i++)
{
obj.cells[i].innerHTML='';
obj.cells[i].style.color='';
obj.cells[i].className='';
}
for(i=0;i<length;i++)
{
obj.cells[i+day].innerHTML=(i+1);
if(year==today.getFullYear()&&(month-1)==today.getMonth()&&(i+1)==today.getDate())
obj.cells[i+day].style.color='red';
if(year==eval(selectDate[0])&&month==eval(selectDate[1])&&(i+1)==eval(selectDate[2]))
obj.cells[i+day].className='ds_border2';
}
}
function getValue(obj,inputObj) //把選擇的日期傳給輸入框
{
var myObj=inputObj.nextSibling.nextSibling.childNodes[0].childNodes[0].cells[2].childNodes;
if(obj.innerHTML)
if(obj.innerHTML.length==1&&myObj[2].innerHTML.length==1)
inputObj.value=myObj[0].innerHTML+"-0"+myObj[2].innerHTML+"-0"+obj.innerHTML;
else if(obj.innerHTML.length==1&&myObj[2].innerHTML.length==2)
inputObj.value=myObj[0].innerHTML+"-"+myObj[2].innerHTML+"-0"+obj.innerHTML;
else if(obj.innerHTML.length==2&&myObj[2].innerHTML.length==1)
inputObj.value=myObj[0].innerHTML+"-0"+myObj[2].innerHTML+"-"+obj.innerHTML;
else if(obj.innerHTML.length==2&&myObj[2].innerHTML.length==2)
inputObj.value=myObj[0].innerHTML+"-"+myObj[2].innerHTML+"-"+obj.innerHTML;
inputObj.nextSibling.nextSibling.style.display='none';
for(i=0;i<obj.parentNode.parentNode.parentNode.cells.length;i++)
obj.parentNode.parentNode.parentNode.cells[i].className='';
obj.className='ds_border2'
}
function dsMove(obj) //實現層的拖移
{
if(event.button==1)
{
var X=obj.clientLeft;
var Y=obj.clientTop;
obj.style.pixelLeft=X+(event.x-DS_x);
obj.style.pixelTop=Y+(event.y-DS_y);
}
}
</script>
</head>
<body>
從
<script language=javascript>
var myDate=new dateSelector();
myDate.year--;
myDate.inputName='start_date'; //注意這里設置輸入框的name,同一頁中日期輸入框,不能出現重復的name。
myDate.display();
</script>
到
<script language=javascript>
myDate.year++;
myDate.inputName='end_date'; //注意這里設置輸入框的name,同一頁中的日期輸入框,不能出現重復的name。
myDate.display();
</script>
</body>
</html>
1.錯誤和信息的處理.
首先在資源文件中定義錯誤信息和普通信息.如:MessageResources.properties中定義如下:
java代碼: |
# # Resources for testing <html:errors> tag. # errors.header=<table> errors.footer=</table> errors.prefix=<tr><td> errors.suffix=</td></tr> property1error1=Property 1, Error 1 property2error1=Property 2, Error 1 property2error2=Property 2, Error 2 property2error3=Property 2, Error 3 property3error1=Property 3, Error 1 property3error2=Property 3, Error 2 globalError=Global Error # # Resources for testing <html:messages> tag. # messages.header=<table> messages.footer=</table> property1message1=Property 1, Message 1 property2message1=Property 2, Message 1 property2message2=Property 2, Message 2 property2message3=Property 2, Message 3 property3message1=Property 3, Message 1 property3message2=Property 3, Message 2 globalMessage=Global Message |
在程序中定義錯誤和信息類,這個例子寫在JSP中
java代碼: |
<% ActionErrors errors = new ActionErrors(); errors.add("property1", new ActionError("property1error1")); errors.add("property2", new ActionError("property2error1")); errors.add("property2", new ActionError("property2error2")); errors.add("property2", new ActionError("property2error3")); errors.add("property3", new ActionError("property3error1")); errors.add("property3", new ActionError("property3error2")); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("globalError")); request.setAttribute(Globals.ERROR_KEY, errors); ActionMessages messages = new ActionMessages(); messages.add("property1", new ActionMessage("property1message1")); messages.add("property2", new ActionMessage("property2message1")); messages.add("property2", new ActionMessage("property2message2")); messages.add("property2", new ActionMessage("property2message3")); messages.add("property3", new ActionMessage("property3message1")); messages.add("property3", new ActionMessage("property3message2")); messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("globalMessage")); request.setAttribute(Globals.MESSAGE_KEY, messages); %> |
顯示錯誤:
java代碼: |
<html:errors property="property1" /> <html:errors property="property2" /> |
顯示信息:
java代碼: |
<html:messages property="property1" message="true" id="msg" header="messages.header" footer="messages.footer"> <tr> <td> <%= pageContext.getAttribute("msg") %> </td> </tr> </html:messages> <html:messages message="true" id="msg" header="messages.header" footer="messages.footer"> <tr> <td> <%= pageContext.getAttribute("msg") %> </td> </tr> </html:messages> |
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection接口
Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的“子接口”如List和Set。
所有實現Collection接口的類都必須提供兩個標準的構造函數:無參數的構造函數用于創建一個空的Collection,有一個Collection參數的構造函數用于創建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。后一個構造函數允許用戶復制一個Collection。
如何遍歷Collection中的每一個元素?不論Collection的實際類型如何,它都支持一個iterator()的方法,該方法返回一個迭代子,使用該迭代子即可逐一訪問Collection中每一個元素。典型的用法如下:
Iterator it = collection.iterator(); // 獲得一個迭代子
while(it.hasNext()) {
Object obj = it.next(); // 得到下一個元素
}
由Collection接口派生的兩個接口是List和Set。
List接口
List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似于數組下標)來訪問List中的元素,這類似于Java的數組。
和下面要提到的Set不同,List允許有相同的元素。
除了具有Collection接口必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator接口,和標準的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向后遍歷。
實現List接口的常用類有LinkedList,ArrayList,Vector和Stack。
LinkedList類
LinkedList實現了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。
注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。
每個ArrayList實例都有一個容量(Capacity),即用于存儲元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長算法并沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。
Vector類
Vector非常類似ArrayList,但是Vector是同步的。由Vector創建的Iterator,雖然和ArrayList創建的Iterator是同一接口,但是,因為Vector是同步的,當一個Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出ConcurrentModificationException,因此必須捕獲該異常。
Stack 類
Stack繼承自Vector,實現一個后進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建后是空棧。
Set接口
Set是一種不包含重復的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重復的元素。
請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。
Map接口
請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
Hashtable類
Hashtable繼承Map接口,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是”one”,”two”,”three”:
Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(“two”);
System.out.println(“two = ” + n);
由于作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable類似,不同之處在于HashMap是非同步的,并且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那么該key可以被GC回收。
總結
如果涉及到堆棧,隊列等操作,應該考慮用List,對于需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類,應該使用同步的類。
要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。
盡量返回接口而非實際的類型,如返回List而非ArrayList,這樣如果以后需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。