天天看點

黑馬程式員——黑馬學習日志之十 集合(一)

------- android教育訓練、java教育訓練、期待與您交流! ----------

黑馬學習日志之十 集合(一)

1 集合

集合就是一種容器,用來存放對象。

集合類的出現:面向對象語言對事物的展現都是以對象的形式,是以為了友善對多個對象的  操作,就對對象進行存儲,集合就是存儲對象最常用的一種方式。

集合的特點:隻用于存儲對象,集合長度可變,可以存儲不同類型的對象。

集合和數組的差別:集合和數組都是容器。

                  數組雖然也可以存儲對象,但長度是固定的,可以存儲基本資料類型

                  集合長度是可變的,集合隻能存儲對象。

                  在實際使用中,如果長度固定,建議使用數組;如果長度不固定,建議使用集合。

2 集合架構

JDK為我們提供了一套完整的容器類庫,這些類統稱為集合類,它們都位于java.util包中。

整個集合類按照存儲結構被分為單列集合和雙列集合,單列集合的的根接口是Collection,雙列集合的根接口是Map集合。在Collection接口中主要有兩個子接口,分别是List和Set。Map接口的主要子接口有HashMap和TreeMap。

黑馬程式員——黑馬學習日志之十 集合(一)

3 Collection

  根接口:  Collection

  子接口:    丨—— List  可重複, 有存儲順序,有索引 

               丨—— Set   元素無序 不可重複

由于Collection是個接口,是以它沒有構造方法,示範它的基本方法,隻能通過其子類來驗證。如ArrayList

方法執行個體:

class  CollectionDemo

{

public static void main(String[] args) 

{

method_get();

}

public static void method_get()

{

ArrayList al = new ArrayList();

//1,添加元素。add(Object obj);

al.add("java01");

al.add("java03");

al.add("java04");

sop(al);

}

public static void method_2()

{

ArrayList al1 = new ArrayList();

al1.add("java01");

al1.add("java02");

al1.add("java03");

al1.add("java04");

ArrayList al2 = new ArrayList();

al2.add("java03");

al2.add("java04");

al2.add("java05");

al2.add("java06");

al1.retainAll(al2); //去交集,al1中隻會保留和al2中相同的元素。

al1.removeAll(al2);

sop("al1:"+al1);

sop("al2:"+al2);

}

public static void base_method()

{

//建立一個集合容器。使用Collection接口的子類。ArrayList

ArrayList al = new ArrayList();

//1,添加元素。

al.add("java01");//add(Object obj);

al.add("java02");

al.add("java03");

al.add("java04");

//列印原集合。

sop("原集合:"+al);

//3,删除元素。

al.remove("java02");

al.clear();//清空集合。

//4,判斷元素。

sop("java03是否存在:"+al.contains("java03"));

sop("集合是否為空?"+al.isEmpty());

//5,擷取個數。集合長度。

sop("size:"+al.size());

//列印改變後的集合。

sop(al);

}

public static void sop(Object obj)

{

System.out.println(obj);

}

}

注意:1,add方法的參數類型是Object。以便于接收任意類型對象。

      2,集合中存儲的都是對象的引用(位址)

4 疊代器

什麼是疊代器呢?

疊代器就是集合取出元素的方式。取出方式定義在集合内部,這樣取出方式可以直接通路集合内容元素,那麼取出方式就被定義成了内部類。

每一個容器的資料結構不同,是以取出的動作細節也不一樣,但是都有共性内容判斷和取出,那麼可以将共性取出。

這些内部類都符合一個規則,就是Iterator.擷取集合的取出對象,通過一個對外提供的方法iterator。

疊代器是取出方式,會直接通路集合中的元素。是以将疊代器通過内部類的形式來進行描述。通過容器的iterator()方法擷取該内部類的對象。

如同抓娃娃遊戲機中的夾子,夾子是疊代器,取出方式被定義在容器内部,夾子的實作方式不同,但封裝在内部。

例子:

class  CollectionDemo

