黑马程序员---java基础------------------集合框架1------Collection

为什么出现集合类:

面向对象语言对事物的体现都是一对象的形式,所以威客方便多个对象的操作,对对象进行存储,集合就是常用的存储对象的方式之一,另一种就是数组,我们已经学习过了。

数组和集合都是用于存储对象的容器,他们之间的区别在于:数组是固定长度的,但是它可以存储基本数据类型;但是集合是可变长度的,它只能存储对象。

集合类的特点:长度可变,可以存储不同类型的对象。

集合框架组织图:

这些都是根据数据结构的不同区分的。

Collection定义了集合框架的共性功能。

1,添加  add(e);  addAll(collection);

    1,add方法的参数类型是Object。      以便于接收任意类型对象。

2,集合中存储的都是对象的引用(地址)

2,删除  remove(e);  removeAll(collection);  clear();

3,判断。  contains(e);  isEmpty();

4,获取  iterator();  size();

5,获取交集。  retainAll();

6,集合变数组。  toArray();

迭代器:集合的取出元素的方式。会直接访问集合中的元素。所以将迭代器通过内部类的形式来进行描述。通过容器的iterator()方法获取该内部类的对象。

class  CollectionDemo {  

      public static void main(String[] args)  {      

          method_get();  

      }  

    public static void method_get()  {   

      ArrayList al = new ArrayList();

        //1,添加元素。   

      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() ; )   {    for循环也是可以获取集合中的元素的,因为list结构是有角标的基于数组的

          sop(it.next());   

      }  

  }

   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());

      //2,获取个数。集合长度。   

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

      //打印改变后的集合。   

      sop(al);

   }

   public static void sop(Object obj)  {   

      System.out.println(obj);  

      }

}

Collection

    |--List:元素是有序的,元素可以重复。因为该集合体系有索引。

      |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。

      |--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。

      |--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。

            枚举就是Vector特有的取出方式。

    发现枚举和迭代器很像。其实枚举和迭代是一样的。

      Enumeration en = v.elements();

      while(en.hasMoreElements())

      {

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

      }

    |--Set:元素是无序,元素不可以重复

  


    List:  特有方法。凡是可以操作角标的方法都是该体系特有的方法。

      增  add(index,element);  addAll(index,Collection);

      删  remove(index);

      改  set(index,element);

      查  get(index):  subList(from,to);       listIterator();                int indexOf(obj):获取指定元素的位置。            ListIterator listIterator();

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

        在迭代时,不可以通过集合对象的方法操作集合中的元素。 因为会发生ConcurrentModificationException异常。所以,在迭代器时,只能用迭代器的方式操作

      元素,可是Iterator方法是有限的, 只能对元素进行判断,取出,删除的操作, 如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。

      该接口只能通过List集合的listIterator方法获取。

JDK1.6出现了替代方法。

offerFirst();

offerLast();

peekFirst();//peek看一眼的意思

peekLast();获取元素,但不删除元素。如果集合中没有元素,会返回null

pollFirst();//poll剪短,修剪

pollLast();获取元素,但是元素被删除。如果集合中没有元素,会返回null

 

 

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)  {

          //演示列表迭代器。   

        ArrayList al = new ArrayList();

        //添加元素   

        al.add("java01");   al.add("java02");   al.add("java03");

        sop(al);

        ListIterator li = al.listIterator();

        //sop("hasPrevious():"+li.hasPrevious());

        while(li.hasNext())   {    

            Object obj = li.next();

            if(obj.equals("java02"))     

            //li.add("java009");     

            li.set("java006");

        }

        while(li.hasPrevious())   {    

            sop("pre::"+li.previous());   

        }   

        //sop("hasNext():"+li.hasNext());   

        //sop("hasPrevious():"+li.hasPrevious());

        sop(al);

        /*   //在迭代过程中,准备添加或者删除元素。

          Iterator it = al.iterator();

          while(it.hasNext())   {    

            Object obj = it.next();

            if(obj.equals("java02"))     

            //al.add("java008");     

            it.remove();//将java02的引用从集合中删除了。

            sop("obj="+obj);

        }   

        sop(al);   */   

    }

}

 

