java面試熱點(diǎn):集合框架(一)

Java集合框架由Java類庫的一系列接口威始、抽象類以及具體實(shí)現(xiàn)類組成。集合就是把一組對(duì)象組織到一起像街,然后再根據(jù)不同的需求操縱這些數(shù)據(jù)黎棠。集合類型就是容納這些對(duì)象的一個(gè)容器。根據(jù)集合中是否允許有重復(fù)的對(duì)象镰绎、對(duì)象組織在一起是否按某種順序等標(biāo)準(zhǔn)來劃分的話脓斩,集合類型又可以細(xì)分為許多種不同的子類型。

java集合框架提供了一組基本機(jī)制以及這些機(jī)制的參考實(shí)現(xiàn)畴栖,其中基本的集合接口是Collection接口随静,其他相關(guān)的接口還有Iterator接口、RandomAccess接口吗讶。
抽象類的好處:提供了接口的部分實(shí)現(xiàn)燎猛,這樣就可以在實(shí)現(xiàn)類的基礎(chǔ)上實(shí)現(xiàn)部分功能而不必重寫接口的所有方法。

Collection接口

Collection接口是集合層級(jí)結(jié)構(gòu)的根接口照皆,里面的方法有:

 int size();
 boolean isEmpty();
 boolean contains(Object o);
 Iterator<E> iterator();
 Object[] toArray();
 <T> T[] toArray(T[] a);
 boolean add(E e);
 boolean remove(Object o);
 boolean containsAll(Collection<?> c);
 boolean addAll(Collection<? extends E> c);
 boolean removeAll(Collection<?> c);
 boolean retainAll(Collection<?> c);     //僅保留給定集合c中的元素(optional operation).
 void clear();//清空集合
 boolean equals(Object o);//繼承自O(shè)bject
 int hashCode();//繼承自O(shè)bject

值得注意的是兩個(gè)toArray方法:
它們的功能都是都是返回這個(gè)集合的對(duì)象數(shù)組重绷。第二個(gè)方法接收一個(gè)arrayToFill參數(shù),當(dāng)這個(gè)參數(shù)數(shù)組足夠大時(shí)膜毁,就把集合中的元素都填入這個(gè)數(shù)組(多余空間填null)昭卓;當(dāng)arrayToFill不夠大時(shí),就會(huì)創(chuàng)建一個(gè)大小與集合相同爽茴,類型與arrayToFill相同的數(shù)組葬凳,并填入集合元素绰垂。
我們看一下Collection<E>接口的迭代器:

public interface Iterable<T> {
  Iterator<T> iterator();
}

這個(gè)接口只定義了一個(gè)方法室奏,這個(gè)方法要求我們返回一個(gè)實(shí)現(xiàn)了Iterator<T>類型的對(duì)象,所以我們看下Iterator<T>的定義:

public interface Iterator<E> { 
  boolean hasNext(); 
  E next(); 
  void remove();
}

迭代器就是一個(gè)我們用來遍歷集合中的對(duì)象的東西劲装。即對(duì)于集合胧沫,我們不像對(duì)原始類型數(shù)組那樣通過數(shù)組索引來直接訪問相應(yīng)位置的元素,而是通過迭代器來遍歷占业。這么做的好處是將對(duì)于集合類型的遍歷行為與被遍歷的集合對(duì)象分離绒怨,這樣一來我們無需關(guān)心該集合類型的具體實(shí)現(xiàn)是怎樣的。只要獲取這個(gè)集合對(duì)象的迭代器, 便可以遍歷這個(gè)集合中的對(duì)象了谦疾。而像遍歷對(duì)象的順序這些細(xì)節(jié)南蹂,全部由它的迭代器來處理。
小總結(jié):Collection接口實(shí)現(xiàn)了Iterable<E>接口念恍,這意味著所有實(shí)現(xiàn)了Collection接口的具體集合類都是可迭代的六剥。一個(gè)迭代器對(duì)象也就是實(shí)現(xiàn)了Iterator<E>接口的對(duì)象晚顷,這個(gè)接口要求我們實(shí)現(xiàn)hasNext()、next()疗疟、remove()這三個(gè)方法该默。通常,迭代一個(gè)集合對(duì)象的代碼是這個(gè)樣子的:

Collection<String> c = ...;
Iterator<String> iter = c.iterator();
while (iter.hasNext()) {
  String element = iter.next();
  //do something with element
}

以上代碼可以用增強(qiáng)for來代替:

for (String element : c) {
  //do something with element
}

注意:Iterator接口的remove方法必須在next方法返回一個(gè)元素后才能調(diào)用策彤!


Collection接口是集合層級(jí)結(jié)構(gòu)的根接口栓袖。一個(gè)集合代表了一組對(duì)象,這組對(duì)象被稱為集合的元素店诗。一些集合允許重復(fù)的元素而其他不允許裹刮;一些是有序的而一些是無序的。Java類庫中并未提供任何對(duì)這個(gè)接口的直接實(shí)現(xiàn)必搞,而是提供了對(duì)于它的更具體的子接口的實(shí)現(xiàn)(比如Set接口和List接口)必指。
Collection接口的直接子接口主要有三個(gè):List接口、Set接口和Queue接口恕洲。

  1. List接口:
    List是一個(gè)有序的集合類型(也被稱作序列)塔橡。使用List接口可以精確控制每個(gè)元素被插入的位置,并且可以通過元素在列表中的索引來訪問它霜第。列表允許重復(fù)的元素葛家,并且在允許null元素的情況下也允許多個(gè)null元素。
    官方定義了以下這些方法:
