1. 程式人生 > >說說Java生態圈的那些事兒

說說Java生態圈的那些事兒

tro 學會 登錄 內存 bar 傳遞 成對出現 描述 first

文章目錄:

1.生態圈概述。

2.說說Java,高級Java,Java生態圈的衍生

3. 說說servlet、servlet容器、比較tomcat、jetty、tomcat、jboss;

1. 哪個項目能離開網絡,數據庫,操作系統來運行?所以生態圈的應用技術主要在這些知識點處。

2. Java組件,組件其實就是一個應用程序塊 但是它們不是完整的應用程序,不能單獨運行。就有如一輛汽車,車門是一個組件,車燈也是一個組件。但是光有車燈車門沒有用,它們不能跑上公路在java中這些組件就叫做javabean,有點像微軟以前的com組件,要特別說明的是,由於任何一個java文件編譯以後都是以類的形式存在所以javabean肯定也是一個類,這是毫無疑問的。那麽容器裏裝載的是什麽呢?就是這些組件。而容器之外的程序需要和這些組件交互必須通過容器。舉個例子,IE發送了一個請求給容器,容器通過調用其中的一個組件進行相關處理之後將結果反饋給IE,這種與客戶端軟件交互的組件就叫做servlet。但是組件有很多種,那麽如何區分這些組件呢?有多種管理辦法,比如同是同樣是servlet,有些是通過jsp生成的而有些是開發人員自己寫的,那麽通過jsp生成的servlet集中放在一個地方而開發人員自己寫的則需要在xml裏面配置一些基本的參數同時,不同組件有可能還需要繼承一些特定的父類或者接口,這也是容器管理的需要還有其他的一些組件。那麽容器有很多種,按照他們裝載的組件類型劃分:比如有裝EJB的EJB容器,有裝servlet與jsp還有靜態頁面的web容器等等,這種只含有web容器的應用服務器也被叫做web服務器 。(當表示層的應用軟件通過網絡向appserver發送一個請求的時候 appserver自動找到相應容器中的組件,執行組件中的程序塊,把得到結果返還給客戶 而我們要做的事就是寫組件也就是javabean,然後放到appserver裏面去就可以了 至於怎樣與IE通訊,怎樣截獲網絡上的請求,怎樣控制對象的數量等等 這些繁瑣而無味的工作我們都不管,都由appserver去做吧,把註意力集中在業務邏輯上 )
3. 框架就是一組相互協作的類,對於特定的一類軟件,框架構成了一種可重用的設計。

4. 對於Servlet,我們常常這樣稱呼:Servlet容器。Servlet工作原理:首先簡單解釋一下Servlet接收和響應客戶請求的過程,首先客戶發送一個請求,Servlet是調用service()方法對請求進行響應的,通過源代碼可見,service()方法中對請求的方式進行了匹配,選擇調用doGet,doPost等這些方法,然後再進入對應的方法中調用邏輯層的方法,實現對客戶的響應。在Servlet接口和GenericServlet中是沒有doGet,doPost等等這些方法的,HttpServlet中定義了這些方法,但是都是返回error信息。所以,我們每次定義一個Servlet的時候,都必須實現doGet或doPost等這些方法。每一個自定義的Servlet都必須實現Servlet的接口,Servlet接口中定義了五個方法,其中比較重要的三個方法涉及到Servlet的生命周期,分別是上文提到的init(),service(),destroy()方法。GenericServlet是一個通用的,不特定於任何協議的Servlet,它實現了Servlet接口。而HttpServlet繼承於GenericServlet,因此HttpServlet也實現了Servlet接口。所以我們定義Servlet的時候只需要繼承HttpServlet即可。

技術分享
Servlet生命周期分為三個階段:

  1,初始化階段  調用init()方法

  2,響應客戶請求階段  調用service()方法

  3,終止階段  調用destroy()方法
技術分享 技術分享
Servlet初始化階段:

  在下列時刻Servlet容器裝載Servlet:

    1,Servlet容器啟動時自動裝載某些Servlet,實現它只需要在web.XML文件中的<Servlet></Servlet>之間添加如下代碼: <loadon-startup> 1 </loadon-startup> 

    2,在Servlet容器啟動後,客戶首次向Servlet發送請求

    3,Servlet類文件被更新後,重新裝載Servlet。Servlet被裝載後,Servlet容器創建一個Servlet實例並且調用Servlet的init()方法進行初始化。在Servlet的整個生命周期內,init()方法只被調用一次。