使用LinkedList模拟一个堆栈或者队列数据结构。

堆栈:先进后出 如同一个杯子。

队列:先进先出 First in First out  FIFO 如同一个水管。

import java.util.*;

class DuiLie {  

    private LinkedList link;

    DuiLie()  {   

        link = new LinkedList();  

    }    

    public void myAdd(Object obj)  {   

        link.addFirst(obj);  

    }  

    public Object myGet()  {   

        return link.removeFirst();  

    }  

    public boolean isNull()  {   

        return link.isEmpty();  

    }

}

 

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())   {    

            System.out.println(dl.myGet());   

        }  

    }

}

往hashSet集合中存入自定对象:姓名和年龄相同为同一个人,重复元素。

import java.util.*;

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));

        //sop("a1:"+hs.contains(new Person("a2",12)));    

        //  hs.remove(new Person("a4",13));   

        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;  这里乘以任意一个数都可以只是让它的结果hash值不同所以乘以除1以外的数

    }

    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;  

    }

}

    |--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、  |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。    HashSet是如何保证元素    

        唯一性的呢?    是通过元素的两个方法,hashCode和equals来完成。    如果元素的HashCode值相同,才会判断equals是否为true。    如果元素的

        hashcode值不同,不会调用equals。

        注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

    |--TreeSet:Set集合的功能和Collection是一致的。    底层数据结构是二叉树。      

          保证元素唯一性的依据:     compareTo方法return 0.

          TreeSet排序的第一种方式:让元素自身具备比较性:元素需要实现Comparable接口,覆盖compareTo方法。     也种方式也成为元素的自然顺序,或者叫                                                                   做默认顺序。

          TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的。     这时就需要让集合自身具备比较性。     在集合初始化

                       时,就有了比较方式。

import java.util.*;

class HashSetDemo {  

    public static void sop(Object obj)  {   

        System.out.println(obj);  

    }  

    public static void main(String[] args)  {      

        HashSet hs = new HashSet();

        sop(hs.add("java01"));   

        sop(hs.add("java01"));   

        hs.add("java02");   hs.add("java03");   hs.add("java03");   hs.add("java04");

        Iterator it = hs.iterator();

        while(it.hasNext())   {    

            sop(it.next());   

        }  

    }

}

 

将自定义对象作为元素存到ArrayList集合中,并去除重复元素

    比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。

        思路: 1,对人描述,将数据封装进人对象。 2,定义容器,将人存入。 3,取出。

            List集合判断元素是否相同,依据是元素的equals方法。

import java.util.*; 

class Person {  

    private String name;  

    private int age;  

    Person(String name,int age)  {   

        this.name = name;   this.age = age;  

    }    

    public boolean equals(Object obj)  {

        if(!(obj instanceof Person))    

            return false;

        Person p = (Person)obj;   

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

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

     }   

     public String getName()  {   

        return name;  

    }  

    public int getAge()  {   

        return age;  

    }

}

class ArrayListTest2 {  

    public static void sop(Object obj)  {   

        System.out.println(obj);  

    }  

    public static void main(String[] args)  {   

        ArrayList al = new ArrayList();

        al.add(new Demo());   al.add(new Person("lisi01",30));    //al.add(Object obj);  

        //Object obj = new Person("lisi01",30);   

        //al.add(new Person("lisi02",32));   

        al.add(new Person("lisi02",32));   al.add(new Person("lisi04",35));   al.add(new Person("lisi03",33));   

        //al.add(new Person("lisi04",35));

        //al = singleElement(al);

        sop("remove 03 :"+al.remove(new Person("lisi03",33)));      //remove方法底层也是依赖于元素的equals方法。

        Iterator it = al.iterator();

        while(it.hasNext())   {    

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

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

        }  

    }