{

public static void main(String[] args) 

{

method_get();

}

public static void method_get()

{

ArrayList al = new ArrayList();

//添加元素。

al.add("java01");//add(Object obj);

al.add("java02");

al.add("java03");

al.add("java04");

Iterator it = al.iterator();//擷取疊代器,用于取出集合中的元素。

while(it.hasNext())

{

sop(it.next());

}

// 疊代的另一種用法

for(Iterator it = al.iterator(); it.hasNext() ; )

{

sop(it.next());

}

}

public static void sop(Object obj)

{

System.out.println(obj);

}

}

5 List集合

List集合是Collection的一個子接口,繼承了Collection中的方法。

List集合:元素有序,可重複,該集合體系有索引

List子類:Vector:底層是數組資料結構,線程同步,但增删查詢速度慢,被ArrayList替代。

          ArrayList:底層是數組資料結構,線程不同步,查詢速度快。預設容量為10

          LinkedList:底層使用連結清單資料結構,增删速度快

List集合的特有方法:凡是可以操作角标的方法,都是該體系特有方式。

add(int i,Object obj):在指定位置添加元素

addAll(int I,Collection):在指定位置添加一堆的元素

get  使用size和get方法可以周遊集合中的元素

int indexOf(Object o):傳回此清單中第一次出現的指定元素的索引,如果此清單中不包    含該元素,則傳回-1

int lastIndexOf(Object o):傳回此清單中最後出現的指定元素的索引:如果清單中不包    含此元素,則傳回-1;

List subList(int fromIndex, int toIndex):傳回清單中指定的fromIndex和toIndex之間的           部分的集合。

boolean add(E e):向list裡添加元素

void add(index,E e):在index索引位插入元素

boolean remove(E e):删除元素,有這個值就傳回真,沒有這個值就傳回假

Object remove(int index):根據索引位(角标)删除,會把删除的元素傳回

E set(int index, E element):對索引位置的元素進行修改。會傳回你傳入的元素.

E get(int index):通過索引位(角标)擷取到對應的元素

List subList(int fromIndex, int toIndex):根據指定的頭尾角标擷取子清單

例子:

import java.util.*;

class ListDemo 

