F3达人

            ---JDK掘金

什么是F3达人

如何成为F3达人

JDK掘金之瞅瞅List

 

文笔不好,就乱说几句。在下此处说的f3 并不是BYDf3,此乃 eclipse 上的f3.  因为鄙人的环境是windowslinux这样的高深环境,一般不怎么用。 再个大家可能更多开发环境也是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 list=new ArrayList();

list.add("1");

list.get(0);

 

咱们对着 add  就是一下F3 ,结果给了

List.class -> boolean add(E e);

一看定位到了List.class add方法。都知道List是个接口,add是个接口方法签名,没有具体实现。因为咱们用的是面向接口编程 即声明时 List 而不是ArrayList   此时来一下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 node(int index) {

        // assert isElementIndex(index);

        if (index < (size >> 1)) {

            Node x = first;

            for (int i = 0; i < index; i++)

                x = x.next;

            return x;

        } else {

            Node 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相关的