Java集合框架Collections【List/Set】

  1. 集合就是存放對象的,他比數(shù)組好的一點(diǎn)就是他一開始不清楚自己長度
    容器一般是分為很多種的,很多的容器在一起然后進(jìn)過斷的抽象和抽取就成了一個(gè)體系,我們稱之為集合框架
    我們看體系首先是看頂層的容器,他是底層的容器都有的特性,然后在逐步求精
    最頂層的我們稱之為collection 在util包中的

  2. 在collection中分為兩個(gè)比較常用的子接口分別是list和set宪拥。
    list是類似于數(shù)組的那種,也就是集合元素可重復(fù)个唧,有序有腳標(biāo)江解。
    set則為無序的,所以集合元素不可重復(fù)徙歼,不可腳標(biāo)查找
    以下是List的通用方法:

    • 添加元素:
      add(index,data)
    • 刪除元素:
      remove(index)
    • 修改元素:
      set(index,data)
    • 獲取元素:
      get(index) 配合for循環(huán)
    • 迭代器
      indexOf(data)
      subList(start,end)

    在list中有一個(gè)特殊的迭代器犁河,其他的集合都沒有只是list有叫做ListIterater
    這個(gè)迭代器比一般的迭代器會多非常多的功能

    另外注意的一點(diǎn)就是在使用iterater進(jìn)行l(wèi)ist迭代的時(shí)候,不能夠使用集合的方法對集合進(jìn)行增刪改查的操作
    否則就會出現(xiàn)一個(gè)運(yùn)行時(shí)異常魄梯,主要原因就是同時(shí)操作一個(gè)集合導(dǎo)致不合法桨螺,類似于同時(shí)IO同一塊數(shù)據(jù)塊
    因此在迭代的過程中只能使用迭代器提供的操作集合的方法
    或者不使用迭代器,直接使用原生的for循環(huán)酿秸,然后直接就可以使用迭代器的方法進(jìn)行對集合的操作

  3. add方法接受的參數(shù)類型為object以便于接受任意類型的參數(shù)
    集合中存放的是對象的地址而不是對象本身
    對象可以直接被打印

  4. List可以分為三種灭翔,但是常用的只有兩種,他們之間的主要區(qū)別就是底層的數(shù)據(jù)及結(jié)構(gòu)不一樣辣苏。

  • ArrayList 底層的實(shí)現(xiàn)使用的是數(shù)組肝箱,也就是說類似于數(shù)組構(gòu)成的線性表,查詢快增刪慢稀蟋,而且他是不同步的
  • LinkedList 底層使用的是鏈表煌张,那么就會出現(xiàn)查詢慢,增刪快
  • Vector 底層和ArrayList完全一樣退客,只不過vector就是jdk1.0出現(xiàn)的那時(shí)候還沒有集合框架骏融,后來有了集合框架被分到List里面,目前被ArrayList代替因?yàn)樗峭降乃俣嚷瓤瘢覀兌际怯肁rraylist然后自己寫鎖來手動同步
  1. arraylist和vector之間區(qū)別還有就是他們們的迭代方式可以有不同档玻,由于vector是最先出來的,所以說他一開始用的并不是
    iterator迭代器而是枚舉enumeration他和迭代器很相似茫藏,目前由于枚舉不好記就用iterator误趴。另外arraylist和vector使用的
    是變長數(shù)組,也就是本來都是固定長度10個(gè)元素务傲,然后如果查過十個(gè)以后ArrayList使用的是50%的增長也就是會變成15個(gè)冤留,二vector則是
    直接100%增長20個(gè)
    枚舉的代碼如下:

        public class Enmu {
            public static void main(String[] args) {
                Vector v=new Vector();
                v.add("1");
                v.add("2");
                v.add("3");
                Enumeration e=v.elements(); //定義枚舉
                while (e.hasMoreElements()){  //循環(huán)遍歷
                    System.out.println(e.nextElement());
                }
            }
        }
    
  2. LinkedList中除了一般的List的通用方法還有他自己特有的方法碧囊,而且比較重要

    • addFirst
    • addLast
    • getFirst 獲取元素但是不刪除元素
    • getLast
    • removeFirst 獲取元素而且刪除元素,但是如果給的是一個(gè)空的鏈表列表使用此方法會產(chǎn)生異常因此有了以下替代方法
    • removeLast
    • offerFirst 添加
    • offerLast
    • peekFirst 獲取
    • peekLast
    • pollFirst 刪除
    • pollLast 空鏈表列表也不會有異常而是直接返回null

    代碼如下:

        public class LinkedList_5 {
            public static void main(String[] args) {
                LinkedList list=new LinkedList();
                list.addFirst("1");
                list.addFirst("2");
                list.addFirst("3");
                System.out.println(list.getFirst());
                System.out.println(list.removeFirst());
    
                LinkedList list1=new LinkedList();
                list1.offerFirst("1");
                list1.offerFirst("2");
                list1.offerFirst("3");
                System.out.println(list1.peekFirst());
                System.out.println(list1.pollFirst());
    
            }
        }
    

