F3达人
---向JDK掘金
什么是F3达人
如何成为F3达人
向JDK掘金之瞅瞅List
文笔不好,就乱说几句。在下此处说的f3 并不是BYD的f3,此乃 eclipse 上的f3. 因为鄙人的环境是windows,linux这样的高深环境,一般不怎么用。 再个大家可能更多开发环境也是windows,所以就windows上的eclipse默认源码查看键F3来展开这个小系列。
解释了f3不够,咱的目标是要成为f3达人!在这肉欲横飞的世界里,达人到处都有,干嘛的都有,唯独咱们此处说的达人,或者提出的F3达人还是不多见的吧 :) 所以成为这个达人,也算是个追求吧…
如何成为f3达人呢? 最简单不过了,什么时间你的键盘F3被用的破损了,估计差不多了,此处只指eclipse使用时点f3 ,其他的各位看官自己处理吧,反正网管不会给非此方法搞坏f3的人换键盘 …
都是技术人,说了半天,来点干货吧。
度娘告诉我们一个技巧:“只遍历用Arraylist,只要有修改就用linkedList,如果修改中还有遍历则是LinkedList+iterator借口遍历”。咱们称此为规则1,下文也以此引用。
以前一些哥们对前辈或者老大说的话不会过多的思考的,所以他就很久没成为老大,或者只成为老辈,没有成为别人的前辈,甚是可惜。咱们今天换个想法,虽然度娘很猛,不过咱们还是自己多想想,多试试。
方案一:黑盒测试
http://blog.csdn.net/xyx139/article/details/6591420
这哥们比较勤恳,已经测试了,我就不重复贴码了。
方案二:白盒一下
码一段:
List<String> list=new ArrayList<String>();
list.add("1");
list.get(0);
咱们对着 add 就是一下F3 ,结果给了
List.class -> boolean add(E e);
一看定位到了List.class 的add方法。都知道List是个接口,add是个接口方法签名,没有具体实现。因为咱们用的是面向接口编程 即声明时 List<String> 而不是ArrayList<String> 。 此时来一下ctrl+t 。选中弹出来框中的 ArrayList即可。 此过程咱们不多说了。
这时来到了ArrayList.class
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true; }
有兴趣的F3一把ensureCapacityInternal()
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
兴趣还存,那就在F3一把grow()
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
好了,到此,我们已经知道了,ArrayList底层使用数组实现的,每次add时判断一下是否超出了初始的大小,超过了就grow一下,grow中用的数组拷贝之类的方法,大家可以活学活用,今天主题不是这个,不多说他了。
不过插一小句啊,刚才提及了,说是如果超过初始大小的话就grow。那么初始大小多大呢?
public ArrayList() {
this(10);
}
此处看到,初始大小是10. 据此,咱们可以增加一条优化使用方法。如果咱们对ArrayList的大小有个大小预期,超过10,咱们就直接调用ArrayList(int initialCapacity) 这样避免掉频繁的grow。
下面开始对get方法F3. 或许到此你还在为了成为达人,在看着烂文,呵呵。
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
实现就是,rangeCheck 检查一下是否越界。 之后就是直接返回了elementData(index); 再次F3
E elementData(int index) {
return (E) elementData[index];
}
好了,到此看到,get直接由封装的数组直接定位返回。(小知识:汇编之所以快,因为很多都是直接寻址;java中数组的直接下标寻址也是非常快的,或许是最快的吧,咱就不断言了)
咱们分析一下LinkedList的get方法。 因为直接知道要分析谁,直接ctrl+shift+t LinkedList 定位到 LinkedList.class
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
最终的node(int index),代码和数组直接下标取值相比,势必慢点。通过以上F3,咱们了解了 ArrayList LinkedList 的get 方法的不同。
好了,至此,咱们通过一路F3在JDK源码中掘金:
1.ArrayList 底层用数组实现。初始默认大小是10 。
2.每次add时会检测是否超出数据大小,超过的话就grow
3.因为get(int index) 方法是调用底层的数据下标寻址,所以速度非常快;相比之下LinkedList因为底层使用链表,所以查询天生就不如数组快。
更多的金子等待各位看官去挖了。 希望没有过多的浪费您的时间 :)
PS:计划下次写一下Hash相关的