Java集合总体框架

Java 集合系列01之 总体框架

java集合框架
在这里插入图片描述
Java集合工具包的位置是java.util.*

Collection接口:

是高度抽象出来的集合,包含了集合的基本操作和属性
在这里插入图片描述

Collection包含了List和Set两大分支

  1. List: List是一个有序的队列,每一个元素都有它的索引,第一个元素的索引值是0;List的实现类有:
    ① LinkedList
    ② ArrayList
    ③ Vector
    ④ Stack

  2. Set:Set是一个不允许有重复元素的集合;Set的实现类有:
    ① HashSet:依赖于HashMap,是通过HashMap实现的
    ② TreeSet:依赖于TreeMap,是通过TreeMap实现的

Iterable接口

Collection 继承了 Iterable< E > 接口,Iterable 接口内只有一个 iterator 方法,返回一个 Iterator 迭代器:

public interface Iterable<T> {

    /**
    * Returns an {@link Iterator} for the elements in this object.
    *
    * @return An {@code Iterator} instance.
    */
    Iterator<T> iterator();
}

Iterator接口

它是遍历集合的工具,即我们通常通过Iterator迭代器来遍历集合。我们说Collection依赖于Iterator,是因为Collection的实现类都要实现iterator()函数,返回一个Iterator对象。

通过Iterable定义的iterator()接口可以拿到iterator

List接口

在这里插入图片描述
一个 List 是一个元素有序的、可以重复、可以为 null 的集合(有时候我们也叫它“序列”)。
Java 集合框架中最常使用的几种 List 实现类是 ArrayList,LinkedList 和 Vector。在各种 List 中,最好的做法是以 ArrayList 作为默认选择。 当插入、删除频繁时,使用 LinkedList,Vector 总是比 ArrayList 慢,所以要尽量避免使用它

在List中除了继承Collection中的一些方法,还提供了以下操作
① 位置相关:List 和 数组一样,都是从 0 开始,我们可以根据元素在 list 中的位置进行操作,比如说
get, set, add, addAll, remove;

② 搜索:从 list 中查找某个对象的位置,比如 indexOf, lastIndexOf;

③ 迭代:使用 Iterator 的拓展版迭代器 ListIterator 进行迭代操作;

④ 范围性操作:使用 subList 方法对 list 进行任意范围的操作

**其中在List接口中定以了 ListIterator listIterator()方法用来返回一个listIterator(),listIterator()更强大它可以双向遍历,同时还允许进行add,set,remove等操作 **
在这里插入图片描述

AbstractCollection接口

在这里插入图片描述
AbstractCollection是对Collection接口的直接实现类(是一个抽象类),Collection下的大多数子类都要继承AbstractCollection,他实现了一些方法,也定义了一些抽象方法留给子类实现

抽象方法

  1. public abstract Iterator<E> iterator();
  2. public abstract int size();

注意:
在AbstractCollection中不支持添加单个元素,所以直接调用add(E)方法会报错,如果子类是可添加的数据结构,需要自己实现这些方法

public boolean add(E object) {
    throw new UnsupportedOperationException();
}

这样设计主要是因为如果你想修改一个不可变的集合时,抛出 UnsupportedOperationException 是标准的行为,比如 当你用 Collections.unmodifiableXXX() 方法对某个集合进行处理后,再调用这个集合的 修改方法(add,remove,set…),都会报这个错;

AbstractList

在这里插入图片描述
AbstractList 继承自 AbstractCollection 抽象类,实现了 List 接口 ,是 ArrayList 和 AbstractSequentiaList 的父类。它实现了 List 的一些位置相关操作,是第一个实现随机访问方法的集合类,但不支持添加和替换。还是默认不支持add(),set(),remove()操作

在AbstractList 中实现了ListIterator和Iterator

1. Iterator的实现

private class Itr implements Iterator<E> {
        /**
         * Index of element to be returned by subsequent call to next.
         */
        int cursor = 0;

        /**
         * Index of element returned by most recent call to next or
         * previous.  Reset to -1 if this element is deleted by a call
         * to remove.
         */
        int lastRet = -1;