7.使用LinkedList實(shí)現(xiàn)堆棧和隊(duì)列結(jié)構(gòu)也就是他所特有的addFirst addLast 以及remove方法的使用
只是要注意在LinkedList里面添加和刪除的元素都是object而不是一般的對象纤怒,應(yīng)該說
所有的集合框架里面的東西都是接受object對象的 所以在寫具體的函數(shù)的時(shí)候注意一下

8.使用ArrayList寫幾個(gè)小程序,第一個(gè)就是使用ArrayList去處重復(fù)元素天通,其中的元素就是字符串泊窘,而第二個(gè)則是
去除的某些自定義對象。第二個(gè)程序也揭示了對于List集合中的元素的比較的接口就是contains他底層是調(diào)用
的對象的equals方法像寒,對于remove也是底層調(diào)用了equals方法從而進(jìn)行比較和刪除烘豹。所以說重點(diǎn)在于重寫
equals方法。
另外在迭代器中每使用一次next方法必須要進(jìn)行一次hasNext的判斷否則很有可能出現(xiàn)找不到元素的情況
例如一個(gè)hasNext里面有兩個(gè)next方法诺祸,而元素又為奇數(shù)個(gè)時(shí)候會拋異常

        class Person{
            private String name;
            private int age;
            Person(String name,int age){
                this.name=name;
                this.age=age;
            }
            String getName(){
                return this.name;
            }
            private int getAge(){
                return this.age;
            }
            public boolean equals(Object object){
                if (!(object instanceof Person)){
                    return false;
                }
                Person person=(Person)object;  //注意這個(gè)地方必須要強(qiáng)轉(zhuǎn)否則會出現(xiàn)下面的person無法調(diào)用方法
                return this.name.equals(person.getName()) && this.age==person.getAge();
            }
        }
        public class ArrayList_7 {
            private static ArrayList<Person> singleElement(List<Person> al){
                ArrayList<Person> newAl=new ArrayList<Person>();
                Iterator<Person> it=al.iterator();
                while (it.hasNext()){
                    Person tmp= it.next();  //iterator返回的是object所以必須要強(qiáng)轉(zhuǎn)
                    if (!newAl.contains(tmp)){
                        newAl.add(tmp);
                    }
                }
                return newAl;
            }

            public static void main(String[] args) {
                ArrayList<Person> al=new ArrayList<>();
                al.add(new Person("zhang01",1));
                al.add(new Person("zhang02",2));
                al.add(new Person("zhang03",1));
                al.add(new Person("zhang03",1));
                al=singleElement(al);
                for (Person per : al) {   //可以使用這種更好的語言結(jié)構(gòu)來實(shí)現(xiàn)迭代省去了iterator迭代 也不用考慮向下類型轉(zhuǎn)換
                    System.out.println(per.getName());
                }
            }
        }

