黑马程序员——Java集合框架—概述

来源:互联网 发布:内衣品牌推荐 知乎 编辑:程序博客网 时间:2024/06/08 04:22
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


1、Java集合框架类结构图

下面是java集合框架的类结构图(包括接口、抽象类、遗留构件,不包括Queue的实现,图片来自网络):



上面的图可能比较复杂,下面再贴2张简化图(图片来自网络):



从上面的图片中可以看出,java的集合类主要由2个接口派生而出:Collection和Map,这2个接口是java集合框架的根接口。

本文仅仅简单介绍一下Collection接口,关于Map接口将在以后的文章中介绍。


2、Collection接口简要分析

从上面的类结构图可以看出,Collection接口是Set、Queue、List的父接口,所以在Collection接口中定义的是3个子接口共有的方法。

List和Set、Queue很大的一个不同点是,List是有索引的,它可以通过索引来获取对象(即获取对象时需要传一个index参数),但是另外2个集合没有索引(获取对象时传入一个对象),所以在Collection接口中没有定义获取集合中元素的方法。

3个集合添加元素的方式是相同的,都需要传入被添加的对象,所以在Collection接口中定义了添加元素的方法。


下面看一下Collection接口的源码:

package java.util;public interface Collection<E> extends Iterable<E> {//返回集合里元素的个数    int size();//返回集合是否为空。当集合长度为0时返回true,否则返回false。    boolean isEmpty();//返回集合里是否包含指定元素    boolean contains(Object o);//返回一个Iterator对象,用于迭代集合里的元素    Iterator<E> iterator();//把集合变成一个数组并返回    Object[] toArray();//    <T> T[] toArray(T[] a);//向集合里添加一个元素,如果集合对象被该添加操作改变了,则返回true。    boolean add(E e);//删除集合中的指定元素,当集合中包含一个或多个指定元素时,这些元素都会被删除。如果成功删除返回true,否则返回false。    boolean remove(Object o);//返回当前集合中是否包含指定集合c中的所有元素    boolean containsAll(Collection<?> c);//把集合c里的所有元素添加到当前集合中    boolean addAll(Collection<? extends E> c);//把指定集合c中包含的元素从当前集合中删除    boolean removeAll(Collection<?> c);//将当前集合的内容变成当前集合与指定集合c的交集    boolean retainAll(Collection<?> c);//清除集合里的所有元素,将集合长度变为0。    void clear();    boolean equals(Object o);        int hashCode();}

从源码可以看出Collection是一个接口,并且继承了Iterable接口。iterable可以翻译为可迭代,可以理解为凡是实现了Itreable接口的类都是可以迭代的。

下面看一下Iterable接口的源码:

package java.lang;import java.util.Iterator;public interface Iterable<T> {    Iterator<T> iterator();}

从上面的源码可以看出,Iteable接口中只有一个方法,该方法返回一个迭代器Iterator的实例。

下面看一下Iterator接口的源码:

package java.util;public interface Iterator<E> {//被迭代的集合中是否还有下一个元素    boolean hasNext();//返回下一个元素    E next();//删除集合即上一次next方法返回的元素    void remove();}

从上面的源码可以看出,Iterator实际上也是一个接口。因为接口是不能创建实例的,所以Iterable的iterator方法返回的肯定是Iterator接口子类的实例。

那Iterable的子类是在哪里定义的呢??

下面我们以ArrayList为例稍微说一下Iterable接口的子类。

我们可以从ArrayList类的源代码中看到如下代码:

package java.util;public class ArrayList<E> extends AbstractList<E>        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{//这是从Collection接口继承得到的iterator方法public Iterator<E> iterator() {//下面的代码返回了一个Itr类的实例        return new Itr();    }    //私有内部类Itr,实现了Iterable接口    private class Itr implements Iterator<E> {        int cursor;       // index of next element to return        int lastRet = -1; // index of last element returned; -1 if no such        int expectedModCount = modCount;        public boolean hasNext() {            return cursor != size;        }        @SuppressWarnings("unchecked")        public E next() {            checkForComodification();            int i = cursor;            if (i >= size)                throw new NoSuchElementException();            Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length)                throw new ConcurrentModificationException();            cursor = i + 1;            return (E) elementData[lastRet = i];        }        public void remove() {            if (lastRet < 0)                throw new IllegalStateException();            checkForComodification();            try {                ArrayList.this.remove(lastRet);                cursor = lastRet;                lastRet = -1;                expectedModCount = modCount;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }        final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }    }}

从上面代码可以看出,ArrayList的iterator方法返回的是一个内部类Itr的实例,该内部类实现了Iterator接口。

不仅仅是ArrayList,你可以从其他的集合类中找到类似的代码。

最后看一个使用Iterator的小例子,及几个需要注意的点:

package org.lgy.study.collection;import java.util.Collection;import java.util.ArrayList;import java.util.Iterator;public class IteratorTest{public static void main(String[] args){Collection c = new ArrayList();/*代码片段1:Iterator对象的next方法返回的是集合对象中元素的值。如果集合中的元素为基本数据类型,则返回基本数据类型对应的值;如果是引用类型,则返回对应的引用(也可以理解为元素指向的地址),此时如果通过获得的引用变量修改了所引用的对象,则导致集合元素也被修改。*/c.add(new Name("Ying", "Tony"));System.out.println(c);Iterator iterator = c.iterator();while(iterator.hasNext()){Name name = (Name)iterator.next();name.setFirstName("li");name.setLastName("guoying");}System.out.println(c + "\n");/*代码片段2:当使用Iterator迭代集合时,不能在迭代语句内部使用集合本身的方法删除、添加集合元素,否则引发ConcurrentModificationException异常。(可以修改元素,不抛出异常,但不建议直接修改)如果需要在迭代的过程中删除元素,应该使用Iterator的remove方法。*/c.clear();c.add("111");c.add("222");c.add("333");Iterator iterator2 = c.iterator();while(iterator2.hasNext()){Object obj = iterator2.next();System.out.print(obj + "  ");//下面代码是在添加集合元素时引发异常。//无论在哪里添加新元素,都会引发异常。if(obj.equals("333"))c.add(0.5);/*//下面代码是在删除集合元素时引发异常。//当删除111、333时会引发异常,在删除222时不会引发异常,但依然不建议在//迭代元素的同时使用集合本身的方法删除集合元素。if(obj.equals("222"))c.remove(obj);*/}/*下面代码使用for each迭代集合*/c.clear();c.add("111");c.add("222");c.add("333");for(Object obj : c){System.out.print(obj + "  ");}System.out.println();/*迭代集合时,for each 返回的是集合元素的值*/c.clear();c.add(new Name("li", "guoying"));for(Object obj : c){Name name = (Name)obj;System.out.print(name);name.setFirstName("Tony");name.setLastName("Ying");}System.out.println("\n" + c);/*迭代集合的过程中,不能删除、添加元素,否则引发ConcurrentModifactionException异常具体请参见使用Iterator迭代时的情况*/c.add("111");c.add("222");c.add("333");for(Object obj : c){System.out.print(obj + "  ");if(obj.equals("333"))c.remove(obj);}}}class Name{private String firstName;private String lastName;public Name(String firstName, String lastName){this.firstName = firstName;this.lastName = lastName;}public void setFirstName(String firstName){this.firstName = firstName;}public void setLastName(String lastName){this.lastName = lastName;}public String toString(){return firstName + lastName;}}



3、AbstraceCollection抽象类简要分析

Collection是一个接口,它有一个名为AbstractCollection的实现类(抽象类)。下面我们看一下AbstractCollection的源码:

package java.util;public abstract class AbstractCollection<E> implements Collection<E> {    protected AbstractCollection() {    }//抽象方法,没有实现    public abstract Iterator<E> iterator();//抽象方法,没有实现    public abstract int size();    public boolean isEmpty() {        //已实现    }    public boolean contains(Object o) {        //已实现    }    public Object[] toArray() {        //已实现    }    public <T> T[] toArray(T[] a) {        //已实现    }    public boolean add(E e) {        //已实现    }    public boolean remove(Object o) {        //已实现    }    public boolean containsAll(Collection<?> c) {        //已实现    }    public boolean addAll(Collection<? extends E> c) {        //已实现    }    public boolean removeAll(Collection<?> c) {        //已实现    }    public boolean retainAll(Collection<?> c) {        //已实现    }    public void clear() {        //已实现    }//重写Object中的toString方法    public String toString() {        //已实现    }//equals和hashCode方法由Object类实现了//boolean equals(Object o);    //int hashCode();}

从源码可以看出,AbstractCollection抽象类中只有2个抽象方法(iterator、size),2个方法(toString、hashCode)由Object类实现,其余11个从Collection接口继承的方法全部提供了实现。

集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用),而集合里只能保存对象(实际上保存的是对象的引用),甚至可以在一个集合中保存不同类型的对象。

关于List、 Set、Map等后面会分类介绍。

0 0
原创粉丝点击