collection转换为list_聊聊Java,Collection类

从Interface结构看

注意下图中,ArrayList,LinkedList,HashSet为实现类。其他均为接口。

eddc76273b1ae0c5e17c652b869ad695.png
  • Iterable
    表述一种可以进行迭代的能力。表现在可以通过iterator方法返回迭代器。
    主要方法介绍:
    iterator()方法约束迭代能力
  • Collection
    表述一个容器的能力,例如获取容器大小,检查容器中是否包含某些元素,添加和删除容器中的元素, 两容器之间返回交集。
    主要方法介绍:
    父接口方法不再累述。
    size()通过该方法获取集合的大小。
    isEmpty()检查集合是否为空。
    contains(Object o)检查对象是否是否该元素。
    toArray()将集合转换为数组。
    add(E e)向集合添加对象。
    remove(Object o)从集合移除对象。
    containsAll(Collection<?> c)检查集合是否包含指定集合的所有元素。
    addAll(Collection<? extends E> c)将指定集合的所有元素添加到本集合中。
    removeAll(Collection<?> c)从集合中移除指定集合的所有元素。
    retainAll(Collection<?> c) 取两个集合的交集。
    clear()清空集合。
    列举了这么多方法,这些方法表现的都是一个集合应该拥有的能力,例如增删查。
  • List
    表述一个列表的能力,列表是一个有位置概念的集合,列表需要表述一个元素再列表中的位置,比如你是列表中第几个元素。
    主要方法介绍:
    父接口方法不再累述。
    get(int index)通过位置获取元素。
    set(int index, E element)将元素添加到指定位置,如果该位置有元素则替换。
    add(int index, E element)将元素插入到指定位置,如果该位置有元素则后移。
    remove(int index)移除列表中指定位置的元素。
    indexOf(Object o)返回元列表中指定元素的位置。
    lastIndexOf(Object o)获取最后一个匹配的指定元素的位置。
    subList(int fromIndex, int toIndex)根据指定位置返回子列表。
    从List中约束的方法可以看出,列表这样的集合不仅仅满足Collection对元素的添加和删除,他还额外提供了对容器里面元素位置的操作,比如add(int index, E element)指定插入位置,indexOf(Object o)获得元素位置。
  • Set
    表述一个装载不重复元素的能力。这个不重复的能力在Set的实现类中表达了出来。而Set接口和Collection在方法层面的约束几乎一致。

从Class的结构看

注意在下图中,Iterable和Collection均为接口。其他均为类。有了上面接口约束的基础,我们就比较容易理解下面的抽象类都在干什么了。

63999ee0d3b3b50a510774cf0c33ec6b.png
  • Iterable和Collection请见上面描述。
  • AbstractCollection
  • 实现Collection接口中的如下方法:
    boolean isEmpty(),调用size()方法结果为0的容器肯定是空的。把size()方法的实现交给具有更细节的容器实现来做吧。
    boolean contains(Object o),通过迭代器调用获取每一个元素然后和传入的元素对比,不就知道是否包含这个元素了吗。
    Object[] toArray(),通过迭代器遍历元素,然后把他们都放在数组里。
    remove(Object o),通过迭代找到该元素,调用迭代器的remove方法移除。
    containsAll(Collection<?> c),遍历通过contains方法验证是否存在。
    addAll(Collection<? extends E> c),遍历通过add方法添加。
    boolean removeAll(Collection<?> c),遍历通过remove方法删除。
    retainAll(Collection<?> c),遍历容器,通过contains方法检查是否存在,然后通过remove方法删除
    clear(),遍历通过remove方法删除
  • 未实现Collection接口中的如下方法:
    Iterator<E> iterator()
    int size()
    boolean add(E e)

未实现的方法都因为和容器的具体数据结构相关,所以留给抽象类的子类实现。**上面说了那么多废话,不难发现实现的方法都是基于xxx来实现的,而未实现的方法才是这些实现这些方法的细节。**抽象类就是这样,总会基于一些抽象方法来实现其它方法,这些实现方法都是在假设我们有这样的抽象方法返回的基础上实现的。这不就是抽象的本真吗,屏蔽掉不同容器间的细节让实现类去做,抽象类的实现方法描述的是容器的共性。