技術分享 技術分享
Servlet響應請求階段:

  對於用戶到達Servlet的請求,Servlet容器會創建特定於這個請求的ServletRequest對象和ServletResponse對象,然後調用Servlet的service方法。service方法從ServletRequest對象獲得客戶請求信息,處理該請求,並通過ServletResponse對象向客戶返回響

應信息。
對於Tomcat來說,它會將傳遞過來的參數放在一個Hashtable中,該Hashtable的定義是:private Hashtable<String String[]> paramHashStringArray = new Hashtable<String String[]>(); 這是一個String-->String[]的鍵值映射。HashMap線程不安全的,Hashtable

線程安全的。
技術分享
Servlet終止階段:

  當WEB應用被終止,或Servlet容器終止運行,或Servlet容器重新裝載Servlet新實例時,Servlet容器會先調用Servlet的destroy()方法,在destroy()方法中可以釋放掉Servlet所占用的資源。
技術分享
Servlet何時被創建:

  1,默認情況下,當WEB客戶第一次請求訪問某個Servlet的時候,WEB容器將創建這個Servlet的實例。

  2,當web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素時,Servlet容器在啟動web服務器時,將按照順序創建並初始化Servlet對象。

  註意:在web.xml文件中,某些Servlet只有<serlvet>元素,沒有<servlet-mapping>元素,這樣我們無法通過url的方式訪問這些Servlet,這種Servlet通常會在<servlet>元素中配置一個<load-on-startup>子元素,讓容器在啟動的時候自動加載這些Servlet並調
用init()方法,完成一些全局性的初始化工作。
技術分享 技術分享
Web應用何時被啟動:

  1,當Servlet容器啟動的時候,所有的Web應用都會被啟動

  2,控制器啟動web應用

Servlet與JSP的比較:

  有許多相似之處,都可以生成動態網頁。

  JSP的優點是擅長於網頁制作,生成動態頁面比較直觀,缺點是不容易跟蹤與排錯。

  Servlet是純Java語言,擅長於處理流程和業務邏輯,缺點是生成動態網頁不直觀。
技術分享

對於文中說到的,Servlet生成動態網頁不直觀。servlet可以用於生成動態的Web頁內容。但是,它的一個缺點是必須將HTML標記和文本嵌入到Java源代碼中。這樣,如果要改變靜態的HTML文本,必須修改Java源代碼並重新進行編譯。同時,在servlet中有許多靜態HTML代碼和一些動態HTML代碼混在一起,由於正常的HTML代碼是Java源代碼的一部分,所以很難閱讀和維護這些代碼。JSP就是為了克服上述缺點而引入的。

技術分享
編輯文件:CurrentTime.jsp如下所示:

技術分享
<html>
<head>
  <title>CurrentTime</title>
</head>
<body>
  CurrentTime is <%= new java.util.Date()%>
</body>
</html>
技術分享
將程序放到tomcat容器下運行。
技術分享

5. 繼續探究Servlet,Servlet本身是單實例的,這樣當多個用戶同時訪問某個Servlet時,會訪問該唯一的Servlet實例中的成員變量,如果對成員變量進行寫入工作,那就會導致Servlet的多線程問題,即數據不一致。

技術分享
解決Servlet多線程同步問題的方案:

  1,Servlet實現了javax.servlet.singleThreadModel(Servlet2.4中已經廢棄該接口),此時的Servlet容器將保證Servlet實例是以單線程的方式運行,也就是說同一時刻,只會有一個線程運行Servlet的service()方法。   不推薦使用,大大降低了效率。

  2,去除實例變量,使用局部變量  推薦

  3,使用同步代碼塊 synchronized{...}  不推薦使用
技術分享

6. Cookie的英文原意是“點心”,當用戶訪問WEB服務器時,服務器在用戶硬盤上存放的信息,好像是服務器送給用戶的點心。服務器可以根據Cookie來跟蹤用戶,這對於需要區別用戶場合特別有用。先來看看我們在HTML5項目中使用過的cookie具體案例:

技術分享
這個是在H5/js/common.js中的兩個函數。
//保存到cookie
function setCookie(name,value,days) 
{ 
    var exp = new Date(); 
    exp.setTime(exp.getTime() + days*24*60*60*1000); 
    document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString(); 
} 
//讀取cookies 
function getCookie(name) 
{ 
    var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
 
    if(arr=document.cookie.match(reg))
 
        return unescape(arr[2]); 
    else 
        return null; 
}
技術分享

兩個函數,分別用來設置cookie和取得cookie。

技術分享

  setTimeout(function() {
    var cookieChid=getCookie(‘chid‘);
    if(cookieChid !=‘w5‘)
    {
      $("#underonlaodFlag").attr("style","display:display");
    }
  },300);

在其他頁面中,通過這段JS,延遲300ms執行,保證先加載了common.js, 再執行這段JS。做出判斷。

var uid=getCookie(‘uid‘)==null?‘‘:getCookie(‘uid‘);  //這個同樣是其他頁面需要使用cookie的案例。
技術分享

繼續來讀代碼

技術分享
public class CookieServlet extends HttpServlet
{
    private int count1;
    private int count2;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        Cookie cookie = new Cookie("cookiename"+ count1++,"cookievalue"+ count2++);
         
        cookie.setMaxAge(10);//設置存活時間  單位秒
         
        resp.addCookie(cookie);
         
         
        Cookie[] cookies = req.getCookies();
         
        if(null == cookies)
        {
            return;
        }
         
        for(Cookie cookie2:cookies)
        {
            System.out.println(cookie2.getName());
            System.out.println(cookie2.getValue());
        }
         
    }
}

//代碼中展現了:Servlet 中創建、存儲和接收客戶端存儲Cookie的過程。
技術分享

7. 客戶端的cookie都有生命周期的,一般為兩周。又或者用戶主動清空了自己的cookie,那麽服務器怎麽來跟蹤用戶記錄呢?Session回話,Session用於跟蹤客戶的狀態,Session是指在一段時間內,單個客戶與WEB服務器一連串相關的交互過程。在一個Session中,客戶可能多次請求訪問同一個網頁,也有可能請求訪問各種不同的服務器資源。

技術分享
Web服務器跟蹤客戶狀態通常有四種方法:

  1,建立含有跟蹤數據的隱藏字段  type=hidden

  2,重寫包含額外參數的URL

  3,使用持續的Cookie

  4,使用Servlet API中的Session(會話)機制
技術分享

技術分享
Session的生命周期:

  當客戶第一次訪問WEB應用中支持Session的某個頁面時,就會開始一個新的session

  接下來客戶訪問這個WEB應用中不同的網頁時,都處於同一個session中

  默認情況下,JSP頁面是支持Session的,如果想不支持Session,可使用標簽<%@ page session="false"%>

  在下列情況下,Session將結束生命周期,Servlet容器將釋放HttpSession占用的資源:

    1,客戶瀏覽器關閉?

    2,Session過期

    3,服務器端調用了HttpSession的Invalidate()方法

  如何做到在瀏覽器關閉時刪除Session?

    嚴格的講,做不到這一點。可以做的努力的辦法是在所有的客戶端頁面裏使用javascript的方法window.onclose來監視瀏覽器的關閉動作,然後向服務器發送一個請求來刪除Session;

    但是對於瀏覽器崩潰或強行殺死進程這種非常規手段仍然無能為力。

    實際上我們在項目中也不會這麽做,而是讓服務器在Session過期時將其刪除。
技術分享

技術分享
Session運行機制:

  當一個Session開始時,Servlet容器將創建一個HttpSession對象,在HttpSession對象中可以存放客戶的狀態信息(例如購物車)。

  Servlet容器為HttpSession分配一個唯一標誌符,稱為SessionID。Servlet容器將SessionID作為Cookie保存在客戶的瀏覽器中。

  每次客戶發送Http請求時,Servlet容器可以從HttpServletRequest對象中讀取SessionID,然後根據SessionID找到對應的HttpSession對象,從而獲取客戶的狀態信息。

Session的接口HttpSession:

  getId()   返回session的ID

  Invalidate()  讓當前session失效,Servlet容器會釋放HttpSession對象占用的資源

  getAttribut()     setAttribute()

    isNew()  判斷是否是新創建的session,如果是返回true 否則返回false

  setMaxInactiveInterval()  設置session的最大有效時間 單位為秒 如果設置為負數,表示不限制session處於不活動狀態的最大有效時間,默認的設置時間為30分鐘
