黑马程序员 - 集合


集合类:
 对象用于封装特有数据,对象如果个数众多且需要存储,就使用集合容器进行存储。
集合的特点:
 1.用于存储对象的容器。
 2.集合的长度是可变的。
 3.集合中不可以存储基本数据。
集合容器因为内部的数据结构不同,有多种具体容器.
不断向上抽取,就形成类集合框架Collection.
1.添加
 boolean add(Object obj)
 boolean addAll(Collection coll)
2.删除
 boolean remove(Object obj)
 boolean removeAll(Object obj)
 void clear();
3.判断
 boolean contains(Object obj)
 boolean comtainsAll(Object obj)
 boolean isEmpty();
4.获取
 int size();
集合中引用的都是地址。
迭代器:不同集合数据结构不同,所以取出动作细节也不同,但都具备共性内容:判断和取出。
     所以将共性内容抽取出来形成迭代器。
     所以迭代器就是集合取出元素的方式。
     在迭代器循环中,允许对集合进行删除操作,不允许进行增加操作。
步骤:1.用集合的iterator(),获取一个迭代器。
  2.用迭代器的next()方法获取下一个元素。
  3.用迭代器的hasNext()判断是否还有下个元素。

以下代码演示Collection的基本操作

import java.util.*;
class  ACollectionDemo{
    public static void main(String[] args) {
        //创建一个集合容器,使用Collection接口的子类,ArrayList
        ArrayList a1 = new ArrayList();   //定义集合
        ArrayList a2 = new ArrayList();
        //1.添加元素
        a1.add("java01");  //a1.add(Object obj))
        a1.add("java02");
        a1.add("java03");
        a1.add("java04");
        
        a2.add("java01");  //a2.add(Object obj))
        Iterator it = a1.iterator();                        //获取迭代器,用于取出容器a1中的元素
        while (it.hasNext()){                               // it.hasNext  判断容器中是否还有下个元素
            sop(it.next());                                 //获取容器中的下个元素
        }
        //打印集合
        sop("集合a1:"+a1+"   集合a2:"+a2);
        //2.获取个数,集合长度。
        sop("a1的size:"+a1.size());
        //3.删除元素。
        a1.remove("java02");
        //al.clear();    清空集合。
        sop(a1);
        //4.判断元素
        sop("java03是否在集合内:"+a1.contains("java03"));
        sop("集合是否为空:"+a1.isEmpty());
        //5.操作
        a1.retainAll(a2);  //取a1和a2交集赋予a1
        sop("集合a1:"+a1);
        //a1.removeAll(a2);  //从a1中删除a1与a2的交集
        //sop("集合a1:"+a1);
    }
    public static void sop(Object obj){    //静态函数
        System.out.println(obj);
    }
}

运行结果

集合类的主要分类为List、Set、Map

List:元素有序,元素可以重复
   |--ArrayList:底层的数据结构使用的数组结构 特点:查询速度快,但是但增删慢,线程不同步。
   |--LinkList:底层使用的链表结构 特点:查询慢,但增删快
   |--Vector:底层使用的数组结构,线程同步 被ArrayList替换 特点:增删,查询都很慢
List特有方法:(凡可以操作角标的方法都是该体系的特与方法)
增:
add(index,element)
addAll(index,Collection)
删;
remove(index);
改:
set(index,element);
查:
get(index);
subList(from,to);
listIterator();
indexOf(element);
List集合特有的迭代器:ListIterator是Iterator的子接口,可以在迭代中对集合进行增、删、改,和倒序遍历操作。
在迭代过程中,不可以通过集合对象的方法操作集合中的元素。
因为会发生ConcurrentModificationException异常。
ArrayList因为底层的数据结构使用的数组结构,所以可以用循环对其进行操作。
以下代码演示ArrayList的常用方法