        /**
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;//为的是remove操作
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

需要注意的地方是:
① 如果没有执行过next(), 直接remove()会抛异常。因为没对象让你移除。然后,每次移除完成之后,lastRet = -1 , 又回到了,next()之前的状态。也就意味着。每次 remove()之前都必须调用一次next(),否则报错。

② 因为迭代器的remove方法会同步expectedModCount和modCount所以不会fast-fail

2. ListIterator的实现

private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() {
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i);
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

在ListIterator和Iterator中的next() 和remove() 等方法都会调用AbstractList的get()和remove()方法,而这些方法又会在子类中进行重写实现,也就是说,子类调用迭代器后迭代器里实际调用的是自己的get()和remove()方法

Map接口

Map是一个映射接口,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。

AbstractMap是个抽象类,实现了Map接口的大部分API,① HashMap,② TreeMap,③ WeakHashMap都是继承于AbstractMap

总结

Java集合中List,Set以及Map等集合体系详解

在这里插入图片描述
List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口

List接口的实现类有ArrayList,Vector,LinkedList

Set接口的实现类有HashSet,LinkedHashSet,TreeSet

Map接口的实现类有Hashtable,LinkedHashMap,HashMap,TreeMap

自己实现

MyIterator接口

package interfacePag;

public interface MyIterator<T> {
    boolean hasNext();

    T next();

    void remove();
}

MyIterable接口

所有的集合操作都实现了Collection接口,也就是在Collection接口中定义了常规都需要的方法,而且要使用泛型
而Collection接口继承于Iterable接口,所以应该先去定义Iterable接口,实现这个接口实现对象的增强,变成可迭代的

package interfacePag;

import java.util.Iterator;

public interface MyIterable<T>{
    /**
     *
     * @return 返回该类型的迭代器
     */
    MyIterator<T> iterator();

    //下面的看不懂了
    /*default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }*/

}

MyCollection接口

这个接口是为了集合操作的最大通用性,不会直接提供这个接口的实现,而是会通过实现其子接口(List,set)加以使用

规定

  1. 所以的集合都应该实现两个构造方法① 无参构造创建新集合 ②有参构造,传入另一个集合构造新集合

  2. 有些方法是可选的,如果不实现,应该抛出UnsupportedOperationException

  3. 一些集合不对元素进行限制,如紧张空元素,会抛出{@code NullPointerException}或{@code ClassCastException}

  4. 巴拉巴拉有时间再读

package interfacePag;

import java.util.Collection;


/**
 * 集合层次结构的根集合,集合包含一组对象(元素)
 * 有些集合允许重复元素有些不允许
 * 有些集合有序有些无序
 * JDK没有提供这个根集合的直接实现吗,而是去实现他的子接口(list, set)
 *
 * 实现该接口的集合应该实现两个标准构造器
 * ①无参构造
 * ②有参构造,传入另一个collection构造新collection
 *
 * 有些方法是可选的,如果不去实现应该抛出@code UnsupportedOperationException}
 *
 * 有些集合的实现可能对元素加以限制
 * ① 对空值的限制 @code NullPointerException}
 * ② 对指定类型的限制 {@code ClassCastException}
 *
 * 每个实现都有自己的同步政策
 *
 *
 * @param <E>
 */
public interface MyCollection<E> extends MyIterable<E> {
    /**
     * 返回collection的元素个数,如果个数比Integer.MAX_VALUE大则返回nteger.MAX_VALUE
     * @return collection的元素个数
     */
    int size();

    /**
     *
     * @return {@code true} 如果为空
     */
    boolean isEmpty();

    /**
     *
     * @param o element
     *
     * @return {@code true}如果包含元素o,不直接用泛型E是因为可能不规定泛型
     *
     * @throws ClassCastException 如果o的类型于Collection所支持的类型不同
     *
     * @throws NullPointerException 当不支持null但是传入了null
     */
    boolean contains(Object o);

    /**
     * 并不会保证元素的返回顺序,除非规定
     *
     * @return {@code Iterator}返回迭代器
     */
    MyIterator<E> iterator();

    /**
     * 把集合元素放到新数组返回,注意,返回的是新数组(safe),所以用户可以随意更改
     *
     * @return Object[]
     */
    Object[] toArray();

    //剩下还有几个toArray太复杂以后再看吧

