黑馬程序員_Java基礎_集合(1)

------- android培訓java培訓、期待與您交流! ----------

集合框架:

 爲什麼會出現那麼多容器?
 因爲每一個容器 對數據的存儲方式是不一樣的
 這個存儲方式稱之爲:數據結構

 數組和集合類有何不同?
 數組雖然可以存儲對象,但長度是固定的;
 集合長度是可變的,數組中可以存儲基本數據類型,集合只能存儲對象
 集合類的特點
 集合只用於存儲對象,集合長度是可以改變的,集合可以存儲不同類型的對象
 1. add方法的參數類型是Object.與便於接受任意類型對象
 2. 集合中存儲的都是對象的引用(對象地址) 


Conllection 
     |--List:元素是有序的,元素可以重複,因爲該集合體繫有索引
        |--ArrayList:底層的數據結構使用的是數組結構。  特點:查詢速度很快,但是增刪稍慢,線程不同步。    1.2版本出現
        |--LinkedList:底層使用的是鏈表結構, 特點:增刪速度很快,查詢速度稍慢。
        |--Vector:底層使用的是數組數據結構。  線程同步。被ArrayList替代了。  1.0版本出現
  
     |--Set:元素是無序的,元素不可以重複



例子1:
 
public class ConllectionDemo {


    /**

     * @param args

     */

    public static void main(String[] args) {

//      base_mentod();

        metod02();


    }

    public static void metod02() {

        

        ArrayList al = new ArrayList();

        

        al.add("java01");

        al.add("java02");

        al.add("java03");

        al.add("java04");

        

        ArrayList al01 = new ArrayList();

        

        al01.add("java03");

        al01.add("java04");

        al01.add("java05");

        al01.add("java06");

        

        ///去交集,al01中只會保留和al02中相同的元素。

//      al.retainAll(al01);

        print(al);

        

        

        //al去掉與al01中相同的元素,保留剩下的元素

        al.removeAll(al01);

        print(al);

        

    }


    public static void base_mentod() {

        // 創意一個容器,使用Conllection接口的子類ArryList類進行創建

        ArrayList al = new ArrayList();


        // 1.添加元素

        al.add("java01");

        al.add("java02");

        al.add("java03");

        al.add("java04");


        // 打印集合

        print(al);


        // 2.判斷元素是否存在

        print("java02時候存在:" + al.contains("java02"));

        print("集合是否爲空:" + al.isEmpty());


        // 3.獲取元素個數,集合長度

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


        // 4.刪除元素

        al.remove("java02");


        // 5.清空集合

        al.clear();

        print(al);


    }


    // 打印

    public static void print(Object obj) {

        System.out.println(obj);

    }


}


 List :
 特有方法:方式可以操作的角標的方法都是該體系特有的方法
 
 add(index,element); 添加一個元素
 addAll(index,Conllection);  添加一個集合
 刪
 removed(index);
 改
 set(index,element);
 查
 get(index);
 subList(from, to);
 listIterator();
 
 List集合特有的迭代器。 ListIterator是Iterator的子接口。
 
 在迭代時,不可以通過集合對象的方法操作集合中的元素。
 因爲會發生ConcurrentModificationException異常
 
 所以,在迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的
 只能對元素進行判斷,取出,刪除的操作
如果想要其他的操作如添加、修改等,就需要使用其子接口,ListIterator
該接口只能通過List集合的listIterator方法獲取(因爲List集合有下標,這方法是唯一的)
ListIterator常見方法
 add(E e)  將指定的元素插入列表
 set(E e)    用指定元素替換 next 或 previous 返回的最後一個元素
 hasNext()   以正向遍歷列表時,如果列表迭代器有多個元素,則返回 true(換句話說,如果 next 返回一個元素而不是拋出異常,則返回 true)。
 next()    返回列表中的下一個元素。
 hasPrevious()     如果以逆向遍歷列表,列表迭代器有多個元素,則返回 true。
 previous()   返回列表中的前一個元素。
例子2:
public class ListDemo {


    public static void main(String[] args) {

        // 創建一個容器

        ArrayList list = new ArrayList();


        list.add("1");

        list.add("2");

        list.add("3");

        list.add("4");

        

        //使用ListIterator在迭代過程中,可以進行對元素集合的操作

        ListIterator it = list.listIterator();

        System.out.println(list);

        

        //從頭部來時遍歷

        while(it.hasNext()){   

            Object obj = it.next();

            

            if(obj.equals("2")){

//              it.add("5");   //可以在ListIterator迭代過程中對元素進行操作

//              it.remove();

//              it.set("5");   //替換

            }

        }

        System.out.println(list);

        

        System.out.println("List hasPrevicous"+it.hasPrevious());

        

        //從尾部開始進行遍歷

        while(it.hasPrevious()){

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

        }


        


    }