import java.util.*;
class BArrayList {
    public static void main(String[] args){
        ArrayList a1 = new ArrayList();  //定义集合
        a1.add("java01");                //添加元素
        a1.add("java02");
        a1.add("java03");
        a1.add("java04");
        sop("原集合:"+a1);
        a1.add(1,"java09");       //在指定位置添加元素
        sop("添加元素后集合a1:"+a1);
        a1.remove(2);             //在指定位置删除元素
        sop("删除指定元素后集合a1:"+a1);
        a1.set(2,"java07");       //更改指定位置元素
        sop("更改2号位置元素后集合a1:"+a1);
        sop("get(0):"+a1.get(0)); //获取指定位置元素
        for (int x=0;x<a1.size();x++){        //通过for循环获取所有元素
            sop("a1("+x+"):"+a1.get(x));
        }
        sop("--------------------------");
        for (Iterator it=a1.iterator();it.hasNext() ; ){//通过迭代器方式获取所有元素
            sop(it.next());
        }
        sop("index="+a1.indexOf("java01"));
        List sub = a1.subList(1,3);       //获取子集合包含开始指针,不包含结束指针。
        sop("sub="+sub);
        sop("--------------------------");
        sop("原集合:"+a1);
        ListIterator li = a1.listIterator();
        while (li.hasNext()){            //通过循环将集合中的"java09"改为"java006"
            Object obj = li.next();
            if (obj.equals("java09"))    //判断取出的元素是否为java09
            {
                li.set("java006");       //将元素改为java006
            }
        }
        sop(a1);
    }
    public static void sop(Object obj){   //定义打印方法
        System.out.println(obj);
    }
}

运行结果

 ArrayList集合的简单应用

需求:

去除ArrayList集合中的重复元素
思路:
定义一个临时容器,将ArrayList中的每个元素存入临时容器中
每次存入元素时先判断临时容器中是否有该元素。
步骤:
1.导包,在主函数中创建原容器并存入元素
2.创建一个取单的对象,在其中创建取单的方法
3.在主函数中调用对象中取单方法(把原容器传入调用的对象)
4.将取单完成的新容器传给原容器,并打印

import java.util.*;
public class BArrayListTest{
    public static void main(String[] args) {
        ArrayList a1 = new ArrayList ();  //定义原容器,并向里面存入元素
        a1.add("java01");
        a1.add("java02");
        a1.add("java03");
        a1.add("java01");
        a1.add("java02");
        a1.add("java03");
        a1.add("java04");
        a1.add("java05");
        a1.add("java01");
        sopCH.sop("原集合"+a1);
        a1 = ArrayTool.SingleElement(a1); //调用编写的去重复元素静态方法
        sopCH.sop("去除重复元素后集合:"+a1);
    }
}
class sop{
    public static void sop(Object obj){
        System.out.println(obj);
    }
}
class ArrayTool{                              //定义一个工具类
    static ArrayList a2 = new ArrayList ();   //定义一个新集合a2用于存储去掉重复元素后的集合
    public static ArrayList SingleElement(ArrayList  a1){ //定义去重复元素的静态方法(方便通过类名调用)
        for (int x=0;x<a1.size() ;x++ ){      //通过for循环遍历集合a1
            if (!(a2.contains(a1.get(x))))    //判断a2中是否存在该元素,没有就将该元素存入a2
                a2.add(a1.get(x));
        }
        return a2;                            //返回a2
    }
}

运行结果

Set:

元素无序而且不重复;包含HashSet和TreeSet
  HashSet:底层数据结构是哈希表;
    HashSet是如何保证元素的唯一性?
    是通过hashCode和equals来完成。
    如果元素的HashCode值相同,就调用equals方法判断内容(此时equals需要复写)
    如果元素的HashCode值不同,则元素不同,不会调用equals。
    所以一般都会复写HashCode。
    注意:对于判断元素是否存在以及删除等操作,均是通过判断元素的hashCode和equals方法。
    set集合的功能与Collection一致

  TreeSet:可以对Set集合中的元素进行排序。
    底层数据结构是二叉树。
  保证元是唯一性的依据是:
  ompareTo方法 return 0, -1,1