9.Set中存放的元素都是無序的并且里面的元素都是不可重復(fù)的携悯,顯然如果只存放字符串的話很容易就知道是否重復(fù)
也就無序我們自己去判斷是否重復(fù)了。
set中的公共方法就是集合框架中共有的方法筷笨,重要的還是他的子類憔鬼,這里有兩個(gè)就是hashSet和TreeSet

而存放一般的自定義對象的時(shí)候我們發(fā)現(xiàn)如果想要某些屬性一致的對象作為重復(fù)對象
的話hashSet自身是做不到的,所以我們需要了解hashSet的底層層放原理胃夏,hashSet底層就是hash表轴或,在存放元素的時(shí)候
首先來判斷存放的元素的hashCode值是否一樣也就是調(diào)用他們的hashCode方法,注意hashCode是object對象的方法仰禀,所以
所有的對象都有此方法照雁,另外如果他們的hashCode是一樣的然后就調(diào)用他們的equals方法.不一樣則就存進(jìn)去一樣則被踢出去
那么說白了hashSet底層判斷是否為重復(fù)元素做了兩件事第一個(gè)就是判斷他們的hashCode第二個(gè)就是equals方法
如果要自定義對象如何存放就要重寫這兩個(gè)方法,但是重寫的時(shí)候一定要注意他們的參數(shù)列表否則肯定不會生效答恶,hashCode
一般來說也盡量不要讓不同的對象的hashCode一致造成多余的比較

對于元素判斷是否存在和刪除元素都是hashCode和equals方法

下面是hashSet的代碼示例:

  class People{
      private String name;
      private int age;

      People(String name,int age){
          this.name=name;
          this.age=age;
      }

      String getName(){
          return this.name;
      }

      private int getAge(){
          return this.age;
      }

      public int hashCode(){
          return name.hashCode()+age;
      }

      public boolean equals(Object object){
          if (!(object instanceof People)){
              return false;
          }
          People person=(People)object;  //注意這個(gè)地方必須要強(qiáng)轉(zhuǎn)否則會出現(xiàn)下面的person無法調(diào)用方法
          return this.name.equals(person.getName()) && this.age==person.getAge();
      }

  }

  public class HashSet_8 {
      public static void main(String[] args) {
          HashSet<People> hs=new HashSet<People>();
          hs.add(new People("1",11));
          hs.add(new People("2",11));
          hs.add(new People("1",11));
          for (People pe:hs){
              System.out.println(pe.getName());
          }
      }
  }

10.treeSet是在集合中的元素會自動排序饺蚊,如果是字符串什么的他們都可以自動比較,因?yàn)樽址且呀?jīng)實(shí)現(xiàn)了Compareable接口
但是如果要存放一般的元素對象的時(shí)候注意一定要讓改類實(shí)現(xiàn)compareable接口悬嗓,因?yàn)榇私涌跁岊悘?qiáng)制具有比較性
然后復(fù)寫此接口中的compareTo方法污呼,大于返回正數(shù)等于為零小于則為負(fù),這里要注意如果有多個(gè)排序元素的話然后在比較
的時(shí)候相等條件判斷要注意對其他排序元素的判斷烫扼,否則會造成某個(gè)條件相等但是并不是同一個(gè)元素而無法存入

class Student implements Comparable{
 private String name;
 private int age;

 Student(String name,int age){
     this.name=name;
     this.age=age;
 }

 public String getName() {
     return name;
 }

 public int getAge() {
     return age;
 }

 @Override
 public int compareTo(Object o) {
     if (!(o instanceof Student)){
         throw new RuntimeException("not same type");
     }
     if (this.age>((Student) o).age){
         return 1;
     }else if (this.age==((Student) o).age){
         return this.name.compareTo(((Student) o).name);
         //注意多重判斷曙求,要是age一樣的話他們就會被當(dāng)成相同元素而無法插入  string類已經(jīng)實(shí)現(xiàn)了comparable接口
         //其實(shí)java中很多類都實(shí)現(xiàn)了comparable接口,讓類具有可比性
     }
     return -1;
 }
}

