黑马程序员--自学笔记--集合(其一)

来源:互联网 发布:小猫软件scratch下载 编辑:程序博客网 时间:2024/05/19 02:17

集合(其一)

-------- android培训java培训、期待与您交流! ---------

一.概述

    面向对象编程语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就需要对对象进行存储,存储对象最常用的方式就是集合和数组。而当对象具有多个且个数不确定时,就可以使用集合容器对对象进行存储以及操作。总而言之,集合是一个能存储对象的对象。
    集合的特点:
        ① 集合是用于存储对象的容器 ;
        ② 集合的长度是可变的,可以用于存储个数不确定的对象;
        ③ 集合中不能存储基本数据类型,只能够存储引用数据类型。
    集合的结构框图:


二.Collection集合

    Collection集合是集合框架的根接口,它包含了集合体系中的共性内容。在Collection下有两大子类:一类是List集合(输入输出有序,可重复);另一类是Set集合(元素不可重复)。
    集合对象的创建:
        Collectioncoll = new ArrayList() ;
        // 创建一个Collection集合容器需要使用接口的子类对其进行实例化
1.Collection集合的常用方法(集合的共性方法)
    ① 添加元素:
        (返回值:boolean) add(E e) ;    //添加一个集合元素
        (返回值:boolean) add(Collection coll);    //向一个集合中添加另一个集合的元素
    ② 删除元素:
        (返回值:boolean) remove(E e) ;    //删除集合中的一个元素(会改变集合长度)
        (返回值:boolean) removeAll(Cllectioncoll) ;    //将两个集合中相同的元素从调用者中除去
        (返回值:void) clear() ;    //清空集合中的全部内容
    ③ 判断:
        (返回值:boolean) contain(Object obj);    //判断集合中是否有某元素
        (返回值:boolean) contain(Collection coll);    //判断集合中是否包含其他集合中的全部元素
        (返回值:boolean) isEmpty() ;    //判断集合是否为空
    ④ 获取:
        (返回值:int) size() ;    //获取集合的长度(大小)
         (返回值:Iteraator) iterator() ;    //迭代取出集合中的元素(迭代器)
    ⑤ 其他方法:
        (返回值:boolean) retainAll(Collectioncoll) ;    //取出两集合的交集元素
        (返回值:Object[]) toArray() ;    //将集合转换为数组
2.迭代器对象:Iterator
    通过迭代器获取集合中的元素代码演示:
//创建并实例化Collection集合对象Collection coll = new ArrayList() ;//添加元素coll.add("a") ;coll.add("b") ;coll.add("c") ;//删除元素coll.remove("c") ;//使用迭代器遍历出集合中的所有元素Iterator it = coll.iterator() ;//使用Iterator对象的hasNext()方法判断是否已到集合的末尾while(it.hasNext()){//使用next()方法取到集合的元素System.out.println(it.next());}
  使用迭代器迭代取出集合中的元素与直接打印输出集合对象的区别是:直接打印输出集合对象是通过内部代码将集合元素转换成字符串,然后直接输出整个字符串,这样将导致难以对其中的个体进行操作。而使用迭代器可以很轻松的获取集合对象中的每一个元素,并且必要时还可以对他们分别进行处理操作。
    在以上代码中,Iterator对象it在循环结束后还继续存在于内存中,并且还可以继续使用,但这确实无意义的,并且浪费了内存空间。应此在开发中,我们常用一下代码代替:
for(Iterator it = coll.iterator();it.hasNext();){System.out.println(it.next()) ;}
注意:
    Iterator是通过内部类实现的。其对象必须依赖于集体容器。但因为每一个容器的数据结构都不相同,所以迭代器对象是在容器中进行实现的。对于使用容器者而言,具体实现过称不重要,只要通过容器获取到该实现的迭代器对象即可。总而言之,Iterator接口就是对所有的Collection容器进行元素取出的公共接口。

三.List集合

    在Collection结合下有两大子类:List集合和Set集合。其中,List集合具有有序的(此处的有序是指:存入和取出的顺序是一致的),并且元素都有索引(即角标)以及可以存入重复的元素的特点。而Set集合则是不包含重复元素的Collection集合,并且Set集合是无序的二.Collection集合(此处的有序是指:存入和取出的顺序是一致的)。所以List集合的特有方法就是可以操作角标。List集合判断元素是否相同,依据的是元素的equals()方法,其实remove()和contains()方法内部调用的就是equals()来先找到,再进行处理的。
    List对象的创建于初始化:
        List list = new ArrayList() ;    // 需要使用接口的子类对其进行实例化