TreeSet排序:
  方法一: 让元素自身具备比较性。此方法是需要元素实现Comparable接口。(自然顺序)
  方法二: 当元素自身不具备比较性,或具备的比较性不是所需的
      这时需要让容器自身具备比较性
      定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
      当两种排序都存在时,以比较器为主。

以下代码演示TreeSet的两种比较方式

import java.util.*;
class PersonTS implements Comparable{           //定义类实现Comparable接口,使其具有比较性
    private    String name;                        //定义成员变量
    private int age;
    PersonTS(String name,int age){              //构造函数
        this.name=name;
        this.age=age;
    }
    public int compareTo(Object obj){           //覆写compareTo方法,定义排序规则为先按年龄再按姓名排序
        if (!(obj instanceof PersonTS))         //判断对比对象是否为Person
            throw new RuntimeException("不是Person对象");
        PersonTS p = (PersonTS)obj;                //向下转型为Person
        sop.sop(this.name+":compareto:"+p.name);//显示具体对比的元素
        if (this.age>p.age)                     //判断年龄大小
            return 1;
        else if(this.age==p.age)                //年龄相同时判断姓名
            return this.name.compareTo(p.name);
        else
            return -1;
    }
    public String getName(){                    //定义获取姓名方法
        return name;
    }
    public int getAge(){                        //定义获取年龄方法
        return age;
    }
}
public class CTreeSet{
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();             //定义ts集合并存入元素,用以演示按元素本身的排序规则排序
        ts.add(new PersonTS("a1",11));
        ts.add(new PersonTS("a2",12));
        ts.add(new PersonTS("a3",13));
        ts.add(new PersonTS("b2",12));
        ts.add(new PersonTS("b2",12));
        
        TreeSet ts2 = new TreeSet(new MyComparePerson());   //定义ts2集合并存入元素,并将比较器作为参数传给集合
        ts2.add(new PersonTS("a1",11));               //用以演示按定义的比较器的排序规则排序
        ts2.add(new PersonTS("a4",12));
        ts2.add(new PersonTS("a1",13));
        ts2.add(new PersonTS("b2",12));
        ts2.add(new PersonTS("b2",12));
        
        for (Iterator it=ts.iterator();it.hasNext() ; ){
            PersonTS p = (PersonTS)it.next();
            sop.sop("元素本身排序方式"+p.getName()+":"+p.getAge());
        } 
        for (Iterator it=ts2.iterator();it.hasNext() ; ){
            PersonTS p = (PersonTS)it.next();
            sop.sop("自定义比较器排序方式"+p.getName()+":"+p.getAge());
        }         
    }
}
class MyComparePerson implements Comparator{                  //定义类实现Comparator,使其具备比较器的功能
    public int compare(Object o1,Object o2){            //覆写compare方法,定义先按照姓名再按照年龄排序
        if (!(o1 instanceof PersonTS)&&!(o2 instanceof PersonTS))//判断对比对象是否为Person
            throw new RuntimeException("不是Person对象");
        PersonTS p1= (PersonTS)o1;                      //将对比元素向下转型为PersonTS
        PersonTS p2= (PersonTS)o2;
        int num = p1.getName().compareTo(p2.getName()); //先按照姓名排序
        if(num==0){                                     //判断姓名是否相同,如果相同再对比其年龄
            if(p1.getAge() > p2.getAge())
                return 1;
            else if (p1.getAge() == p2.getAge())
                return 0;
            else
                return -1;
        }
        else
            return num;
    }
}

运行结果

特殊的集合类Map

Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1.添加
put(K key,V value)
putAll(Map<? extends K,? extends V> m )
2.删除
clear()
remove(Object key)
3.判断
containValue(Object value)
containKey(Object key)
isEmpty()
4.获取
get(Object key)
size()
value()
entrySet()
Map
|--HashTable<K,T>:底层是哈希表结构,不可以存入null键null值,该集合是线程同步的。
|--HashMap:底层是哈希表数据结构,无序,允许使用null值和null键,该集合是线程不同步的。
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给集合中的键排序。

