写在开头

  java.util.Collection 作为Java开发最常用的接口之一,我们经常使用,今天我带大家一起研究一下Collection接口,希望对大家以后的编程以及系统设计能有所帮助,本文所研究的jdk版本为jdk1.8.0_131

明确一下几点:

    •   Collection是接口,其继承了Iterable接口
    •   Collection属于单值类型集合,重点子接口List接口和Set接口

Java.util.List接口(有序、不唯一)

ArraryList

  ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。ArrayList是非同步的,效率高但是线程不安全,Collections.sychromiziedList(new ArraryList<>());可以让那个ArrayList变成线程安全类

    • ArrayList是基于动态数组实现的,在增删时候,需要数组的拷贝复制。
    • ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
    • 删除元素时不会减少容量,若希望减少容量则调用trimToSize()
    • 它不是线程安全的。它能存放null值。

LinkedList

  

  LinkedList是一个双向循环列表队列

    • LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
    • LinkedList 实现 List 接口,能对它进行队列操作。
    • LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
    • LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
    • LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
    • LinkedList 是非同步的。

Vector

    • 底层是数组,现在已少用,被ArrayList替代,原因有两个:

    • Vector所有方法都是同步,有性能损失
    • Vector初始length是10 超过length时 以100%比率增长,相比于ArrayList更多消耗内存
    • 参考资料:https://www.zhihu.com/question/31948523/answer/113357347

  总的来说:查询多用ArrayList,增删多用LinkedList。

  ArrayList增删慢不是绝对的(在数量大的情况下,会有例外):

    •   如果增加元素一直是使用add()(增加到末尾)的话,并且不扩容的情况下)
    •   一直删除末尾的元素也是ArrayList要快【不用复制移动位置】
    •   至于如果删除的是中间的位置的话,还是ArrayList要快

  但一般来说:增删多还是用LinkedList,因为上面的情况是极端的~

Java.util.Set接口(无序、唯一)

|——SortedSet接口——TreeSet实现类

Set接口——|——HashSet实现类

|——LinkedHashSet实现类

hashSet

  hashSet底层基于hashMap实现,如图

  

  hashSet中的add()方法,是将对象E放入hashMap中的key的位置,value位置存放的是一个固定的Object,如图:

  HashSet是无序唯一的,当元素为自定义对象时,两者的hashCode不同,被认为是不同的元素从而被允许放入HashSet中,但这不符合实际的生产意义,因此需要让其判定位相等,就要重写hashCode(),然而重写HashCode(),会出现重码的bug,因此需要重写equals()来解决

  添加元素的时候,如果key(也对应的Set集合的元素)相等,那么则修改value值。而在Set集合中,value值仅仅是一个Object对象罢了(该对象对Set本身而言是无用的)。

也就是说:Set集合如果添加的元素相同时,是根本没有插入的(仅修改了一个无用的value值),从源码(HashMap)中也看出来,==和equals()方法都有使用,具体过程如下

    1.   新元素的hsah是否等于老元素的hash,如果不相等,则元素不同,如果相等,那么进行第二部比较
    2.   新元素与老元素用“==”进行比较,如果相等,则为同一元素,若不同则进行第三部比较
    3.   新元素和老元素用equals()方法判定是否相等,如果不等则不是同一元素,如果相等那么结果为:两个元素不是同一个对象,程序想把它们当成同一个对象,因此重写了equals方法;

TreeSet

与HashSet是基于HashMap实现一样,TreeSet同样是基于TreeMap实现的。

TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向  TreeSet中加入的应该是同一个类的对象。

LinkedHashSet

LinkedHashSet是HashSet的一个“扩展版本”,HashSet并不管什么顺序,不同的是LinkedHashSet会维护“插入顺序”。HashSet内部使用HashMap对象来存储它的元素,而LinkedHashSet内部使用LinkedHashMap对象来存储和处理它的元素

  

  

  

  