1.List集合的常用方法
    ① 添加元素:
        (返回值类型:void) add(index,element) ;    // 在指定的index角标出添加element元素
        (返回值类型:void) add(index,collection) ;    // 在指定的index角标出添加collection集合中的元素
    ② 删除元素:
        (返回值类型:Object) remove(index) ;    // 删除List集合中的元素,并且返回被删除的元素内容
    ③ 修改元素:
        (返回值类型:Object) set(index,element) ;    
        // 修改指定的index角标元素,将其修改为element,并且返回被修改的元素内容
    ④ 获取:
        (返回值类型: Object) get(index) ;    
        // 获取指定index角标的元素内容,这是List集合特有的取出方式。但是,如果index超出集合长度范围,将会出现角标越界异常
        (返回值类型:int) indexOf(Object) ;    
        // 从前往后查找指定的元素内容,如果找到返回所指定元素在集合中的位置,否则返回-1
        (返回值类型:int) lastIndexOf(Object) ; 
        // 从后往前查找指定的元素内容,如果找到返回所指定元素在集合中的位置,否则返回-1
        (返回值类型:List) subList(from,to) ;
        // 获取原列表的子集(即子列表),from和to都是角标,此子列表包含from角标的元素但是不包含to角标的元素
2.ListIterator接口
    在使用Iterator接口对集合中的元素进行迭代的时候,不要对原有集合进行操作,很容易就会出现异常。此时可以通过Iterator接口的一个子接口ListIterator接口来完成。该子接口中含有增删方法,并且可以在迭代集合时对元素进行更多的操作。该子接口的获取方法只有List中才有,具体方法为:list.ListIterator()。
3.List接口的实现子类--Vector
    Vector是实现List接口的一种方式,但在JDK1.5之后已经比较少用。它的内部结构是一个长度可变的数组数据结构(容器默认大小是10,当超过时按100%增长==>20),并且其使用过程是同步的。但是此实现类增删查询效率都很慢。
    Vector集合获取元素的方法比较特殊,它利用到了枚举,不过现在基本上已经被Iterator接口代替。
    范例:   
<span style="font-family:KaiTi_GB2312;">//创建并实例化Vector对象Vector v = new Vector() ;//通过Vector对象获取集合元素的枚举值Enumeration en = v.elements() ;//遍历出所有的元素while(en.hasMoreElements()){System.out.println(en.nextElement()) ;}</span>
4.List接口的实现子类--LinkedList
    LinkedList是实现List接口的一种方式,它的内部结构是链表数据结构,其使用过程是不同步的,但是使用此子类在集合中增删元素速率高。
    在JDK1.5之前,LinkedList集合特有的方增删方法为:
        ① addFirst()/addLast() ;    //在第一个位置/最后一个位置增加元素
        ② getFirst()/getLast() ;    //获取第一个位置/最后一个位置的元素,但不删除所获取到的元素
        ③ removeFirst()/removeLast() ;    
        //移除第一个位置/最后一个位置的元素,并返回所移除的对象。(如果此列表为空将会抛出NoSuchElementException异常)
    在JDK1.5之后,LinkdedList集合中特有的增删方法为:
        ① peekFirst()/peekLast() ;    //在第一个位置/最后一个位置增加元素
        ② pollFirst()/pollLast() ;    
        //移除第一个位置/最后一个位置的元素,并返回所移除的对象。(如果此列表为空,返回null,但不抛出异常)
通过以下利用LinkedList集合模拟的队列和栈容器,来深入了解LinkedLIst集合的增删方法:(注意:注释中包含注意点和知识点)
模拟一个队列容器:
<span style="font-family:KaiTi_GB2312;">package cn.itzixue.linkeedlist;import java.util.LinkedList;//模拟一个队列容器,通过LinkedLIst集合类实现----队列的特点:后进先出public class ImitateQueue {//创建一个LinkedList集合对象private LinkedList list = null ;public ImitateQueue(){//在该自定义队列容器对象产生时实例化LinkedLIst集合对象list = new LinkedList() ;}//利用LinkedLIst集合对象的addLast()方法从最后一位添加数据public void myAll(Object obj){list.addLast(obj) ;}//利用LinkedLIst集合对象的removeLast()方法从第一位获取并移除数据public Object myGet(){return list.removeFirst() ;}//利用LinkedLIst集合对象的isEmpty()方法判断集合是否为空public boolean IsNull(){return list.isEmpty() ;}}</span>
模拟一个栈容器:
<span style="font-family:KaiTi_GB2312;">package cn.itzixue.linkeedlist;import java.util.LinkedList;//模拟一个栈容器,通过LinkedLIst集合类实现----栈的特点:先进后出public class ImitateInn {//创建一个LinkedList集合对象private LinkedList list = null ;public ImitateInn(){//在该自定义栈容器对象产生时实例化LinkedLIst集合对象list = new LinkedList() ;}//利用LinkedLIst集合对象的addLast()方法从最后一位添加数据public void myAll(Object obj){list.addLast(obj) ;}//利用LinkedLIst集合对象的removeLast()方法从最后一位获取并移除数据public Object myGet(){return list.removeLast() ;}//利用LinkedLIst集合对象的isEmpty()方法判断集合是否为空public boolean IsNull(){return list.isEmpty() ;}}</span>
5.List接口的实现子类--ArrayList
    ArrayList集合内部是一个大小可变的数组数据结构(容器默认大小是10,当超过时按50%增长==>15),它是用来替代Vector的,但是它使用时的线程是不同步的,但是可以通过多种方式(例如:增加锁)来实现多线程的同步。使用此集合能够使得在集合中查询元素的速率变快。