技術分享

8. 說完了Servlet,來到了我們常用的框架中是怎麽攔截過濾Servlet的。那就說到了Servlet的過濾器Filter。

Servlet過濾器是在Java Servlet規範2.3中定義的,它能夠對Servlet容器的請求和響應對象進行檢查和修改。Servlet過濾器本身不生成請求和響應對象,它只提供過濾作用。Servlet過濾器能夠在Servlet被調用之前檢查Request對象,修改Request Header和Request內容。在Servlet被調用後檢查Response Header和Response內容,Servlet過濾器負責過濾WEB的組件可以是Servlet,JSP和HTML。

技術分享
Filter接口:

  每一個Servlet過濾器都會實現javax.serlvet.Filter接口,這個接口中含有三個過濾方法必須實現:

    init(FilterConfig):這是Servlet過濾器的初始化方法,Servlet容器創建Servlet過濾器後將調用這個方法,在這個方法中可以讀取web.xml中Servlet過濾器的初始化參數

    doFilter(ServletRequest,ServletResponse,FilterChain):這個方法完成實際的過濾操作。當客戶請求訪問與過濾器關聯的URL的時候,Servlet過濾器將先執行doFilter方法。FilterChain參數用於訪問後續過濾器。

    destroy():Servlet容器在銷毀過濾器實例前調用這個方法,在這個方法中可以釋放Servlet過濾器占用的資源。
技術分享

我們可以看一段使用struts框架中的過濾器的實例是怎麽操作的。