java.util.Collection源码分析和深度讲解的更多相关文章

  1. java.util.HashMap源码分析

    在java jdk8中对HashMap的源码进行了优化,在jdk7中,HashMap处理“碰撞”的时候,都是采用链表来存储,当碰撞的结点很多时,查询时间是O(n). 在jdk8中,HashMap处理“ ...

  2. java.util.AbstractStringBuilder源码分析

    AbstractStringBuilder是一个抽象类,是StringBuilder和StringBuffer的父类,分析它的源码对StringBuilder和StringBuffer代码的理解有很大 ...

  3. java.util.Hashtable源码分析

    Hashtable实现一个键值映射的表.任何非null的object可以用作key和value. 为了能存取对象,放在表里的对象必须实现hashCode和equals方法. 一个Hashtable有两 ...

  4. java.util.Dictionary源码分析

    Dictionary是一个抽象类,Hashtable是它的一个子类. 类的声明:/** The <code>Dictionary</code> class is the abs ...

  5. java.util.TreeSet源码分析

    TreeSet是基于TreeMap实现的,元素的顺序取决于元素自身的自然顺序或者在构造时提供的比较器. 对于add,remove,contains操作,保证log(n)的时间复杂度. 因为Set接口的 ...

  6. java.util.LinkedList源码分析

    public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, D ...

  7. java.util.ArrayList源码分析

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  8. java.util.HashSet源码分析

    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java. ...

  9. java.util.Map源码分析

    /** * An object that maps keys to values. A map cannot contain duplicate keys; * each key can map to ...

随机推荐

  1. Java位操作全面总结[ZZ]

    Java位操作全面总结 在计算机中所有数据都是以二进制的形式储存的.位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快.在实际编程中,如果能巧妙运用位操作,完全可以达到四两拨千 ...

  2. unlimited channel buffer in Go

    channel buffer可以事先分配大小,但是这些是需要占用内存的,事先分配几G内存给一个channel很浪费资源的,所以怎样创建一个无限的channel buffer呢?比较naive的写法就是 ...

  3. TransactionScope事务使用

    using (System.Transactions.TransactionScope T_Scope = new System.Transactions.TransactionScope()) { ...

  4. Flask 视图,模板,蓝图.

    https://www.cnblogs.com/wupeiqi/articles/7552008.html 1. 配置文件 from flask import Flask app =Flask(__n ...

  5. MySQL(动态执行SQL)

    day61 防sql注入 delimiter \\ CREATE PROCEDURE p4 ( ), in arg int ) BEGIN set @xo = arg; PREPARE xxx FRO ...

  6. Android应用安全防护和逆向分析 ——apk反编译

    概述 最近一直在学习Android应用安全相关和逆向分析的知识.现在移动app在安全方面是越来越重视了,特别是那些巨头企业涉及到钱的应用,那加密程度,简直是丧心病狂,密密麻麻.从这里可以看出,对于应用 ...

  7. webpack快速入门——webpack3.X 快速上手一个Demo

    1.进入根目录,建两个文件夹,分别为src和dist 1).src文件夹:用来存放我们编写的javascript代码,可以简单的理解为用JavaScript编写的模块. 2).dist文件夹:用来存放 ...

  8. [Swift实际操作]七、常见概念-(10)使用UserDefaults和归档方式存取用户数据实际操作

    在项目开发之中,你会经常需要将一些数据存储在本地,以便记录用户生产的数据或操作习惯.在项目文件夹上带点击鼠标右键.弹出右键菜单.本文将为你演示,存储用户数据的两种常用方式. 选择菜单中的创建新文件选项 ...

  9. Linux之开源软件移植

    移植环境 Utuntu 15.04 1.mplayer移植 版本:mplayer-export-snapshot.tar.bz2 /mplayer-export-2015-11-26 Linux PC ...

  10. java解压缩.gz .zip .tar.gz等格式的压缩包方法总结

    1..gz文件是linux下常见的压缩格式.使用 java.util.zip.GZIPInputStream即可,压缩是 java.util.zip.GZIPOutputStream public s ...