    public static ArrayList singleElement(ArrayList al)  {   

        //定义一个临时容器。   

        ArrayList newAl = new ArrayList();

        Iterator it = al.iterator();

        while(it.hasNext())   {    

            Object obj = it.next();

            if(!newAl.contains(obj))     

                newAl.add(obj);

        }

        return newAl;  

    }

}

去除ArrayList集合中的重复元素。

import java.util.*;

class ArrayListTest {

    public static void sop(Object obj)  {   

        System.out.println(obj);  

    }  

    public static void main(String[] args)  {   

        ArrayList al = new ArrayList();

        al.add("java01");   

        al.add("java02");   

        al.add("java01");   

        al.add("java02");   

        al.add("java01");

        //  al.add("java03");

        /*   在迭代时循环中next调用一次,就要hasNext判断一次。   

        Iterator it = al.iterator();

        while(it.hasNext())   {    

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

        }   */

        sop(al);      

        al = singleElement(al);

        sop(al);   

    }

    public static ArrayList singleElement(ArrayList al)  {   

        //定义一个临时容器。   

        ArrayList newAl = new ArrayList();

        Iterator it = al.iterator();

        while(it.hasNext())   {    

            Object obj = it.next();

            if(!newAl.contains(obj))     

                newAl.add(obj);

        }

        return newAl;  

    }

}

往TreeSet集合中存储自定义对象学生。想按照学生的年龄进行排序。排序时,当主要条件相同时,一定判断一下次要条件。

import java.util.*;

class TreeSetDemo {  

    public static void main(String[] args)  {   

        TreeSet ts = new TreeSet();

        ts.add(new Student("lisi02",22));   ts.add(new Student("lisi007",20));   ts.add(new Student("lisi09",19));   

        ts.add(new Student("lisi08",19));   //ts.add(new Student("lisi007",20));   //ts.add(new Student("lisi01",40));

        Iterator it = ts.iterator();   

        while(it.hasNext())   {    

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

            System.out.println(stu.getName()+"..."+stu.getAge());   

            sop(it.next()+"...."+it.next());//这种方式最好不要出现,当集合是奇数时容易发生空指针异常。

        }  

    }

}

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)  {

          //return 0;      

          if(!(obj instanceof Student))    

              throw new RuntimeException("不是学生对象");   

          Student s = (Student)obj;

          System.out.println(this.name+"....compareto....."+s.name);   

          if(this.age>s.age)    

              return 1;   

          if(this.age==s.age)   {    

              return this.name.compareTo(s.name);   

      }   

      return -1;    

    }

    public String getName()  {   

        return name;

    }  

    public int getAge()  {   

        return age;  

    }

}

泛型JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。

好处

1.将运行时期出现问题ClassCastException,转移到了编译时期。方便于程序员解决问题。让运行时问题减少,安全。,

 

2,避免了强制转换麻烦。

 

泛型格式:通过<   >来定义要操作的引用数据类型。

 

在使用java提供的对象时,什么时候写泛型呢?

 

通常在集合框架中很常见,只要见到<   >就要定义泛型。

 

其实<   >就是用来接收类型的。接口类型也可加泛型。

 

当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

 

 

泛型类

     

泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类

 

    型,而且类型还不确定。那么可以将泛型定义在方法上。

public <Q> void print(Q q)

{

 

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

 

}

 

特殊之处:

 

静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。

 

public  static <W> void method(W t)

{

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

}

 

泛型定义在接口上。

 

interface Inter<T>

{

  void show(T t);

}

 

泛型高级应用:涉及通配符?和泛型方法的区别。

 

ArrayList<? extends Person> al = new ArrayList<Student>();//泛型限定?        通配符。也可以理解为占位符。

 

泛型的限定:

 

extends E: 可以接收E类型或者E的子类型。上限。

 

super E: 可以接收E类型或者E的父类型。下限

 

 

 

    

posted @ 2013-05-28 19:36  zhao198627  阅读(175)  评论(0编辑  收藏  举报