技術分享
//這個是在web.xml中使用struts2的過濾器的配置文件,
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name> 
    <url-pattern>/*</url-pattern>
</filter-mapping>
技術分享

9. 數字九嘛,立即想到的就是JSP的九大內置對象。

技術分享
JSP有以下九種內置對象:
        request,請求對象
        response,響應對象
        pageContext,頁面上下文對象
        session,會話對象
        application,應用程序對象
        out,輸出對象
        config,配置對象
        page,頁面對象
        exception,異常對象
    
    重點學習:request,session,application

 1. request的setAttribute()與getAttribute()方法一般都是成對出現的,首先通過setAttribute()設置屬性和屬性值,然後通過getAttribute()方法獲得與屬性對應的對象值(獲取到之後,一般都要向下類型轉換,將屬性值轉換為真正的對象)。setAttribute()與ge   tAttribute()都是在服務器端內部執行的,客戶端不知道服務器端是否執行該方法。
    
 2. request.getParameter()是服務器端獲取到客戶端通過表單或url請求參數所發送過來的參數值,是客戶端與服務器端之間的交互。服務器端要想獲取客戶端發送過來的數據,就需要通過getParameter()來獲取,沒有setParameter()方法。
    
 3. request內數據的存活範圍就是在request對象的存活範圍內,當客戶端向服務器端發送一個請求,服務器向客戶端返回一個響應後,該請求對象就被銷毀了;之後再向服務器端發送新的請求時,服務器會創建新的request對象,該request對象與之前的request對象沒有任   何關系,因此也無法獲得在之前的request對象中所存放的任何數據。

 4. session內數據的存活範圍就是session對象的存活範圍。

    application(應用對象):存活範圍最大的對象,只要服務器沒有關閉,application對象就會一直存在。在整個服務器的運行當中,application對象只有一個。

    application.getRealPath("")返回資源在服務器上的具體位置。
技術分享

10. 做Java Web項目當然離不開網絡,你要學會HTTP協議以及衍生的一些知識。(另詳述)

11. 理論實在太枯燥,我們說幾個實際開發中的場景吧:

//場景一:(異步消息機制)

在J2EE系統中最常見的一個場景,前端瀏覽器 jsp/servlet向服務器端發出一個請求,jsp/servlet將請求傳遞給後端的應用程序處理業務邏輯,業務模塊將響應的結果直接返回給客戶端,而不是真正的計算結果,例如一個網站的用戶註冊功能,一個用戶點擊註冊以後,將會發

送一份郵件給他當時的註冊郵箱,如果需要等到郵件發送成功再返回給用戶結果的話,用戶體驗將會很差,所以將結果直接返回給用戶,將用戶註冊的信息通過消息發送給後端程序慢慢處理。

上面的異步消息機制。JMS(Java消息服務)大體上有 3個部分消息發送端、中間件服務器、消息接收端。三個組件缺一不可。 JMS消息分為兩種消息模式,點對點和發布者/訂閱者。許多提供商支持這種。程序員可以在他們的分布式軟件中實現面向消息的操作,這些操作將具有不同面向消息中間件產品的可移植性。Java消息服務器是指,將數據通過消息作為載體在網絡中從一個系統異步傳送給另一個系統。這樣的異步消息傳送意味著:發送者不需要等待接收者接收或處理該消息;它可以自由地發送消息並持續進行處理。這樣一個異步式的架構主要依賴於一臺消息服務器(message server)。消息服務器,也稱為消息路由器(message router)或代理(broker),它負責從一個消息傳送客戶端向其他消息傳送客戶端傳送消息。

技術分享
JMS對與一個大型系統是必不可少的一個應用組件,可以利用JMS來實現3個目的:

    1.提高可伸縮性(Increase Scalability),

     2.可以利用JMS來緩解系統瓶頸(Reduce  Bottlenecks)

     3.提高系統對用戶的響應能力
技術分享

Topic消息和Queen消息:

  Topic 是一對多的消息傳送,你可以看做是QQ應用程序 QQ群 聊天中的一對多發送消息,一個人發出消息,可以有多個訂閱的人閱讀的到,需要有一個消息主題作為支柱,Tocip消息發送完畢以後 無論有 沒有客戶端接收,JMS服務器中的Topic消息都不會存在JMS服務器中。

  Queue是一對一的消息傳送,你可以看做是QQ應用程序中的一對一發送消息,一個人發出消息,只能有另外一個人閱讀的到,中間需要通過一個隊列支持Queue消息發送完畢後會保存在 JMS服務器的隊列 中,如果接收端接收以後將從隊列中摘除。

Topic發送完畢以後不會保留在JMS服務器;Queue消息發送完畢後會保存在 JMS服務器的隊列中。

//場景一:(Java應用多線程的場景)
我們的項目部署在Tomcat上,上百個客戶端訪問同一個web應用,tomcat接入後都是把後續的處理扔給一個新的線程來處理,這個新的線程最後調用到我們的servlet程序,比如doGet或者doPost方法。你想,如果不采用多線程機制,上百個人同時訪問一個web應用的時候,

tomcat就得排隊串行處理了,那樣客戶端根本是無法忍受那種訪問速度的。所以說,Tomcat內部采用的就是多線程。

比如任務 a和任務 b要並行處理,單個線程只能串行處理,先做完任務 a然後再做任務b。如果想要多個任務同時執行的話,就必須為每個任務分配一個線程,然後通過java虛擬機的線程調度,來同時執行多個任務。比如你的CPU是多核心的話,就可以讓一個CPU執行一個線程。如果只有一個CPU的話,底層是按照分時復用的原則,各個線程按照時間片來獲得CPU資源。那麽這種場景,顯然也是需要使用多線程的。

在Java web 開發方面,幾乎用不到多線程!因為有多線程的地方 servlet 容器或者其他開發框架都已經實現掉了。

技術分享
//場景一:(Java集合類的應用場景)
說到集合類,無非就是三個:List、Set和Map。
集合類,就是容器。容器就是箱子,Java中的箱子就是用來盛放Java對象。他們這三個箱子還是不一樣的。
第一個箱子,箱子List。在J2EE web項目中,我們的admin管理端,常常需要呈現一些數據。比如你做了一個淘寶,對於商家來說,商家登錄管理端。需要看到自己所有的訂單,以列表的形式展現出來。那麽這是我們常常會使用ArrayList。
  ArrayList<OrderList> list = new ArrayList<OrderList>();
  list.add(new OrderList());
  list.add(new OrderList());
  list.save();
 List這個箱子,按照對象進入的數學保存元素,不做排序和編輯操作。元素可以重復。
技術分享
強調一下,List是接口不是類。List接口繼承自 Collection接口。實現List接口的類主要有三個:LinkedList, ArrayList, Vector(面試中常有三種的區別)

List接口有三個實現類:LinkedList,ArrayList,Vector 
LinkedList:底層基於鏈表實現,鏈表內存是散亂的,每一個元素存儲本身內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢 
ArrayList和Vector的區別:ArrayList是非線程安全的,效率高;Vector是基於線程安全的,效率低 

List的功能方法

  實際上有兩種List: 一種是基本的ArrayList,其優點在於隨機訪問元素,另一種是更強大的LinkedList,它並不是為快速隨機訪問設計的,而是具有一套更通用的方法。

  List : 次序是List最重要的特點:它保證維護元素特定的順序。List為Collection添加了許多方法,使得能夠向List中間插入與移除元素(這只推薦LinkedList使用。)一個List可以生成ListIterator,使用它可以從兩個方向遍歷List,也可以從List中間插入和移除元素。

  ArrayList : 由數組實現的List。允許對元素進行快速隨機訪問,但是向List中間插入與移除元素的速度很慢。ListIterator只應該用來由後向前遍歷ArrayList,而不是用來插入和移除元素。因為那比LinkedList開銷要大很多。(ArrayList有默認的初始化容量以及擴容機制,面試中常被提及)

  LinkedList : 對順序訪問進行了優化,向List中間插入與刪除的開銷並不大。隨機訪問則相對較慢。(使用ArrayList代替。)還具有下列方法:addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 這些方法 (沒有在任何接口或基類中定義過)使得LinkedList可以當作堆棧、隊列和雙向隊列使用。

技術分享
第二個箱子,箱子Set。假如我們現在想要在一大堆數據中查找 X 數據。LinkedList的數據結構就不說了,查找效率低的可怕。ArrayList哪,如果我們不知道X的位置序號,還是一樣要全部遍歷一次直到查到結果,效率一樣可怕。HashSet天生就是為了提高查找效率的。
當使用HashSet時,hashCode()方法就會得到調用,判斷已經存儲在集合中的對象的hash code值是否與增加的對象的hash code值一致; 如果不一致,直接加進去; 如果一致,再進行equals方法的比較。equals方法如果返回true,表示對象已經加進去了,就不會再增加新的對象,否則添加進去。
http://www.java3z.com/cwbwebhome/article/article8/83553.html?id=4632  關於HashSet與hasCode() 的關系,可以看這篇帖子。

Set無放入順序,元素不可重復。同樣的Set是接口,它繼承自Collection接口,它的實現類有:HashSet(底層由HashMap實現),TreeSet,LinkedHashSet  

   

技術分享
Set具有與Collection完全一樣的接口,因此沒有任何額外的功能,不像前面有兩個不同的List。實際上Set就是Collection,只是行為不同。(這是繼承與多態思想的典型應用:表現不同的行為。)Set不保存重復的元素(至於如何判斷元素相同則較為負責)

  Set : 存入Set的每個元素都必須是唯一的,因為Set不保存重復元素。加入Set的元素必須定義equals()方法以確保對象的唯一性。Set與Collection有完全一樣的接口。Set接口不保證維護元素的次序。

  HashSet : 為快速查找設計的Set。存入HashSet的對象必須定義hashCode()。

  TreeSet : 保存次序的Set, 底層為樹結構。使用它可以從Set中提取有序的序列。

  LinkedHashSet : 具有HashSet的查詢速度,且內部使用鏈表維護元素的順序(插入的次序)。於是在使用叠代器遍歷Set時,結果會按元素插入的次序顯示。
技術分享
第三個箱子,箱子Map。List,Set,Map是否繼承自Collection接口?List,Set是,Map不是。 Collection是最基本的集合接口。 Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同key,每個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容可以被當做一組key集合和一組value集合,或者一組key-value映射。 

技術分享
 Map的功能方法:
  方法put(Object key, Object value)添加一個“值”(想要得東西)和與“值”相關聯的“鍵”(key)(使用它來查找)。方法get(Object key)返回與給定“鍵”相關聯的“值”。可以用containsKey()和containsValue()測試Map中是否包含某個“鍵”或“值”。標準的Java類庫中包含了幾種不同的Map:HashMap, TreeMap, LinkedHashMap, WeakHashMap, IdentityHashMap。它們都有同樣的基本接口Map,但是行為、效率、排序策略、保存對象的生命周期和判定“鍵”等價的策略等各不相同。

  執行效率是Map的一個大問題。看看get()要做哪些事,就會明白為什麽在ArrayList中搜索“鍵”是相當慢的。而這正是HashMap提高速度的地方。HashMap使用了特殊的值,稱為“散列碼”(hash code),來取代對鍵的緩慢搜索。“散列碼”是“相對唯一”用以代表對象的int值,它是通過將該對象的某些信息進行轉換而生成的。所有Java對象都能產生散列碼,因為hashCode()是定義在基類Object中的方法。

  HashMap就是使用對象的hashCode()進行快速查詢的。此方法能夠顯著提高性能。

  Map : 維護“鍵值對”的關聯性,使你可以通過“鍵”查找“值”

  HashMap : Map基於散列表的實現。插入和查詢“鍵值對”的開銷是固定的。可以通過構造器設置容量capacity和負載因子load factor,以調整容器的性能。

  LinkedHashMap : 類似於HashMap,但是叠代遍歷它時,取得“鍵值對”的順序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一點。而在叠代訪問時發而更快,因為它使用鏈表維護內部次序。

  TreeMap : 基於紅黑樹數據結構的實現。查看“鍵”或“鍵值對”時,它們會被排序(次序由Comparabel或Comparator決定)。TreeMap的特點在於,你得到的結果是經過排序的。TreeMap是唯一的帶有subMap()方法的Map,它可以返回一個子樹。

  WeakHashMao : 弱鍵(weak key)Map,Map中使用的對象也被允許釋放: 這是為解決特殊問題設計的。如果沒有map之外的引用指向某個“鍵”,則此“鍵”可以被垃圾收集器回收。

  IdentifyHashMap : 使用==代替equals()對“鍵”作比較的hash map。專為解決特殊問題而設計。
技術分享 技術分享

12. 講到Java這門語言,就不得不說其運行時候很關鍵的一部分,Java虛擬機。它承上啟下,基於操作系統,服務於我們的程序。我們的程序的具體執行是在Java虛擬機中來執行的。我們在Java基礎知識中,知道有基本數據類型和引用數據類型。所以,很多人只知道有堆內存和棧內存。但是,很顯然程序真正運行的時候,內存的劃分遠比這個發雜的多,接下來我們就詳細了解一下Java運行時,內存是怎麽劃分疆域的。

                     方法區                               堆
                   本地方法                           程序計數器
                       虛擬機

為了容易記憶,總共劃分為五個部分。方法區、本地方法棧、虛擬機棧、堆、程序計數器。

// 方法區
方法區與java堆棧一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等等。雖然java規範裏面把方法區描述為堆的一個邏輯部分,但是其實它是一個非堆【Non-Heap】,其目的就是為了和java堆區分開。

  在HotSpot虛擬機中,很多人都把方法區成為永久代,其實只在hotspot才存在方法區,在其他的虛擬機沒有方法區這一個說法的。本文是采用Hotspot,所以把方法區介紹了。在這裏在啰嗦一下,如果方法區無法滿足內存分配需求時候就會拋出OutOfMemoryError異常。
// 本地方法棧
本地方法棧和虛擬機棧差不多,只不過java虛擬機執行java的方法,本地方法區執行的是native方法而已,有的虛擬機把本地方法和虛擬機棧合二為一。
// Java虛擬機棧
java虛擬機棧和程序計數器一樣的,線程都是私有的,它的生命周期與線程一樣【虛擬機棧描述的是java方法執行的內存模型,每個方法執行的時候都會創建一個棧幀,用於存儲局部變量表、操作棧、動態鏈接、方法出口等信息。每一個方法被調用直至執行完成的過程。就對應著一個棧在虛擬機中從入棧道出棧的過程。
// 程序計數器
程序計數器是一個很小的內存空間,它的作用其實很簡單,就是當前線程所執行的字節碼行號的指示器。在Hotspot虛擬機中字節碼解釋器工作的時候就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令、分支、循環、跳轉、異常處理等等。
// 堆
在java程序員中堆,肯定不陌生,堆是使用的最多的,也是程序猿最關心的一快內存區域。堆中所有的線程都共享一個內存區域,在虛擬機啟動的時候就被創建,此內存區域唯一的目的就是存放對象實例,幾乎所有的對象實例都在這裏分配,但是隨著JIT的成熟,有些時候可能不一樣。

同時java堆中也是GC管理的主要區域,有時候也叫GC堆,java堆中可以分為新生代和老年代,Eden空間,from Survivor空間,To Survivor空間。新生代和Eden空間采用的GC算法【主要是分代收集算法】不一樣。

13. Java集合類框架。

文章轉載出自 : http://www.cnblogs.com/RunForLove/p/4636221.html

說說Java生態圈的那些事兒