    /**
     *
     * @param e
     * @return {@code true} 如果成功添加
     *
     * @throws UnsupportedOperationException 如果不支持add操作
     *
     * @throws ClassCastException add了collection不支持的类型
     *
     * @throws NullPointerException add了null,但是collection不支持addnull
     *
     * @throws IllegalStateException
     *
     * @throws IllegalArgumentException
     */
    boolean add(E e);

    /**
     * {@code Objects.equals(o, e)}, if
     * this collection contains one or more such elements.  Returns
     * {@code true} if this collection contained the specified element (or
     * equivalently, if this collection changed as a result of the call).
     *
     * @param o element to be removed from this collection, if present
     * @return {@code true} if an element was removed as a result of this call
     * @throws ClassCastException if the type of the specified element
     *         is incompatible with this collection
     *         (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified element is null and this
     *         collection does not permit null elements
     *         (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
     * @throws UnsupportedOperationException if the {@code remove} operation
     *         is not supported by this collection
     */
    boolean remove(Object o);

    /**
     * 最简单的方法是依赖 {@code Object.equals}来实现
     * 但是有些会覆盖重写这个方法根据情况选择值比较或引用比较
     * @param o
     * @return
     */
    boolean equals(Object o);

    //接下来是一些对多个对象进行的操作,这里只写几个
    void clear();

    boolean addAll(Collection<? extends E> c);
    
}

MyAbstractCollection

package AbstractPag;

import interfacePag.MyCollection;
import interfacePag.MyIterator;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Iterator;

import static java.util.AbstractCollection.finishToArray;

public abstract class MyAbstractCollection<E> implements MyCollection<E> {

    protected MyAbstractCollection() {
    }

    public abstract MyIterator<E> iterator();

    public abstract int size();

    /**
     * 判断是否为空就是调用size()方法,判断返回值是否为0
     * @return
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 查找元素是否存在
     * @param o element
     *
     * @return
     * @throws ClassCastException   {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    public boolean contains(Object o){
        //使用迭代器遍历,拿到迭代器对象
        MyIterator<E> itr = iterator();
        //判断是否为空
        if(o == null){
            while(itr.hasNext()){
                if(itr.next() == null){
                    return true;
                }
            }
        }else {
            while (itr.hasNext()){
                if(o.equals(itr.next())){
                    //.equals根据不同的对象可能有不同的重载,可能是值比较也可能是引用比较
                    return true;
                }
            }
        }
        return false;
    }

    public Object[] toArray(){
        //先拿到迭代器,在遍历拷贝到新的数组
        //数组的长度可以通过size()获得
        int capacity = size();
        Object[] array = new Object[capacity];
        MyIterator<E> itr = iterator();
        for(int i = 0; i < capacity; i++){
            //还是要判断是否能取到,因为可能在toArray的过程中其他线程对collection进行了修改
            if(!itr.hasNext()){
                //拷贝到一个容量更小的数组返回
                return Arrays.copyOf(array,i);
            }
            array[i] = itr.next();
        }
        //看是否真的遍历完了
        //return itr.hasNext() ? finishToArray(array, itr) : array;
        if(itr.hasNext()){
            //finishToArray(array, itr)
            while (itr.hasNext()){
                int cap = array.length;
                if(capacity == cap){
                    //会构建一个新的数组,新数组的容量是原来的两倍+1
                    int newCap = cap + (cap >> 1) + 1;
                    array = Arrays.copyOf(array,newCap);
                }
                array[capacity++] = (E)itr.next();
            }
        }
        //因为新数组的容量是原来的两倍+1,所以不一定占满
        if(capacity < array.length){
            array = Arrays.copyOf(array,capacity);
        }
        return array;
    }

    public boolean remove(Object o){
        MyIterator<E> itr = iterator();
        if(o == null){
            while (itr.hasNext()){
                if(itr.next() == null){
                    itr.remove();
                    return true;
                }
            }
        }else{
            while (itr.hasNext()){
                if(itr.next().equals(o)){
                    itr.remove();
                    return true;
                }
            }
        }
        return false;
    }
    public String toString(){
        //应该用可变字符串StringBuilder
        MyIterator itr = iterator();
        if(!itr.hasNext()){
            return "[]";
        }else{
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            while (itr.hasNext()){
                sb.append(itr.next());
                if (! itr.hasNext())
                    return sb.append(']').toString();
                sb.append(',').append(' ');
            }
        }
        return null;
    }
}


Mylist接口

package interfacePag;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;

/**
 * 有序集合,元素在集合有序可以通过下标访问
 *
 * 允许重复元素
 *
 * 可以对null进行操作,也可以禁止对null的操作
 *
 * 这个接口规定了除了{@code Collection} 接口外的其他限制
 */

public interface MyList<E> extends MyCollection<E> {
    int size();

