实验一 线性结构

实验内容

  • 1.ArrayList和LinkedList测试:
    查看ArrayList和LinkedList的Java API帮助文档,参考http://www.cnblogs.com/rocedu/p/4837092.html 用Junit对ArrayList和LinkedList的方法进行测试,要尽量覆盖正常情况,异常情况,边界情况
  • 2.分别用Java的ArrayList和LinkedList实现有序线性表的合并:aList,bList都是非递减线性表,合并后也是非递减public static List<? extends Comparable> mergeSortedList(List<? extends Comparable> aList, List<? extends Comparable> bList) 测试mergeSortedList的正确性,要尽量覆盖正常情况,异常情况,边界情况。
  • 3.参考Java Foundation 3rd 第15.6节,用数组实现线性表List用JUnit或自己编写驱动类对自己实现的ArrayList进行测试。
  • 4.参考Java Foundation 3rd 第15.7节,用链表实现线性表List用JUnit或自己编写驱动类对自己实现的LinkedList进行测试。
  • 5.参考http://www.cnblogs.com/rocedu/p/7483915.html对Java的ArrayList,LinkedList按要求进行源码分析。

实验步骤

实验1:

根据需求,首先查找帮助文档中ArrayList和LinkedList类的方法,根据要求测试add、isEmpty、remove、contains方法,首先建立一个数组,在里面放入5个元素。测试是否为空,返回false;使用add方法添加"book",检查数组中是否含有该要素;先add一个元素“book”,再调用remove方法删去这个元素,检最后查是否含有“book”;使用element方法来查唯一元素"book"验证contains方法,返回true。

实验2:

我的思路是先创建两个列表,两个列表可以放不同的元素,例如数字和String类型,比如我先创一个列表A,在其中中放入数字1和3,再创一个列表B,放入数字2和4,编写代码将数字个数少的列表插入数字多的列表,进行比较两列表的元素,完成插入排序,然后将结果返回到列表C,从而完成两列表的合并。最后编写测试代码进行测试。

实验3:

由于实验3要求编写驱动类对ArrayList方法进行测试,这和前几天的Bag类基本相同,所以可以参考我的Bag类博客

实验4:;

根据题意可知需要用LinkedList来实现List方法,有isEmpty、add、remove方法。为了方便测试我引入了element方法,即获取列表中的第一个元素。首先实现isEmpty,放入若干个数字,测试返回false;然后使用add方法加入"666",使用element获取第一个元素是否为“666”,测试成功;测试remove先放入一个“666”和“Java”,再用remove删去“666”,然后使用element获取第一个元素,返回"Java",测试成功。

实验5:源码分析

通过查找src.zip解压包util/ArrayList文件夹目录,使用IDEA打开。找到源码后首先ArrayList引用了AbstractList类,这个提供 List 接口的骨干实现,以最大限度地减少实现“随机访问”数据存储(如数组)支持的该接口所需的工作。然后就出现了很多看不懂的代码,但是我挑选了我们常用的一些方法的实现作为案例分析:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

通过查看这段代码可以知道一个add方法的基本思路是首先这个容器的容量要加1,以表示添加了一个元素,然后把e元素附加到该列表,整个过程十分精炼。插入指定元素在指定的位置在这列表。移动当前处于该位置的元素(如果有的话)和右边的任何后续元素(添加一个到它们的索引)。
但是针对这段代码我有一个疑问,比如我在elementData中放入一个元素,按照这段代码,它被放入了elementData[1]中,但是elmentData[0]不就没有东西吗?如果获取列表中的第一个元素的话不就获取的是elementData[0]吗?通过做实验,elementData[size++] = e;这段代码讲的其实是先放入元素到elementData[0]里然后在size++,所以不是先完成size++。

 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方法的实现,index是要删除的元素的索引,oldValue是列表中要删除的元素,思路是在列表中指定位置删除元素。所有后续元素左移(减去一个从指数)。

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方法利用indexOf来实现,查阅后发现原理是建立一个循环,对列表里面的元素进行逐一比较,返回的第一个出现的指定元素的索引在这份名单中,如果此列表不包含元素。返回最低的索引。后面翻阅contains方法时就调用了indexOf来检查列表中是否含有某元素。
感受:通过查读源代码我总结出一些规律,1.任何类的任何方法都是由最基础的程序设计语言实现的 2.编写源代码的程序员在编写源代码时的思维十分清晰,我是真的佩服,这也给后生们写代码提供了思路和灵感,可以学到很多有用的编程方法和设计模式 3.查阅源代码可以对出现的bug实行有针对性的debug,知道具体哪个地方出错

我的码云

posted @ 2017-09-25 22:51  润润大魔王  阅读(224)  评论(0编辑  收藏  举报