从源码角度解析Java集合框架
来源:互联网 发布:linux cp复制文件夹 编辑:程序博客网 时间:2024/05/29 15:48
1.ArrayList(允许重复的元素,允许null值,非线程同步的(Vector是同步的),其内部实现还是数组)
public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
从源码中可以看出,contains方法是遍历object数组,通过object的equals方法来比较的
/** * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The * elements themselves are not copied.) * * @return a clone of this <tt>ArrayList</tt> instance */ public Object clone() { try { @SuppressWarnings("unchecked") ArrayList<E> v = (ArrayList<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } }
这回我们不用看代码,直接看代码上面的注释就可以知道ArrayList的clone方法是浅拷贝。(当然,对应的还有深拷贝,什么是浅拷贝,深拷贝,大家去百度吧,这里不作解释)
add方法不看源码,因为涉及到的方法很多,结论是,每次调用add方法的时候,系统会监测是否超过ArrayList的最大承受范围,如果超过了,就将ArrayList的容量扩大一倍,然后再进行元素的添加
remove方法
public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; }
先检查要remove元素的下标是否越界,如果没有越界,就将该元素后面的所有元素往前移一位,最后将需要删除的那个元素赋值null,目的是通知垃圾回收机制去回收该对象
ArrayList中的Iterator,这相当于一个遍历器,能够依次访问到每个元素
ArrayList中的一些常见的方法都分析完了,其他的如果想自己分析,就查看JDK源码吧。与arraylist类似的还有LinkedList,内部是一个双向链表,学过数据结构的同学都知道,链表的插入元素和删除元素的时候比较方便,所以当数据量非常大的时候,用LinkedList更高效。
2.HashSet
开发中HashSet用的比较多,它不允许重复的元素,允许null值,而且是无序的,它内部是基于HashMap实现的。它有两个关键的因数,一个是capacity,另一个是load factor。官方建议不要将capacity设置太大或者将load factor设置太小。如果capacity设置太大,bucket就放不满,占用过多无效的内存空间;如果load factor设置过小,系统就会频繁得给bucket扩容,影响程序的运行效率。
/** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); }
从源码中可以看出,默认的capacity是16,load factor是0.75。具体意思就是当里面的元素个数达到16*0.75=12时,系统就会为HashSet扩容,扩容到当前的两倍
public int size() { return map.size(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); }
这几个方法内部都是通过HashMap来实现的,其他方法不赘述,其实都差不多
由于HashSet是无序的,所以没有办法通过正常的循环结构来遍历其中的数据,JDK给我们提供了Iterator接口,使用方法和ArrayList中的Iterator方法一样
与HashSet类似的还有LinkedHashSet,看名字就能猜得出来,内部实现原理是链表;TreeMap,可以用来排序的Set,初始化时候需要传一个Comparator参数
3.HashMap
HashMap允许空值,而Hashtable不允许空值
这里我们重点看put和get方法
public V put(K key, V value) { //如果HashMap内部的table是空的,就实例化一个table if (table == EMPTY_TABLE) { inflateTable(threshold); } //如果key为null,就调用putForNullKey() if (key == null) return putForNullKey(value); //如果key不为null,就找到key的hashcode所对应的地址,在该地址里面遍历所有的entry,看是否有相同的元素,相同则替换旧的value,不同就添加该元素 int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
get方法原理跟这个差不多,就不赘述了
HashMap中值得注意的一个知识点是,要判断两个元素是否相等,必须要同时满足hashcode和equals相同,只要有其中一个值不相同,就视为不同元素
与HashMap类似的一些集合类使用方法跟它差不多,所有就不多说了,可以自己查看JDK源码学习
学会看源码是一个程序员必备的技能!
- 从源码角度解析Java集合框架
- 从源码角度解析Handler
- Java集合框架源码解析-ArrayList
- Java集合框架源码解析-LinkedList
- Java集合框架源码解析-TreeSet
- Java集合框架之HashMap源码解析
- java集合框架(1)-从api角度分析集合框架的结构
- 从源码角度简要分析ActionBar框架
- 从源码角度简要分析ActionBar框架
- 从源码角度分析imageLoader框架
- 从源码角度学习Volley框架
- 从源码角度解析Android消息机制
- 从源码角度解析ArrayList特性
- 从源码角度解析LinkedList特性
- 从源码角度解析Vector特性
- 从源码角度解析HashMap特性
- HashMap-Java集合框架之 Java HashMap 源码解析
- Java集合框架之 Java HashMap 源码解析
- 并发编程学习总结(七) :java中synchronized关键字使用详解(1)
- 【阅读】《黑客与画家》系列05-时间(节选)
- H264--编码原理以及I帧B帧P帧--1
- 数据库连接池的工作原理
- 如何有效提升Unity Gear VR游戏性能
- 从源码角度解析Java集合框架
- 欢迎使用CSDN-markdown编辑器
- H.264RTP封包原理
- 【XSHELL】xshell快捷键配置
- 剑指offer 阅读笔记 左旋转字符串
- Maven – Create a fat Jar file – One-JAR example
- Leetcode Best Time to Buy and Sell Stock IV
- H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
- 信息分析——共享经济服务模式的分析与研究