    boolean isEmpty();

    MyIterator<E> iterator();

    boolean contains(Object o);

    Object[] toArray();

    /**
     *
     * @param e 将e添加到尾部
     * @return
     * @throws UnsupportedOperationException if the {@code add} operation
     *         is not supported by this list
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this list
     * @throws NullPointerException if the specified element is null and this
     *         list does not permit null elements
     * @throws IllegalArgumentException if some property of this element
     *         prevents it from being added to this list
     */
    boolean add(E e);

    boolean remove(Object o);
    
    MyListIterator<E> listIterator();

    /**
     *
     * @param c 下限通配符用限制类型的下限,通过比较器限制的规则来进行比较
     *          策略模式:在运行时可以通过传递不同的比较器选择不同的算法
     *          <? super E> 准许所以的子类使用相同的父类型的比较器
     */
    default void sort(Comparator<? super E>c){
        Object[] array = this.toArray();
        Arrays.sort(array, (Comparator)c);
        MyListIterator itr = this.listIterator();
        for(int i = 0; i< array.length; i++){
            listIterator().next();
            listIterator().set((E) array[i]);
        }
    }
    
    void clear();
    
    E get(int index);
    
    int indexOf(Object o);
}
    

这里是使用到了Comparator<? super E>c:下限通配符用限制类型的下限,通过比较器限制的规则来进行比较;
策略模式:在运行时可以通过传递不同的比较器选择不同的算法;

<? super E> 准许所以的子类使用相同的父类型的比较器 ## MyLIstIterator接口 ```java package interfacePag; /** * 允许双向遍历 * @param */ public interface MyListIterator extends MyIterator { boolean hasNext(); E next(); boolean hasPrevious(); E previous(); void set(E e); void add(E e); } ``` ## MyAbstractList接口 ```java package AbstractPag; import interfacePag.MyIterator; import interfacePag.MyList; import interfacePag.MyListIterator; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.ListIterator; import java.util.NoSuchElementException; /** * 这个类提供了List框架的实现,减少实现接口所需的工作 */ public abstract class MyAbstractList extends MyAbstractCollection implements MyList { /** * List结构改变的次数 * 就是这个值引起fast-fail * */ protected transient int modCount = 0; protected MyAbstractList(){ } public void add(int index, E elements){ throw new UnsupportedOperationException(); } public boolean add(E e){ add(size(), e); return true; } public abstract E get(int index); public E set(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } public int indexOf(Object o){ MyListIterator iter = listIterator(); if(o == null){ while(iter.hasNext()){ if(iter.next() == null){ return iter.previousIndex(); } } }else{ while(iter.hasNext()){ if(o.equals(iter.next())){ return iter.previousIndex(); } } } return -1; } public MyIterator iterator() { return new Itr(); } //自己实现迭代器 private class Itr implements MyIterator{ int cursor = 0;//指向next返回元素的索引 int lastRet = -1;//有迭代操作后就会记录上次迭代的位置 int expectedModCount = modCount;//当前iterator持有的modcount的值 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } @Override public boolean hasNext() { return cursor != size(); } @Override public E next() { checkForComodification(); try{ int i = cursor; E next = get(i);//可能抛出越界异常 lastRet += 1; cursor+=1; return next; }catch (IndexOutOfBoundsException e){ checkForComodification();//可能是遍历的时候更改导致没有拿到元素 throw new NoSuchElementException(); } } @Override public void remove() { if(lastRet < 0){ throw new IllegalStateException(); } checkForComodification(); try{ if(lastRet < cursor){ cursor--; } lastRet = -1;//删除后,上次迭代的位置会被置为-1 expectedModCount = modCount;//所以遍历的时候用迭代器删除不会报错 }catch (IndexOutOfBoundsException e){ throw new ConcurrentModificationException(); } } } } ```
发布了62 篇原创文章 · 获赞 0 · 访问量 1167

猜你喜欢

转载自blog.csdn.net/weixin_43907800/article/details/103996134