和Set很像,其实Set底层就是调用的Map集合。

map集合的两种取出方式:
1.keySet: Set<k> keySet
将map中所有的键存入到Set集合,应为Set具备迭代器,所以可以用迭代方式取出所有的键
再根据get方法,获取每一个键对应的值。
Map集合的取出原理:将map集合转为Set集合,通过Set集合迭代器取出元素
2.entrySet: Set<Map.Entry<k,v>> entrySet
将map集合中的映射关系存储到Set集合中。

演示代码
需求:
学生属性: 姓名,年龄
注意:姓名和年龄相同的视为同一学生
保证学生的唯一性
1.描述学生
2.定义map容器,将学生作为键,地址作为值,存入。
3.获取map集合的元素

import java.util.*;
class Student implements Comparable<Student>{      //定义类实现Comparable接口,使其具备比较性
    private String name;                           //定义成员变量
    private int age;
    Student(String name,int age){                  //定义带参数构造函数
        this.name = name;
        this.age = age;
    }
    public int hashCode(){                         //覆写hashCode方法,自定义获取hashcode方式
        return name.hashCode()+age*13;
    }
    public boolean equals(Object obj){             //自定义比较类型
        if(!(obj instanceof Student))              //判断对比对象是否是Student
            throw new ClassCastException("类型不匹配");
        Student s = (Student)obj;                  //将对比对象向下转型为Student
        sop.sop(this.name+":equals:"+s.name);     
        return this.name.equals(s.name) && this.age==(s.age);//定义相同条件为姓名年龄均相同
    }
    public int compareTo(Student s){               //默认排序方式为按照年龄排序    
        int num = new Integer(this.age).compareTo(new Integer(s.age));
        if(num == 0)
            return this.name.compareTo(s.name);
        else
            return num;
    }
        public String getName(){                   //定义获取姓名方法
        return name;
    }
    public int getAge(){                           //定义获取年龄方法
        return age;
    }
}

public class DmapDemo{
    public static void main(String[] args){
        HashMap<Student,String> hm = new HashMap<Student,String>();
        hm.put(new Student("mike1",12),"shanghai");
        hm.put(new Student("lili1",12),"shanghai");
        hm.put(new Student("mike2",12),"chengdu");
        hm.put(new Student("lili2",11),"chengdu");
        hm.put(new Student("mike3",12),"beijing");
        hm.put(new Student("lili3",13),"beijing");

        TreeMap<Student,String> tm = new TreeMap<Student,String>(/*new MyCompare()*/);
        tm.put(new Student("mike1",12),"shanghai");
        tm.put(new Student("lili1",12),"shanghai");
        tm.put(new Student("mike2",11),"chengdu");
        tm.put(new Student("lili2",11),"chengdu");
        tm.put(new Student("mike3",12),"beijing");
        tm.put(new Student("lili3",13),"beijing");
        
        Set<Student> keySet = hm.keySet();
        Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
        sop.sop("HashMap的键值对为无序排列:");
        for (Iterator <Student>it = keySet.iterator(); it.hasNext();){    
            Student key = it.next();
            sop.sop(key.getName()+":"+key.getAge()+"....."+hm.get(key));
        }
        sop.sop("TreeMap的键值对按照自定规则排序:");
        for (Iterator <Map.Entry<Student,String>> it = entrySet.iterator(); it.hasNext();){    
            Map.Entry key = it.next();
            Student s = (Student)key.getKey();
            sop.sop(s.getName()+":"+s.getAge()+"....."+key.getValue()); 
        }
    }
}
class MyCompareStu implements Comparator<Student>{//定义按照学生姓名排序的比较器。
    public int compare(Student s1,Student s2){
        int num = s1.getName().compareTo(s2.getName());
        if(num==0)
            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
        else
            return num;
    }
}

运行结果

posted @ 2015-08-20 15:08  koibiki  阅读(141)  评论(0编辑  收藏  举报