    public static void method(){


        // 創建一個容器

        ArrayList list = new ArrayList();


        list.add("1");

        list.add("2");

        list.add("3");

        list.add("4");


        // 創建一個新的容器

        ArrayList list_1 = new ArrayList();


        list_1.add("5");

        list_1.add("6");


        // 將集合list_1添加到list中

        list.add(4, list_1);


        // 查

        Iterator ite = list.iterator();

        while (ite.hasNext()) {

            System.out.println("list:" + ite.next());

        }

        

        //改

        list.set(0, "***");

        System.out.println("修改後:"+list);

        

        //刪除

        list.remove(0);

        System.out.println("刪除第一個下標:"+list);

    }


}

例子3:需求:去除ArrayList集合中重複的元素
public class ArrayListTest {


    /**

     * @param args

     */

    public static void main(String[] args) {


        ArrayList list = new ArrayList();

        list.add("1");

        list.add("2");

        list.add("1");

        list.add("3");

        list.add("2");

        list.add("4");

        System.out.println(list);

        //去除重複元素之後

        list = singleElement(list);

        System.out.println(list);

        

    }

    public static ArrayList singleElement(ArrayList list){

        ArrayList temp = new ArrayList();

        

        Iterator it = list.iterator();

        while(it.hasNext()){

            Object obj=  it.next();

            if(!temp.contains(obj))

                temp.add(obj);

        }

        return temp;

    }


}


 例子4:
將自定義對象作爲元素存放在ArrayList集合中, 並去除重複的元素
 比如: 存人對象,同性名同年齡,視爲同一個人能,爲重複元素
 思路:
 對人描述,將數據封裝到人對象中
 定義容器,將人存入
 取出 
class Person {

    private String name;

    private int age;


    Person(String name, int age) {

        this.name = name;

        this.age = age;

    }


    @Override

    public boolean equals(Object obj) {

        if (!(obj instanceof Person))

            return false;

        Person person = (Person) obj;

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

    }


    public String getName() {

        return name;

    }


    public int getAge() {

        return age;

    }


}


public class ArrayListTest1 {


    public static void main(String[] args) {

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


        list.add(new Person("李四01", 20));

        list.add(new Person("李四02", 22));

        list.add(new Person("李四03", 23));

        list.add(new Person("李四02", 22));

        list.add(new Person("李四02", 22));

        list.add(new Person("李四04", 24));

        

        list = singleElement(list);

        

        Iterator it = list.iterator();

        while(it.hasNext()){

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

            print(p.getName()+"---"+p.getAge());

        }


    }


    public static ArrayList singleElement(ArrayList list) {

        ArrayList temp = new ArrayList();


        Iterator it = list.iterator();

        while (it.hasNext()) {

            Object obj = it.next();

            if (!temp.contains(obj))    //這裏的contains依賴Object中的equals方法

                temp.add(obj);

        }

        return temp;

    }

    public static void print(Object obj){

        System.out.println(obj);

    }


}

迭代器:  就是集合的取出元素的方式
  
  每一個容器的數據結構不同,取出的細節也是不一樣的,但都是有共性內容的
  那麼這些內部類都符合一個規則,該規則就是Iterator
  
 如何獲取集合的去除對象?
  通過一個對外提供的方法
 iterator();
public class IteratorDemo {

    public static void main(String[] args) {

        //創建一個容器

        ArrayList list = new ArrayList();

        

        list.add("java01");

        list.add("java02");

        list.add("java03");

        list.add("java04");

//      第一中方式:

//      Iterator ite = list.iterator();  //獲取迭代器

//      while(ite.hasNext())

//          System.out.println(ite.next());

        

//      第二種方式:國外流行是用,比較減少資源消耗

        for(Iterator ite = list.iterator(); ite.hasNext();)

            System.out.println(ite.next());

    }


}

LinkedList特有方法: (它都會集成List接口的所有方法,我們這裏不在說,只介紹一下它特有的方法)
addFirst();
addLast();
getFirst();
getLast();
獲取元素,但不刪除元素。 如果集合中沒有元素,會穿線NoSuchElementException異常
removeFirst();
removeLast();
獲取元素,但是元素被刪除。   如果集合中沒有元素,會穿線NoSuchElementException異常