{

public static void sop(Object obj)

{

System.out.println(obj);

}

public static void method()

{

ArrayList al = new ArrayList();

//添加元素

al.add("java01");

al.add("java02");

al.add("java03");

sop("原集合是:"+al);

//在指定位置添加元素。

al.add(1,"java09");

//删除指定位置的元素。

//al.remove(2);

//修改元素。

//al.set(2,"java007");

//通過角标擷取元素。

sop("get(1):"+al.get(1));

sop(al);

//擷取所有元素。

for(int x=0; x<al.size(); x++)

{

System.out.println("al("+x+")="+al.get(x));

Iterator it = al.iterator();

while(it.hasNext())

{

sop("next:"+it.next());

}

//通過indexOf擷取對象的位置。

sop("index="+al.indexOf("java02"));

List sub = al.subList(1,3);

sop("sub="+sub);

}

public static void main(String[] args) 

{

 method();

}

}

6 ListIterator

ListIterator是List集合特有的疊代器,ListIterator是Iterator的子接口。

在疊代時,不可以通過集合對象的方法操作集合中的元素,因為會發生并發修改異常(ConcurrentModificationException)。

是以,在疊代器時,隻能用疊代器的方法操作元素,可是Iterator方法是有限的,隻能對元素進行判斷,取出,删除的操作如果想要其他的操作 如添加,修改等,就需要使用其子接口,ListIterator。該接口隻能通過List集合的listIterator方法擷取。

例子:

public static void main(String [] args){

     ArrayList al = new ArrayList();

   //添加元素

   al.add("java01");

   al.add("java02");

   al.add("java03");

   al.add("java04");

   sop(al);

        //疊代器擷取所有元素

   Iterator it = al.iterator(); 

   while (it.hasNext())

   {

    Object obj = it.next();

    if (obj.equals("java02"))

   {

    //al.add("java08");//并發同步異常。疊代器和集合操作不能同    時來執行 

it.remove();  //iterator隻能對元素進行判斷取出删除操作

  }

   sop("obj"+obj);

 }

  sop(al);

}

Iterator例子:

public static void main(String[] args) {

List li = new ArrayList();

li.add("a");

li.add("A");

li.add("b");

li.add("c");

li.add("d");

ListIterator lit = list.listIterator();

while(li.hasNext())

  {

    Object obj =li.next();

     if(obj.equals("A"))

    {

     li.add("e");//在java02後添加Java09

      li.set("a2");//将java02改為Java006

    }

 }

System.out.println("----------------------------");

while(lit.hasPrevious()) { //倒序周遊

System.out.println(lit.previous());

}

7 vector

Vector是List集合的一個子類。底層是數組資料結構,線程同步,但增删查詢速度慢,被ArrayList替代。

Vector中提供了一個獨特的取出方式,就是枚舉Enumeration。此接口Enumeration的功能與 Iterator 接口的功能是重複的Enumeration的名稱和方法的名稱過程,書寫很麻煩。是以被Iterator所取代.

例子:

class VectorDemo{

public static void main(String[] args) {

Vector v = new Vector();

v.addElement("abc1");

v.addElement("abc2");

v.addElement("abc3");

Enumeration en = v.elements();

while(en.hasMoreElements()){

System.out.println(en.nextElement());

}

}

}

8 LinkedList

 LinkedList是List的子類,底層是連結清單資料結構,增删快,查詢慢。

 LinkedList的特有方法: 

添加

void addFirst(Object o): 把元素添加到第一個位置

void addLast(Object o): 把元素添加到最末的位置

擷取

Object getFirst(): 擷取LinkedList中的第一個元素

Object getLast(): 擷取LinkedList中的最後一個元素

Peakfirst()  peaklast() 也是擷取元素

對于get的方法,如果集合中沒有元素,就會抛出異常,

對于peak的方法,如果集合中沒有元素,就會出現null

删除(通過指針被删除的元素都會傳回被删除的元素)

  removeLast()   removeFirst():  如果集合中沒有元素,傳回異常

  pollLast()      pollFirst():如果集合元素沒有,該方法不會抛異常,null

例子:

import java.util.*;

class Duilie

{

private LinkedList list;

Duilie()

{

list = new LinkedList();

}

public void myAdd(Object obj)

{

list.addFirst(obj);

}

public Object myGet()

{

return list.removeFirst();.//先進後出

  //return list.removeLast();  //先進先出

}

public boolean isNull()

{

return list.isEmpty();

}

public static void sop(Object obj)

{

System.out.println(obj);

}

}

class LinkedListTest 

{

public static void main(String[] args) 

{

Duilie dl =new Duilie();

dl.myAdd("java01");

dl.myAdd("java02");

dl.myAdd("java03");

dl.myAdd("java04");

while(!dl.isNull())

{

Duilie.sop(dl.myGet());

}

}

}

9 Set集合

set是根接口collection的一個子接口,繼承了collection的方法。

set集合:元素無序(存入和取出順序不一緻),不可重複,沒有索引。

Set子類:

HashSet:底層是哈希表資料結構,線程非同步。

TreeSet:底層是二叉樹資料結構,可以對set集合中的元素進行排序

10 HashSet

HashSet是set集合的子類,底層是哈希表資料結構。其集合中沒有重複元素。

保證元素唯一:哈希表存儲結構,其實就是哈希值的存儲,每個對象都有一個哈希值通過equals方法和hashCode方法來保證元素的唯一性。hash算法時計算元素的位址值的,它在對對象的存儲的時候是先調用hashCode方法,然後再執行重寫equals方法。

HashSet集合保證元素唯一性,依賴的是元素的hashCode方法和euqals方法。

當元素的哈希值不同時,元素都有自己的獨立位置。不需要在判斷元素的equals方法,

當元素的哈希值相同時,這時元素在哈希表中位置相同,這時就需要在判斷一次元素的内容是否相同。就需要調用元素的equals方法進行一次比較。如果equals傳回是true。那麼視為兩個元素為重複元素。隻儲存一個。如果傳回是false,那麼這兩個元素不是重複元素,會存儲在同一個哈希值上。

 HashSet原理

我們使用Set集合都是需要去掉重複元素的, 如果在存儲的時候逐個equals()比較, 效率較低。

雜湊演算法提高了去重複的效率, 降低了使用equals()方法的次數。當HashSet調用add()方法存儲對象的時候, 先調用對象的hashCode()方法得到一個哈希值, 然後在集合中查找是 否有哈希值相同的對象,如果沒有哈希值相同的對象就直接存入集合;如果有哈希值相同的對象, 就和哈希值相同的對象逐個進行equals()比較,比較結果為false就存入, true則不存。

注意:

類中必須重寫hashCode()和equals()方法

hashCode(): 屬性相同的對象傳回值必須相同, 屬性不同的傳回值盡量不同(提高效率)

equals(): 屬性相同傳回true, 屬性不同傳回false,傳回false的時候存儲

例子:

class HashSetTest 

{

public static void sop(Object obj)

{

System.out.println(obj);

}

public static void main(String[] args) 

{

HashSet hs = new HashSet();

hs.add(new Person("a1",11));

hs.add(new Person("a2",12));

hs.add(new Person("a3",13));

hs.add(new Person("a2",12));

hs.add(new Person("a4",14));

Iterator it = hs.iterator();

while(it.hasNext())

{

Person p = (Person)it.next();

sop(p.getName()+"::"+p.getAge());

}

}

}

class Person

{

private String name;

private int age;

Person(String name,int age)

{

this.name = name;

this.age = age;

}

public int hashCode()

{

System.out.println(this.name+"....hashCode");

return name.hashCode()+age*37;

}

public boolean equals(Object obj)

{

if(!(obj instanceof Person))

return false;

Person p = (Person)obj;

System.out.println(this.name+"...equals.."+p.name);

return this.name.equals(p.name) && this.age == p.age;

}

public String getName()

{

return name;

}

public int getAge()

{

return age;

}

}            

11 TreeSet

TreeSet是set集合的子類,底層是二叉樹資料結構可以對set集合中的元素進行排序,預設自然排序。

保證資料唯一性:

compareTo方法return 0為同一個元素return 1 放元素二叉樹右邊 return -1放元素左邊

TreeSet排序方式:

TreeSet排序的第一種方式:讓元素自身具備比較性。元素需要實作Comparable接口,覆寫compareTo方法,這種方式也成為元素的自然順序 或者叫做預設排序。

例子:

import java.util.*;

class Student implements Comparable

{

private String name; 

private int age;

Student(String name,int age)

{

this.name = name;

this.age = age;

}

public int compareTo(Object obj)   

{                  

if(!(obj instanceof Student))

throw new RuntimeException("對象類型錯誤");

Student stu = (Student)obj;

if(this.age > stu.age)

return 1;

if(this.age == stu.age)              //主要特征比較不出來,用次要特征。

return this.name.compareTo(stu.name); //String類也有compareTo方法。

return -1;

}

public String getName()

{

return name;

}

public int getAge()

{

return age;

}

}

class TreeSetTest

{

public static void main(String[] args) 

{

TreeSet ts = new TreeSet();

ts.add(new Student("sun01",22));

ts.add(new Student("sun02",21));

ts.add(new Student("sun04",21));

ts.add(new Student("sun05",20));

Iterator it = ts.iterator();

while(it.hasNext())

{

               Student s = (Student)it.next();

   sop(s.getName()+"======"+s.getAge());

}

}

public static void sop(Object obj)

{

System.out.println(obj);

}

}

TreeSet排序的第二種方式:當元素自身不具備比較性時,或者具備的比較性不是所需要的,這時需要讓集合自身具備比較性(好比集合裡面有個刻度闆)。在集合的初始化時,就有了比較方式 此時要參閱集合的構造方法。

例子:

import java.util.*;

class Student 

{

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;

}

}

class TreeSetTest2 

{

public static void main(String[] args) 

{

TreeSet ts = new TreeSet(new MyComparator());

ts.add(new Student("sun001",15));

ts.add(new Student("sun002",12));

ts.add(new Student("sun006",10));

ts.add(new Student("sun002",19));

ts.add(new Student("sun004",11));

Iterator it = ts.iterator();

while(it.hasNext())

{

Student stu = (Student)it.next();

sop(stu.getName()+"====="+stu.getAge());

}

}

public static void sop(Object obj)

{

System.out.println(obj);

}

}

//TreeSet的第二種排序方式。 集合自身具備比較性。

class MyComparator implements Comparator

{

public int compare(Object o1,Object o2)

{

Student s1 = (Student)o1;

Student s2 = (Student)o2;

int num = s1.getName().compareTo(s2.getName());

if(num == 0)

{

if(s1.getAge()>s2.getAge())

return 1;

if(s1.getAge()<s2.getAge())

return -1;

return 0;

}

return num;

}

}

12 泛型