public class TreeSet_9 {
 public static void main(String[] args) {
     TreeSet<Student> ts=new TreeSet<>();
     ts.add(new Student("ab",1));
     ts.add(new Student("kb",3));
     ts.add(new Student("mb",3));
     ts.add(new Student("am",7));
     for (Student stu :
             ts) {
         System.out.println(stu.getName()+"--------"+stu.getAge());
     }
 }
}

11.TreeSet底層的數(shù)據(jù)結(jié)構(gòu)就是二叉樹映企,元素的排列方式就是第一個(gè)進(jìn)入的元素作為根節(jié)點(diǎn)然后按照compareTo方法
返回的值來判定是左孩子還是右孩子悟狱,這里就是如果說compareTo方法返回的正數(shù)則右孩子,負(fù)數(shù)為左孩子相等就說明
是同一個(gè)元素不用再比較。
所以說決定了TreeSet中的元素的重復(fù)與否就是compareTo函數(shù)的返回值
那么這樣的話我們也可以規(guī)定一個(gè)TreeSet按照放進(jìn)去的順序取出來 或者倒序取出來就是compareTo全部返回1
或者-1即可堰氓,當(dāng)然如果返回的始終為0那么最后集合中只有一個(gè)元素就是第一個(gè)元素

12.在TreeSet中除了實(shí)現(xiàn)comparable接口復(fù)寫compareTo方法以外還有一種排序方法就是比較器挤渐,前面的comparable
接口是讓元素具有了比較性而比較器則是讓集合具有了比較性這個(gè)優(yōu)先級跟高,具體的方法就是在集合實(shí)例化的時(shí)候傳入一個(gè)
自定義的比較器双絮,也就是構(gòu)造方法傳入一個(gè)比較器對象浴麻,這個(gè)比較器也是一個(gè)接口要實(shí)例化的話需要實(shí)現(xiàn)他的compare方法
比較器也是更加常用的


class MyComparator implements Comparator{

 public int compare(Object o1,Object o2){
     Student obj1=(Student)o1;
     Student obj2=(Student)o2;
     int num=obj1.getName().compareTo(obj2.getName());
     if (num==0){
        return new Integer(obj1.getAge()).compareTo(obj2.getAge());
     }
     return num;
 }
}

public class TreeSet_10 {
 public static void main(String[] args) {
     TreeSet<Student> ts=new TreeSet<Student>(new MyComparator());
     ts.add(new Student("dsf",11));
     ts.add(new Student("dmf",12));
     ts.add(new Student("ddf",13));
     ts.add(new Student("jf",14));
     for (Student stu :
             ts) {
         System.out.println(stu.getName()+"----------"+stu.getAge());
     }
 }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末得问,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子软免,更是在濱河造成了極大的恐慌宫纬,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膏萧,死亡現(xiàn)場離奇詭異漓骚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)榛泛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蝌蹂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人曹锨,你說我怎么就攤上這事孤个。” “怎么了沛简?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵齐鲤,是天一觀的道長。 經(jīng)常有香客問我覆享,道長佳遂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任撒顿,我火速辦了婚禮丑罪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凤壁。我一直安慰自己吩屹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布拧抖。 她就那樣靜靜地躺著煤搜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唧席。 梳的紋絲不亂的頭發(fā)上擦盾,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音淌哟,去河邊找鬼迹卢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛徒仓,可吹牛的內(nèi)容都是我干的腐碱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼掉弛,長吁一口氣:“原來是場噩夢啊……” “哼症见!你這毒婦竟也來了喂走?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谋作,失蹤者是張志新(化名)和其女友劉穎芋肠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遵蚜,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡业栅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谬晕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡携取,死狀恐怖攒钳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雷滋,我是刑警寧澤不撑,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站晤斩,受9級特大地震影響焕檬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜澳泵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一实愚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兔辅,春花似錦腊敲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至介时,卻和暖如春没宾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沸柔。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工循衰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勉失。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓羹蚣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乱凿。 傳聞我的和親對象是個(gè)殘疾皇子顽素,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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