范例:
ArrayList a = new ArrayList() ;a.add(new Person()) ;    // 此处接收的是Object对象Iterator it = a.iterator() ;while(it.hasNext()){Person p = (Person)it.next() ;    // "."的优先级是很高的,所以当直接使用(Person)it.next().getname()获取Person对象的姓名时,将无法获得,因<span style="white-space:pre"></span>为向下转型为Person的操作的优先级低于"."的优先级,所以这样的方式将无法调用到Person对象的方法。要想更好的操<span style="white-space:pre"></span>作Person<span style="white-space:pre"></span>对象,应该先通过一个Person对象来获取集合中的对象。,在对Person对象进行操作}

四.Set集合

    Set集合中的元素不可重复,且是无序的(此处的无序是指:存入取出顺序不一致)。除此之外,Set接口中的方法于Collection接口中的方法一致,但是Set集合只能通过Iterator接口获取其中的元素。Set接口有两个实现的子类:其中一个是:HashSet;另外一个是:TreeSet。
1.HashSet集合
    HashSet集合内部的数据结构是Hash表。它是先将所要存入的对象通过hasCode()计算出其hash值,然后判断其位置(Hash值)是否相同,再通过equals()方法判断其内容是否有重复,确定无重复之后再进行存储。如果hash值不同,将无需再判断其内容。当hash值出现相同时,将会继续判断其内容是否相同。如果内容相同将不进行存储,但如果内容不同时,将会出现hash冲突。此时Set集合将会在此hash值的位置延生出另一个位置进行元素存储,常用方法有两种。一种是后延(向后延长数组);另一种是串联(在相同位置增加一个外延位置--可能重新计算出现hash冲突位置的内容的hash值)。
范例:
    Person类是继承Object类的,它使用的是Object类中的hashCode()方法和equals()方法,其中,equals()方法是比较地址的。当每创建一个Person对象时,其地址将会不同,所以系统将会判断出不同。因此,在自定义Person中必须覆盖Object类中的hashCode()方法和equals()方法。
常见代码演示:
public class Person {……    ……//覆盖Object类中的hashCode()方法public int hasCode(){return name.hashCode() + age*13 ;}//覆盖Object类中的equals()方法public boolean equals(Object obj){//判断地址,防止传入相同地址的对象if(this==obj)return true ;//健壮性判断,防止乱串对象if(!(obj instanceof Person))throw new ClassCastExceotion("类型错误") ;Person p = (Person)obj ;return this.name.equals(p.name)&&this.age=p.age ;<span style="font-family:KaiTi_GB2312;">}}</span>
    顺便提一下,ArrayList集合中的contains(Object o),依据的是对象的equals()方法。同理,remove()方法也是通过判断equals()方法进行判断,返回boolean值。在List体系中,ArrayList通过判断equals()方法,而LinkedList通过判断hashCode()方法和equals()方法。
    Set集合体系中的元素存取都是无序的,如果要想让其存取有序,可以使用HashSet集合的子类LinkedHashSet集合,即可实现有序功能。
    总而言之,List集合体系和Set集合体系最大的区别是:元素为不唯一。
2.TreeSet集合
    TreeSet集合具有Set集合的全部特性以及全部方法,在此基础上,TreeSet集合可以对Set集合中的元素进行排序。使用此集合类时,其线程是不同步的。它的底层数据结构是二叉树,存放到此集合中的对象要么实现Comparable接口(Comparable接口:强行对实现他的每个类的对象进行整体排序--自然排序),要么可以在构造TreeSet对象的时候传递一个实现了Comparator接口的比较器对象。
1.TreeSet集合实现对元素排序的方式一
    TreeSet集合对元素进行排序,是先让元素自身具备比较功能。为此,该集合中的元素对象就需要实现Comparable接口,并将其中的compareTo()方法进行覆盖。而在Set集合中,判断元素唯一性的方式,就是根据比较方法的返回结果是正(大于)、是负(小于)、是零(相同)。
注意:字符串本身应实现了Comparable接口。
    


0 0
原创粉丝点击