  集合在初始化時沒有定義資料類型,潛在安全隐患,出現了泛型。

泛型:jdk1.5版本後出現的新特性。用于解決安全問題,是一個安全機制。

泛型好處:(1)運作期間的classCastException轉移到編譯時期,友善程式員解決問題,讓 運作期問題減少,較安全。

           (2)避免強制轉換麻煩。

泛型格式:通過< >來定義要操作的引用資料類型。其實< >就是來接收資料類型的。

例子:

import java.util.*;

class GenericDemo 

{

    public static void main(String[] args) 

{

 ArrayList<String> al1 = new ArrayList<String>();

 al1.add("sss");

 al1.add("sqq");

 al1.add("saa");

 sop(al1);

 ArrayList<Integer> al2 = new ArrayList<Integer>();

 al2.add(1);

 al2.add(2);

 al2.add(3);

sop(al2);

}

public static<T> void sop(ArrayList<T> al) //T代表一個明确類型

{

Iterator<T> it = al.iterator();

while(it.hasNext())

{

T t = it.next();

System.out.println(t.length());

}

}

}

泛型類

什麼時候定義泛型類:當類中要操作的引用資料類型不确定的時候。早期定義Object 來完成擴充,現在定義泛型來完成擴充。

例子:

class Worker

{

}

class Student

{

}

class Utils<QQ>

{