ListIterator<E> listIterator();
void add(int i, E element);
E remove(int i);
E get(int i);
E set(int i, E element);
int indexOf(Object element);

上面有一個(gè)listIterator方法泌类,它返回一個(gè)列表迭代器癞谒。ListIterator<E>接口定義的方法有:

void add(E e) //在當(dāng)前位置添加一個(gè)元素
boolean hasNext() //返回ture如果還有下個(gè)元素(在正向遍歷列表時(shí)使用)
boolean hasPrevious() //反向遍歷列表時(shí)使用
E next() //返回下一個(gè)元素并將cursor(也就是指針)前移一個(gè)位置
int nextIndex() //返回下一次調(diào)用next方法將返回的元素的索引
E previous() //返回前一個(gè)元素并將cursor向前移動(dòng)一個(gè)位置
int previousIndex() //返回下一次調(diào)用previous方法將返回的元素的索引void remove() //從列表中移除最近一次調(diào)用next方法或previous方法返回的元素
void set(E e) //用e替換最近依次調(diào)用next或previous方法返回的元素

ListIterator<E>是Iterator<E>的子接口,它支持像雙向迭代這樣更加特殊化的操作刃榨。
Java類庫中常見的實(shí)現(xiàn)了List<E>接口的類有:ArrayList弹砚, LinkedList,Stack枢希,Vector桌吃,AbstractList,AbstractSequentialList等等苞轿。

  • ArrayList
    ArrayList是一個(gè)可動(dòng)態(tài)調(diào)整大小的數(shù)組茅诱,允許null類型的元素。Java中的數(shù)組大小在初始化時(shí)就必須確定下來搬卒,而且一旦確定就不能改變瑟俭,這會(huì)使得在很多場景下不夠靈活。ArrayList很好地幫我們解決了這個(gè)問題契邀,當(dāng)我們需要一個(gè)能根據(jù)包含元素的多少來動(dòng)態(tài)調(diào)整大小的數(shù)組時(shí)摆寄,那么ArrayList正是我們所需要的。常用方法有:
boolean add(E e) //添加一個(gè)元素到數(shù)組末尾
void add(int index, E element) //添加一個(gè)元素到指定位置
void clear()
boolean contains(Object o)
void ensureCapacity(int minCapacity) //確保ArrayList至少能容納參數(shù)指定數(shù)目的對(duì)象,若有需要會(huì)增加ArrayList實(shí)例的容量微饥。
E get(int index) //返回指定位置的元素
int indexOf(Object o)
boolean isEmpty()
Iterator<E> iterator()
ListIterator<E> listIterator()
E remove(int index)
boolean remove(Object o)
E set(int index, E element)
int size()

當(dāng)我們插入了比較多的元素锐帜,導(dǎo)致ArrayList快要裝滿時(shí),它會(huì)自動(dòng)增長容量畜号。ArrayList內(nèi)部使用一個(gè)Object數(shù)組來存儲(chǔ)元素缴阎,自動(dòng)增長容量是通過創(chuàng)建一個(gè)新的容量更大的Object數(shù)組,并將元素從原Object數(shù)組復(fù)制到新Object數(shù)組來實(shí)現(xiàn)的简软。若要想避免這種開銷蛮拔,在知道大概會(huì)容納多少數(shù)據(jù)時(shí),我們可以在構(gòu)造時(shí)指定好它的大小以盡量避免它自動(dòng)增長的發(fā)生痹升;我們也可以調(diào)用ensureCapacity方法來增加ArrayList對(duì)象的容量到我們指定的大小建炫。ArrayList有以下三個(gè)構(gòu)造器:

ArrayList()
ArrayList(Collection<? extends E> c)
ArrayList(int initialCapacity) //指定初始capacity,即內(nèi)部Object數(shù)組的初始大小

這里提一下Arraylist的值得注意的一點(diǎn)疼蛾,集合成員允許出現(xiàn)null元素肛跌,而且可以多個(gè)。請(qǐng)看一下代碼:

/**
 * 關(guān)于List中是否可以添加Null的測試
 * @author kyy
 */
public class Demo1 {
    public static void main(String[] args) {
        List<User> users=new ArrayList<User>();
        for (int i = 0; i < 10; i++) {
            users.add(new User());
        }
        //添加null不報(bào)錯(cuò)察郁,但是這樣在堆集合元素進(jìn)行方法調(diào)用時(shí)衍慎,有可能出現(xiàn)空指針異常
        users.add(null);
        //添加Object,報(bào)錯(cuò)
        //users.add(new Object());
        System.out.println(users.size());//運(yùn)行結(jié)果:11
        for (User user : users) {
            //這里要進(jìn)行判斷皮钠,不然有可能發(fā)生空指針異常
            /*if(user!=null){
                System.out.println(user.getUsername());
            }*/
            System.out.println(user.getUsername());
        }
    }
}
class User{
    private String username="小明";
    private int age;
    public String getUsername(){
        return this.username;
    }
}

