• Java笔记(十一)通用容器类和总结


    通用容器类和总结

    一、抽象容器类

    一)AbstractCollection

    提供了Collection接口的基础实现,具体来说,实现了如下方法:

    public boolean addAll(Collection<? extends E> c)
    public boolean contains(Object o)
    public boolean containsAll(Collection<?> c)
    public boolean isEmpty()
    public boolean remove(Object o)
    public boolean removeAll(Collection<?> c)
    public boolean retainAll(Collection<?> c)
    public void clear()
    public Object[] toArray()
    public <T> T[] toArray(T[] a)
    public String toString()

    AbstractCollection不知道基础数据是怎么存储的,它如何实现这些方法呢?

    它依赖于如下更为基础的方法:

    public boolean add(E e)
    public abstract int size();
    public abstract Iterator<E> iterator();

    add方法:

    public boolean add(E e) {
        throw new UnsupportedOperationException();//如果子类集合是不可被修改的,则不用重写该方法,使用默认实现就可以了,否则必须重写
    }

    size()是抽象方法,iterator也是抽象方法。

     二)AbstractList

    提供了List接口的基本实现:

    public boolean add(E e)
    public boolean addAll(int index, Collection<? extends E> c)
    public void clear()
    public boolean equals(Object o)
    public int hashCode()
    public int indexOf(Object o)
    public Iterator<E> iterator()
    public int lastIndexOf(Object o)
    public ListIterator<E> listIterator()
    public ListIterator<E> listIterator(final int index)
    public List<E> subList(int fromIndex, int toIndex)

     abstrackList通过如下更为基础的方法实现:

    public abstract int size();
    abstract public E get(int index);
    public E set(int index, E element)
    public void add(int index, E element)
    public E remove(int index)
    //set, add, remove默认实现都是抛出异常

    另外,AbstrackList不需要实现迭代器类和相关方法,因为其内部已经实现了。

    三)AbstractSequentialList

    它是AbstractList子类,它实现了如下方法:

    public void add(int index, E element)
    public boolean addAll(int index, Collection<? extends E> c)
    public E get(int index)
    public Iterator<E> iterator()
    public E remove(int index)
    public E set(int index, E element)

    它实现了根据索引位置进行操作的get,set,add,remove方法

    这是通过重写listIterator()方法实现的。

    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }

    虽然AbstractSequentialLis 是AbstrackList的子类,但实现逻辑和用法上和Abstract正好相反。

    Abstrack需要具体子类写根据索引操作的方法get,set,add,remove,它提供了迭代器,但迭代器是

    基于这些方法实现的。它假定子类可以高效地根据索引位置进行操作,适用于内部是随机访问类型

    的存储结构(如数组),比如ArrayList就继承自AbstrackList。

    AbstractSequentialList 需要具体子类重写迭代器,它提供了根据索引的操作方法get,set,add,

    remove,但这些方法是基于迭代器实现的。它适用于内部是顺序访问类型的存储结构(如链表)。

    四)AbstrackMap

    AbstrackMap提供了Map接口的基础实现:

    public void clear()
    public boolean containsKey(Object key)
    public boolean containsValue(Object value)
    public boolean equals(Object o)
    public V get(Object key)
    public int hashCode()
    public boolean isEmpty()
    public Set<K> keySet()
    public void putAll(Map<? extends K, ? extends V> m)
    public V remove(Object key)
    public int size()
    public String toString()
    public Collection<V> values()

    AbstractMap 实现这些方法依赖于更基础的方法:

    public V put(K key, V value)
    //抽象方法,子类必须实现
    public abstract Set<Entry<K,V>> entrySet();

    定义了两个公有的静态内部类:

    AbstractMap.SimpleEntry implements Entry<K,V>
    //表示只读的键值对
    AbstractMap.SimpleImmutableEntry implements Entry<K,V>

    二、Collections 

    一)查找和替换

    1.二分查找

    //二分查找
    public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
    public static <T> int binarySearch(List<? extends T> list,T key, Comparator<? super T> c) 

    二分查找要求List中的元素是从小到大排序的。如果是从大到小排序,

    需要传递一个逆序Comparator对象,Collections提供了返回逆序Comparator的方法:

    public static <T> Comparator<T> reverseOrder()
    public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
    ArrayList<Integer> list = new ArrayList<>(Arrays.asList
    (new Integer[]{33, 22, 37, 88, 1, 8, 9}));
    Collections.sort(list);
    System.out.println(Collections.binarySearch(list, 22)); //3

    2.查找最大最小值:

    <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
    <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)
    <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
    <T> T min(Collection<? extends T> coll, Comparator<? super T> comp)

    3.查找元素出现次数:

    public static int frequency(Collection<?> c, Object o)

    4.在sourceList中查找targetList的位置:

    public static int indexOfSubList(List<?> source, List<?> target)
    public static int lastIndexOfSubList(List<?> source, List<?> target)

    indexOfSubList 从头开始查找,lastIndexOfList从结尾开始查找,没有找到返回-1,

    找到第一个匹配元素的索引位置。

    5.查看两个集合是否有交集:

    public static boolean disjoint(Collection<?> c1, Collection<?> c2)//没有返回true,有返回false

    6.替换:

    public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)//替换成功返回true

    二)排序和调整顺序

    1.排序、交换位置与翻转:

    public static <T extends Comparable<? super T>> void sort(List<T> list)
    public static <T> void sort(List<T> list, Comparator<? super T> c)
    //交换元素位置
    public static void swap(List<?> list, int i, int j)
    //翻转
    public static void reverse(List<?> list)

    2.随机化重排:

    public static void shuffle(List<?> list)
    public static void shuffle(List<?> list, Random rnd)

     三、容器类总结

    容器类有两个根接口:

    一)Collection

    表示的数据集合有基本的增、删、查、遍历等方法,但没有定义元素间

    的顺序或位置,也没有规定是否有重复元素。

    List是Collection的子接口,表示有顺序或者位置的数据集合,增加了

    根据索引位置进行操作的方法。两个主要实现类:ArrayList基于数组实现

    随机访问效率很高,但从中间插入或删除元素需要移动元素,效率比较低,

    LinkedList,使用双向链表实现,随机访问效率较低,增删元素只需要调整

    邻近节点的链接。

    Set也是Collection的子接口,它没有新增方法,但保证不含重复元素。它的

    两个主要实现类:HashSet,基于哈希表,根据键的hashCode查找元素,效率

    较高。TreeSet基于排序二叉树实现,元素按比较有序,元素需要实现Comparable

    接口,或者创建TreeSet时提供一个Comparator对象。HashSet还有一个子类LinkedHashSet

    可以按插入有序。还有一个针对枚举类型的实现类EnumSet,它基于位向量,效率很高。

    Queue也是Collection的子接口,表示队列,先进先出,在尾部添加,头部查看或者删除。

    Dueue是Queue的子接口,表示更为通用的双端队列,在头尾都可以查看,删除,添加。

    Dueue的两个实现是LinkedList,ArrayDeque基于循环数组实现。如果只需要Deque接口,

    ArrayDueue效率更高。Queue还有一个特殊实现类PriorityQueue,表示优先级队列,内部

    是使用堆实现的。

    二)Map

    Map接口表示键值对集合,通常根据键进行操作。两个主要实现类:

    HashMap基于哈希表实现,要求键重写hashCode方法,根据键的hashCode

    进行查找,效率很高,但元素没有顺序。TreeMap基于排序二叉树实现,要求

    键实现Comparable接口,或者提供Comparator对象。HashMap有一个子类,

    LinkedHashMap,在HashMap的基础上把每个元素还加入了一个双向链表中,

    它可以按插入和访问有序。

    注意:除了HashTable,Vector和Stack,以上各种容器类都不是线程安全的。

    此外,容器类的迭代器都有一个特点,都会在迭代的中间进行结构性变化

    检测,如果容器发生了结构性变化,就会抛出ConcurrentModificationException,

    所以不能在迭代的时候使用容器类提供的add/remove方法,如需添加和删除需要使用

    迭代器提供的方法。

    Simple is important!
  • 相关阅读:
    DevC++手动开栈
    二分图|网络流建模复习
    C++常用数据类型范围
    卡常剪贴板
    AcWing 2425. 奇怪的计算器
    AcWing 153. 双栈排序 震惊 !2^n 过 1000
    AcWing 352. 闇の連鎖
    AcWing 246. 区间最大公约数
    AcWing 221. 龙哥的问题
    AcWing 381. 有线电视网络
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/10032026.html
Copyright © 2020-2023  润新知