JDK1.6出現了替代方法:
offerFirst();
offerLast();
peekFirst();
peekLast();
獲取元素,但不刪除元素。 如果集合中沒有元素,會返回nul
pollFirst();
pollLast();
獲取元素,但是元素被刪除。 如果集合中沒有元素,會返回nul

public class LinkedListDemo {

    public static void main(String[] args) {

        LinkedList link = new LinkedList();

        //從第一位添加

//      link.addFirst("1");

//      link.addFirst("2");

//      link.addFirst("3");

//      link.addFirst("4");

        print(link);

//      print(link.getFirst());                 //當集合沒有元素時,這個方法會拋出異常

        print(link.pollFirst());     //刪除

//      print(link.getLast());

        print(link.pollLast());

//      print(link.removeFirst());  //獲取並刪除元素    當集合沒有元素時,這個方法會拋出異常

        print(link.peekFirst());    //獲取

        print(link.peekLast());

        

        

        LinkedList link1 = new LinkedList();

        //從最後以爲添加

        link1.addLast("5");

        link1.addLast("6");

        link1.addLast("7");

        link1.addLast("8");

        print(link1);

//      print(link1.getFirst());

//      print(link1.getLast());

        //遍歷

        while(!link1.isEmpty()){

            print(link1.removeFirst());

        }

        


    }

    

    public static void print(Object obj){

        System.out.println(obj);

    }


}


需求:使用LinkedList模擬一個堆棧或者隊列數據結構
堆棧:先進後出
隊列:先進先出  (FIFO) 
 
//隊列類

class Queue{

    private LinkedList link;

    Queue(){

        link = new LinkedList();

    }

    

    public void add(Object obj){

        link.addFirst(obj);

    }

    public Object  get(){

        return link.removeLast();

    }

    public boolean isNull(){

        return link.isEmpty();

    }

    

}


public class LinkedListTest {

    public static void main(String[] args) {

        Queue que = new Queue();

        que.add("1");

        que.add("2");

        que.add("3");

        que.add("4");

        

        while(!que.isNull()){

        System.out.println(que.get());

        }

        


    }


}

枚舉就是Vector特有的取出方式(線程安全,但效率不高)
發現枚舉和迭代器很像
其實枚舉和迭代器是一樣的(可以查文檔看看)
因爲枚舉的名稱以及方法的名稱都過長。
所以被迭代器取代了

public class VectorDemo {

    public static void main(String[] args) {

        

        //使用Vector創建一個新的容器

        Vector vec = new Vector();

        

        vec.add("1");

        vec.add("2");

        vec.add("3");

        vec.add("4");

        

         Enumeration enu = vec.elements();

         while(enu.hasMoreElements()){

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

         }


    }


}
 Set:元素是無序的(存入和取出的順序不一定一致)   元素不可以重複
 |---HashSet:頂層數據結構是哈希表
      |--hashSet是如何保證元素唯一性的呢?
           是通過元素的兩個方法,hashCodeequals來完成。
           如果元素的HashConde值相同,纔會判斷equals是否爲true
           如果元素的HashConde值不同,不會調 用equals.
 注意:對於判斷元素是否存在,以及刪除等操作,(依賴的方法是元素的hashCode和equals方法)
 

 |---TreeSet:
     Set集合的功能和Collection是一致的

例子:
public class HashSetDemo {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        // HashSet集合是沒有重複元素的
        hs.add("1"); // 方法返回的是boolean true
        hs.add("1"); // false   重複添加的元素都無false的
        hs.add("2"); // true
        hs.add("3");// true
        hs.add("3");// false
        hs.add("4");// true
        Iterator it = hs.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

需求: 將自定義對象作爲元素存放在HashSet集合中, 並去除重複的元素 

實現
public class HashSetTest {
    public static void main(String[] args) {
        HashSet hash = new HashSet();
        hash.add(new Student("lisi01", 21));
        hash.add(new Student("lisi01", 21));
        hash.add(new Student("lisi02", 22));
        hash.add(new Student("lisi03", 23));
        
        hash.contains(new Student("lisi01", 21));//true 判斷集合中是否有這一元素,依賴該元素的hashCode和equals方法
        hash.remove(new Student("lisi01", 21)); // 刪除也依賴該元素的hashCode和equals方法
        Iterator it = hash.iterator();
        while (it.hasNext()) {
            Student p = (Student) it.next();
            System.out.println(p.getName() + ":" + p.getAge());
        }
    }
}
class Student {
    private String name;
    private int age;
    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public int hashCode() {
        return name.hashCode() + age * 37; // 這是爲了讓哈希表唯一(必須的*重點)
    }
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Student))
            return false;
        Student person = (Student) obj;
        return this.name.equals(person.name) && this.age == person.age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}