因?yàn)锳rraylist中允許出現(xiàn)null元素稳捆,所以在遍歷的時(shí)候,如果為對(duì)象麦轰,獲取對(duì)象屬性的時(shí)候要先判斷遍歷出來的對(duì)象是否為null乔夯,這樣才可以避免空指針異常。
而且款侵,集合不為空不代表集合長度就不為0末荐,所以在遍歷集合的時(shí)候要進(jìn)行雙重判斷,先判斷集合是否為Null,再判斷集合是否長度大于0.

  • LinkedList類
    LinkedList類代表了一個(gè)雙向鏈表新锈,也允許null元素甲脏。這個(gè)類同ArrayList一樣,不是線程安全的壕鹉。
    這個(gè)類中主要有以下的方法:
void addFirst(E element);
void addLast(E element);
E getFirst();
E getLast();
E removeFirst();
E removeLast();

LinkedList的一個(gè)缺陷在于它不支持對(duì)元素的高效隨機(jī)訪問剃幌,要想隨機(jī)訪問其中的元素聋涨,需要逐個(gè)掃描直到遇到符合條件的元素晾浴。只有當(dāng)我們需要減少在列表中間添加或刪除元素操作的代價(jià)時(shí),可以考慮使用LinkedList牍白。jdk類庫中實(shí)現(xiàn)了List<E>接口的類有:ArrayList脊凰, LinkedList,Stack,Vector狸涌,AbstractList切省,AbstractSequentialList等等。

說到線程安全帕胆,List接口的幾個(gè)實(shí)現(xiàn)類中朝捆,Arraylist和Linkedlist都不是線程安全的,而Stack和Vector則是線程安全的懒豹,但是線程不安全的可以通過Collections的同步方法轉(zhuǎn)換為線程安全對(duì)象芙盘,具體實(shí)現(xiàn),請(qǐng)讀者翻看jdk源代碼脸秽,我相信會(huì)有另一翻收獲的儒老!

參考資料

  1. 《Java核心技術(shù)(卷一)》
  2. What is a view of a collection?
  3. Java SE 7 Docs
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市记餐,隨后出現(xiàn)的幾起案子驮樊,更是在濱河造成了極大的恐慌,老刑警劉巖片酝,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件囚衔,死亡現(xiàn)場離奇詭異,居然都是意外死亡雕沿,警方通過查閱死者的電腦和手機(jī)佳魔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晦炊,“玉大人鞠鲜,你說我怎么就攤上這事《瞎” “怎么了贤姆?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長稳衬。 經(jīng)常有香客問我霞捡,道長,這世上最難降的妖魔是什么薄疚? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任碧信,我火速辦了婚禮,結(jié)果婚禮上街夭,老公的妹妹穿的比我還像新娘砰碴。我一直安慰自己,他們只是感情好板丽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布呈枉。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猖辫。 梳的紋絲不亂的頭發(fā)上酥泞,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音啃憎,去河邊找鬼芝囤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛辛萍,可吹牛的內(nèi)容都是我干的凡人。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼叹阔,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼挠轴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耳幢,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤岸晦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后睛藻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體启上,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年店印,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冈在。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡按摘,死狀恐怖包券,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炫贤,我是刑警寧澤溅固,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站兰珍,受9級(jí)特大地震影響侍郭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掠河,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一亮元、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唠摹,春花似錦爆捞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至望艺,卻和暖如春苛秕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背找默。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國打工艇劫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惩激。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓店煞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親风钻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子顷蟀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 概述 Java集合框架由Java類庫的一系列接口、抽象類以及具體實(shí)現(xiàn)類組成骡技。我們這里所說的集合就是把一組對(duì)象組織到...
    absfree閱讀 1,254評(píng)論 0 10
  • 1.Java集合框架是什么鸣个?說出一些集合框架的優(yōu)點(diǎn)? 每種編程語言中都有集合布朦,最初的Java版本包含幾種集合類:V...
    Oneisall_81a5閱讀 901評(píng)論 0 11
  • 1.Java集合框架是什么囤萤?說出一些集合框架的優(yōu)點(diǎn)? 每種編程語言中都有集合是趴,最初的Java版本包含幾種集合類:V...
    獨(dú)念白閱讀 770評(píng)論 0 2
  • 1.Java集合框架是什么涛舍?說出一些集合框架的優(yōu)點(diǎn)? 每種編程語言中都有集合唆途,最初的Java版本包含幾種集合類:V...
    胖先森閱讀 810評(píng)論 4 17
  • 無論是不是低落在塵埃肛搬,只要你愿意 文/紫藤蘿 晚上和閨蜜聊天吹榴,感慨起來歲月匆匆。無非而已滚婉,大學(xué)畢業(yè)也就三年图筹,可是回...
    辛小丹文案運(yùn)營閱讀 466評(píng)論 0 6