Set方面

接下来关注那些没有被AbstractCollection实现的方法,他们是,Iterator<E> iterator(),int size(),以及boolean add(E e) 。

  • AbstractSet
    实现方法:
    removeAll(Collection<?> c) ,抱着优化的目的重写了AbstractCollection的removeAll方法。方法的语义是删除本集合与指定集合c的交集。在AbstractCollection中我们的做法是遍历本集合,检查此元素是否在c集合中,这样不会漏掉重复的元素。而现在我们是一个set了。这意味着我们是没有重复 元素的。那么遍历c和遍历本集合就不会有差别了。这样代码被优化为先检查c集合和本集合的长短。谁短就遍历谁。
  • HashSet
    一个实现类,那么必然会实现所有接口中约束的方法以及抽象类遗留下来的抽象方法。因为在这里一切的细节都已被敲定。例如数据结构已成定局。
    实现方法:
    iterator(),借助HashMap的keySet的迭代器实现。
    size() ,因为借助了HashMap,所以size就是HashMap的size。
    add(E e),借助了HashMap,所以就理所当然的利用了HashMap.put()作为add方法。
    contains(Object o),这个方式其实在AbstractCollection中借助迭代器实现了。在HashSet借助了HashMap的key作为存储,所以方法被重写,利用HashMap.containsKey()实现此方法。

List方面

  • AbstractList
    主要方法:
    实现的方法:
    boolean add(E e),虽然还不知道具体的数据结构,但是这种在列表末尾添加记录的方式这样就可以了add(size(), e)。
    int indexOf(Object o) ,通过迭代器遍历,返回这个对象的位置。
    int lastIndexOf(Object o),通过迭代器反向遍历,返回这个对象的位置。
    void clear() ,通过迭代器移除所有元素
    boolean addAll(int index, Collection<? extends E> c),通过迭代器添加元素。
    Iterator<E> iterator(),制定了迭代器因为迭代器所约束的hasNext,next,remove都可以托管给size(),get(),remove()
    方法实现。虽然他们都是抽象方法,但是这些方法留个实现类实现即可。例如我们判断list中的cursor!=size()就知道是否还有下面的元素。
    List<E> subList(int fromIndex, int toIndex),基于RandomAccessSubList或者SubList提供一个子集合。
    未实现的方法:
    void add(int index, E element),因为数据结构未定,例如数组还是链表暂时无法决定add方法的实现,留给后面的实现类和抽象类吧。

AbstractSequentialList方面

顺序存储列表与随机存储概念想对应。所有的get,set,add,remove等操作都基于一个抽象的方法ListIterator<E> listIterator(int index)。这个方法通过传入index获取一个ListIterator。既然是抽象方法,那就留给子类实现好了。

  • LinkedList
    boolean add(E e) ,找到链表的最后一个元素,把新元素添加上。
    boolean remove(Object o),通过迭代器找到指定元素并删除他。
    ListIterator<E> listIterator(int index),返回一个自己实现的迭代器。

ArrayList方面

  • ArrayList
    boolean add(E e),确认数组列表容量,添加元素
    add(int index, E element),确认数组容量,在指定位置添加元素,将后面元素整体平移。

最后

搞明白这个关系有啥好处。

  • 至少熟练使用collection和他的子类了吧,至少两集合取交集不会想自己去实现一个了吧。
  • 面试也总爱问这问题ArrayList和LinkedList有啥区别。虽然这问题都被问烂了。
  • 提高代码审美能力,多阅读优秀的设计至少能比较好的让我们体会到接口和抽象类各自的用途吧。
  • 看个帖子并理顺关系的要个20分钟吧,又阻止了你出门瞎逛省了车费,餐费,购物费吧。

54ff420343c3b7fd5e197a1cc57febb8.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值