 private QQ q;

 public void setObject(QQ q){

   this.q = q;

 }

 public QQ getObject(){

   return q;

 }

}

class GenerinDemo3

{

  public static void main(String [] args){

   Utils<Worker>  u= new Utils<Worker>();

   u.setObject(new Worder());

    Worker w = u.getObject();

     }

}

泛型方法:

泛型類定義的泛型,在整個類中有效。泛型類的對象明确要操作的具體類型後,所有要操做的類型就已經固定了。

為了讓不同方法可以操作不同類型,而且類型還不确定,那麼可以将泛型定義在方法上。

例子:

class Demo

{

 public <T> void show(T t){

    System.out.println("show:"+t);

  }

 public <Q> void print(Q q){//該泛型隻在這個方法中有效

   System.out.println("print:"+t);

 }

}

class GenericDemo4

{

 public static void main(String [] args){

  Demo d = new Demo();

  d.show(new Integer(4));

    d.print("hehe");

  d.show("hahah");

 }

靜态泛型方法:

靜态方法不可以通路類上定義的泛型

如果靜态方法操作的應用資料類型不确定,可以将泛型定義在方法上

例子:

class Demo1<T>

{

  public  void show(T t){

   System.out.println("show:"+t);

 }

     public <Q> void print(Q q){

    System.out.println("print:"+q);

 }

 public  static <W> void method(W t){

   System.out.println("method::"+t);

  }

}

public class GenericDemo5

{

  public static void main(String [] args){

    Demo1<String> d1 = new Demo1<String>();

    d1.print(5); 

d1.show("hahah");

   Demo1.method("hehehehe");

 }

   }

泛型限定

? 通配符,也可以了解為占位符。

?extends E:可以接受E類或者E的子類型 上限

?super E:可以接受E類型或者E的父類型 下限

例子:

import java.util.*;

class Person

{

private String name;

Person(String name)

{

this.name = name;

}

public String getName()

{

return name;

}

}

class Student extends Person

{

private String name;

Student(String name)

{

super(name);

}

}

class GenericTest 

{

public static void main(String[] args) 

{

ArrayList<Person> al = new ArrayList<Person>();

al.add(new Person("sun01"));

al.add(new Person("sun02"));

al.add(new Person("sun03"));

sop(al);

ArrayList<Student> al1 = new ArrayList<Student>();

al1.add(new Student("sss01"));

al1.add(new Student("sss02"));

al1.add(new Student("sss03"));

sop(al1);

}

public static void sop(ArrayList<? extends Person> al)

{

Iterator<? extends Person> it = al.iterator();

while(it.hasNext())

{

System.out.println(it.next().getName());

}

}

}

------- android教育訓練、java教育訓練、期待與您交流! ----------