TreeSet:可以對Set集合中的元素進行排序
  底層數據結構是二叉樹
  保證元素唯一性的依據:compareTo方法return 0.
  
  TreeSet排序的第一種方式:讓元素自身具備比較性。
  元素需要實現Comparable接口,覆蓋compareTo方法
  這種方式也成爲元素的自然排序,或者叫做默認排序
  
  TreeSet的第二種排序方式:
  當元素自身不具備比較性是,或者具備比較性不是所需要的。
  這是就需要讓集合自身具備比較性
  在集合初始化時,就有了比較方式;(創建一個類,實現Comparator比較器,複寫compareTo方法,將該類放到TreeSet的構造函數中)
需求:
往TreeSet集合中存儲自定義對象人
想按照人的年齡進行排序
記住,排序是,當主要條件相同時,一定判斷一下次要條件 

例子1:
public class TreeSetTest {
    public static void main(String[] args) {
        TreeSet tree = new TreeSet();
        tree.add(new People("lisi001",21));
        tree.add(new People("lisi001",21));  //去掉重複對象
        tree.add(new People("lisi002",22));
        tree.add(new People("lisi005",22));   //當年齡相同時,判斷姓名進行排序
        tree.add(new People("lisi003",23));
        tree.add(new People("lisi004",24));
        
        Iterator it = tree.iterator();
        while(it.hasNext()){
            People p = (People) it.next();
            System.out.println(p.getName()+"_____"+p.getAge());
            
        }
    }
}
class People implements Comparable{   //一定要實現Comparable接口,爲TreeSet排序時使用到  (重點)
    private String name;
    private int age;
    People(String name ,int age){
        this.name = name;
        this.age = age;
    }
    @Override
    public int compareTo(Object obj) {
        if(!(obj instanceof People))
            throw new RuntimeException("不是People類對象");
        People p = (People) obj;
        
        if(this.age > p.age)
            return 1;
        if(this.age == p.age){
            return this.name.compareTo(p.name);    //當年齡相同時,還用對姓名進行排序,String類應實現了Comparable接口
        }
        return -1;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    
    
}

當元素自身不具備比較性,或者具備的比較性不是所需要的
 這時需要讓容器自身具備比較性
 定義了比較器,將比較器對象作爲參觀傳遞給TreeSet集合的構造函數
 當兩種排序都存在時,以比較器爲主
 定義一個類,實現Comparator接口,覆蓋compareTo方法 
例子2: 
 
public class TreeSetTest01 {
    public static void main(String[] args) {
        TreeSet tree = new TreeSet(new MyComparator());  //使用構造函數進行排序
        tree.add(new People01("lisi001", 21));
        tree.add(new People01("lisi001", 21)); // 去掉重複對象
        tree.add(new People01("lisi002", 22));
        tree.add(new People01("lisi005", 22)); // 當年齡相同時,判斷姓名進行排序
        tree.add(new People01("lisi003", 23));
        tree.add(new People01("lisi004", 24));
        Iterator it = tree.iterator();
        while (it.hasNext()) {
            People01 p = (People01) it.next();
            System.out.println(p.getName() + "_____" + p.getAge());
        }
    }
}
class MyComparator implements Comparator{
    @Override
    public int compare(Object o1, Object o2) {
        People01 p1 = (People01) o1;
        People01 p2 = (People01) o2;
        int num = p1.getName().compareTo(p2.getName());
        //姓名相同
        if(num == 0){
            //當姓名相同時,比較年齡
            return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));   
        }
        return num;
    }
    
}
class People01 {//implements Comparable { // 一定要實現Comparable接口,爲TreeSet排序時使用到 (重點)
    private String name;
    private int age;
    People01(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}


 練習:按照字符串長度排序
字符串本書具備比較性,但是它的比較方式不是鎖所需要的
我們只能使用比較器

例子3:
public class TreeSetTest02 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new Comparator(){
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = (String) o1;
                String s2 = (String) o2;
                int num = new Integer(s1.length()).compareTo(s2.length());
                if(num == 0){
                    return s1.compareTo(s2);
                }
                    
                return num;
            }
            
        });
        
        ts.add("t");
        ts.add("ac");
        ts.add("zcf");
        ts.add("acdr");
        ts.add("acf");
        ts.add("dddd");
        
        Iterator it = ts.iterator();
        
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章