• 实验一


    实验一: ArrayList 和 LinkedList的应用与测试

    项目一

    ArrayList和LinkedList测试:
    
    查看ArrayList和LinkedList的Java API帮助文档,参考http://www.cnblogs.com/rocedu/p/4837092.html 用Junit对ArrayList和LinkedList的方法进行测试,要尽量覆盖正常情况,异常情况,边界情况
    
    提交单元测试运行截图,要全屏,包含学号信息
    
    • 对于这个实验来说最主要的就是理解方法的测试方法,比较花费时间,这个实验我测试了绝大多数的方法。

    • 代码(测试了这两个类,但是代码有点多就只贴出来了其中的一个)
    package exp1.test1;
    import junit.framework.TestCase;
    import org.junit.Test;
    import java.util.LinkedList;
    public class LinkedListTest extends TestCase {
        LinkedList link = new LinkedList();
        @Test
        public void testAdd(){
           assertEquals(true, link.add(0));
           link.add(1);
            link.add(1);
           link.add(3);
           link.add(2,2);
           assertEquals("add",2,link.get(2));
           assertEquals("add",1,link.get(3));
          LinkedList a = new LinkedList();
          a.add(4);
          a.add(5);
          link.addAll(a);
          assertEquals("addAll",4,link.get(5));
          link.addAll(1,a);
          assertEquals("addAll -有参数",4,link.get(1));
          a.addFirst(1);
          a.addLast(6);
          assertEquals("addFirst",1,a.get(0));
          assertEquals("addLast",6,a.get(3));
        }
        @Test
        public void testClear(){
            link.add(1);
            link.add(1);
            link.add(3);
            assertEquals(3,link.size());
            link.clear();
            assertEquals(0,link.size());
        }
        @Test
        public void testContains(){
            assertEquals(false,link.contains("20162324"));
            link.add("1");
            link.add("2");
            link.add("20162324");
            assertEquals(false,link.contains(3));
            assertEquals(true,link.contains("20162324"));
        }
        @Test
        public void testGet(){
            for (int i = 0;i < 100;i++ ){
                link.add(i);
            }
            assertEquals("element",0,link.element());
            assertEquals("get",0,link.get(0));
            assertEquals("get",99,link.get(99));
            assertEquals("getFirst",0,link.getFirst());
            assertEquals("getLast",99,link.getLast());
            link.add(1);
            link.add(100);
            assertEquals("indexOf",1,link.indexOf(1));
            assertEquals("indexOf",101,link.indexOf(100));
            assertEquals("lastIndexOf",100,link.lastIndexOf(1));
        }
        @Test
        public void testOffer(){
            for (int i = 1;i < 21;i++ ){
                link.add(i);
            }
            link.offer(21);
            assertEquals("offer",21,link.size());
            assertEquals("offer",21,link.get(20));
            link.offerFirst(0);
            assertEquals("offerFirst",22,link.size());
            assertEquals("offerFirst",0,link.get(0));
            link.offerLast(22);
            assertEquals("offerLast",22,link.getLast());
        }
        @Test
        public void testPeek(){
            assertEquals("peek",null,link.peek());
            assertEquals("peekFirst",null,link.peekFirst());
            assertEquals("peekLast",null,link.peekLast());
            for (int i = 1;i < 21;i++ ){
                link.add(i);
            }
            assertEquals("peek",1,link.peek());
            assertEquals("peekFirst",1,link.peekFirst());
            assertEquals("peekLast",20,link.peekLast());
        }
        @Test
        public void testPoll(){
            assertEquals("poll",null,link.poll());
            assertEquals("poolFirst",null,link.pollFirst());
            assertEquals("pollLast",null,link.pollLast());
            for (int i = 1;i < 21;i++ ){
                link.add(i);
            }
            assertEquals(20,link.size());
            assertEquals("poll",1,link.poll());
            assertEquals(19,link.size());
            assertEquals("poolFirst",2,link.pollFirst());
            assertEquals(18,link.size());
            assertEquals("pollLast",20,link.pollLast());
            assertEquals(17,link.size());
        }
        @Test
        public void testP(){
            assertEquals(0,link.size());
            link.push("2");
            assertEquals("push",1,link.size());
            assertEquals("pop","2",link.pop());
            assertEquals(0,link.size());
        }
        @Test
        public void testRomve(){
            for (int j = 1;j < 11;j++)
            for (int i = 1;i < 6;i++ ){
                link.add(i);
            }
            assertEquals("remove",1,link.remove());
            assertEquals("remove--有参数",3,link.remove(1));
            assertEquals("removeFirst",2,link.removeFirst());
            assertEquals("removeLast",5,link.removeLast());
            assertEquals("removeLastOccurrence",true,link.removeLastOccurrence(4));
            assertEquals("removeLastOccurrence",false,link.removeLastOccurrence(6));
            assertEquals("removeLastOccurrence",3,link.removeLast());
            assertEquals("removeFirstOccurrence",true,link.removeFirstOccurrence(4));
            assertEquals("removeFirstOccurrence",false,link.removeFirstOccurrence(6));
            assertEquals("removeFirstOccurrence",5,link.removeFirst());
        }
    }
    

    项目二

    分别用Java的ArrayList和LinkedList实现有序线性表的合并:
    aList,bList都是非递减线性表,合并后也是非递减
     public static List<? extends Comparable> mergeSortedList(List<? extends Comparable> aList,  
                List<? extends Comparable> bList) 
    
    测试mergeSortedList的正确性,要尽量覆盖正常情况,异常情况,边界情况,提交测试代码运行截图,包含学号信息
    
    课下把代码推送到代码托管平台
    
    • 这个实验的实现我用了插入排序的方法实现了这个实验,把短的列表插入到长的列表中避免了元素剩余的问题。

    • 代码
    package exp1.test2;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    /**
     * Created by 春旺 on 2017/9/24.
     */
    public class mergeSortedList {
        public static List<? extends Comparable> mergeSortedArrayList
                (List<? extends Comparable> aList,
                 List<? extends Comparable> bList){
            ArrayList array = new ArrayList();
            if (aList.size() >= bList.size()) {
                for (int i = 0;i < aList.size();i ++){
                    array.add(aList.get(i));
                    for (int j= 0;j<bList.size();j++){
    
                        if (aList.get(i).compareTo(bList.get(j)) < 0){
                            array.add(bList.get(j));
                            break;
                        }
                    }
                }
            }
            else {
                for (int i = 0;i < bList.size();i ++){
                    array.add(bList.get(i));
                    for (int j= 0;j<bList.size();j++){
    
                        if (aList.get(i).compareTo(bList.get(j)) < 0){
                            array.add(aList.get(j));
                            break;
                        }
                    }
                }
            }
    return array;
        }
        public static List<? extends Comparable> SortedLinkedList
                (List<? extends Comparable> aList,
                 List<? extends Comparable> bList){
            LinkedList array = new LinkedList();
            if (aList.size() >= bList.size()) {
                for (int i = 0;i < aList.size();i ++){
                    array.add(aList.get(i));
                    for (int j= 0;j<bList.size();j++){
    
                        if (bList.get(i).compareTo(aList.get(j)) < 0){
                            array.add(bList.get(j));
                            break;
                        }
                    }
                }
            }
            else {
                for (int i = 0;i < bList.size();i ++){
                    array.add(bList.get(i));
                    for (int j= 0;j<bList.size();j++){
    
                        if (aList.get(i).compareTo(bList.get(j)) < 0){
                            array.add(aList.get(j));
                            break;
                        }
                    }
                }
            }
    
    return array;
        }
    }
    
    • 测试
    package exp1.test2;
    import org.junit.Test;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    import static org.junit.Assert.*;
    
    /**
     * Created by 春旺 on 2017/9/25.
     */
    public class mergeSortedListTest {
        mergeSortedList ma = new mergeSortedList();
        @Test
        public void mergeSortedArrayList() throws Exception {
           List alist = new ArrayList();
           alist.add(1);
            alist.add(3);
            alist.add(5);
            alist.add(7);
            List blist = new ArrayList();
            blist.add(2);
            blist.add(4);
            blist.add(4);
            blist.add(6);
            List clist = new ArrayList();
            clist.add(1);
            clist.add(2);
            clist.add(3);
           //clist.add(4);
            clist.add(4);
            clist.add(5);
            clist.add(6);
           clist.add(7);
            assertEquals(clist,ma.mergeSortedArrayList(alist,blist));
        }
    
        @Test
        public void mergeSortedLinkedList() throws Exception {
            List alist = new LinkedList();
            alist.add(1);
            alist.add(3);
            alist.add(5);
            alist.add(7);
            List blist = new LinkedList();
            blist.add(2);
            blist.add(4);
            blist.add(6);
            List clist = new LinkedList();
            clist.add(1);
            clist.add(2);
            clist.add(3);
            clist.add(4);
            clist.add(5);
            clist.add(6);
            clist.add(7);
            assertEquals(clist,ma.mergeSortedArrayList(alist,blist));
    
        }
    }
    

    项目三

    参考Java Foundation 3rd 第15.6节,用数组实现线性表List
    
    用JUnit或自己编写驱动类对自己实现的ArrayList进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
    
    课下把代码推送到代码托管平台
    
    • 对于这个类的实现我用了老师在实现Bag类时提供的接口,并且删除了其中的几个方法,并且实现了这几个方法来达到用数组实现列表的目的。因为数组中没有太多的方法所以就不得不自己编写这些方法来实现。

    • 代码
    package exp1.test3;
    /**
     * Created by 春旺 on 2017/9/25.
     */
    public class List<T> implements ListInterface<T> {
        public Object [] arry = new Object[100];
        /*
        声明一个整形数记录非空的元素
        用循环遍历数组不为空时size 加一
        为空继续循环
        */
        @Override
        public int getCurrentSize() {
            int size = 0;
            for (int i = 0; i < arry.length; i++){
                if (arry[i] != null){
                    size = size + 1;
                }
            }
            return size;
        }
        /*
        遍历数组一发现有非空元素就就变为false 并结束循环
        */
        @Override
        public boolean isEmpty() {
            boolean b = true;
            for (int i = 0;i < arry.length;i++){
                if (arry[i] != null){
                    b = false;
                    break;
                }
            }
    
            return b;
        }
        /*
        遍历数组,在第一个非空的的数组元素并将其变成输入的元素
        */
        @Override
        public boolean add(T newEntry) {
            boolean b = false;
            for (int i = 0;i < arry.length;i++){
                if (arry[i] == null){
                    arry[i] = (Object) newEntry;
                    b = true;
                    break;
                }
            }
    
            return b;
        }
        /*
        随意删除,所以将第一个非空的元素变成null
        */
        @Override
        public T remove() {
            T t = null;
            for (int i = 0;i < arry.length;i++){
                if (arry[i] != null){
                    t = (T)arry[i];
                    arry[i] = null;
                    break;
                }
            }
    
            return t ;
        }
        /*
        先查找目标元素,未找到返回false。
    
        for循环遍历数组将所有的目标元素变成
        */
        @Override
        public boolean remove(T anEntry) {
            boolean b = false;
            for (int i =0; i < arry.length;i++){
                if (anEntry == arry[i]){
                    arry [i] = null;
                    b = true;
                }
            }
            return b;
        }
        /*
        删除所有的元素就将原先声明的数组清空
        */
        @Override
        public void clear() {
            for (int i = 0;i< 100;i++) {
                arry[i] = null;
            }
        }
        /*遍历数组将目标元素与数组中的元素一一比较
        如果相等就进行计数,返回计数后的总的值
        */
        @Override
        public int getFrequencyOf(T anEntry) {
            int number = 0;
            for (int i =0; i < arry.length;i++){
                if (anEntry == arry[i]){
                    number ++;
                }
            }
            return number;
        }
        /* 遍历数组将目标元素与数组中的元素一一比较
        只要发现有数组中的元素与目标元素相等就退出循环*/
        @Override
        public boolean contains(T anEntry) {
            boolean b = false;
            for (int i =0; i < arry.length;i++){
                if (anEntry == arry[i]){
                    arry [i] = null;
                    b = true;
                    break;
                }
            }
            return b;
        }
    }
    
    • 测试
    package exp1.test3;
    import ClassTest.Student;
    import org.junit.Test;
    import static org.junit.Assert.*;
    
    /**
     * Created by 春旺 on 2017/9/25.
     */
    public class ListTest {
        List<Student> list= new List<>();
        Student s1 = new Student();
        @Test
        public void getCurrentSize() throws Exception {
            Student s1 = new Student();
            assertEquals(0,list.getCurrentSize());
          list.add(s1);
            assertEquals(1,list.getCurrentSize());
        }
        @Test
        public void isEmpty() throws Exception {
            assertEquals(true,list.isEmpty());
            Student s1 = new Student();
            list.add(s1);
            assertEquals(false,list.isEmpty());
        }
        @Test
        public void add() throws Exception {
            assertEquals(true,list.add(null));
            list.add(s1);
            assertEquals(true,list.add(s1));
        }
        @Test
        public void remove() throws Exception {
            list.add(s1);
            list.remove();
            assertEquals(0,list.getCurrentSize());
        }
        @Test
        public void remove1() throws Exception {
            Student s2 = new Student();
            Student s3 = new Student();
            Student s4 = new Student();
            list.add(s1);  list.add(s2);
            list.add(s3);   list.add(s4);
            list.add(s1);   list.add(s2);
            list.add(s3);  list.add(s4);
            assertEquals(8,list.getCurrentSize());
            list.remove(s2);
            assertEquals(6,list.getCurrentSize());
        }
        @Test
        public void clear() throws Exception {
            for (int i = 0;i<100;i++){
                list.add(s1);
            }
            assertEquals(100,list.getCurrentSize());
            list.clear();
            assertEquals(0,list.getCurrentSize());
    
        }
        @Test
        public void getFrequencyOf() throws Exception {
            Student s2 = new Student();
            Student s3 = new Student();
            for (int i = 0;i < 50;i++){
                list.add(s2);
                list.add(s1);
            }
            assertEquals(50,list.getFrequencyOf(s1));
            assertEquals(0,list.getFrequencyOf(s3));
        }
        @Test
        public void contains() throws Exception {
            Student s2 = new Student();
            Student s3 = new Student();
            for (int i = 0;i < 50;i++){
                list.add(s2);
                list.add(s1);
            }
            assertEquals(true,list.contains(s2));
            assertEquals(false,list.contains(s3));
        }
    }
    

    项目四

    参考Java Foundation 3rd 第15.7节,用链表实现线性表List
    
    用JUnit或自己编写驱动类对自己实现的LinkedList进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
    
    课下把代码推送到代码托管平台
    
    • 对于这个实验来说与实验三比较的相似,只是LinkedList相对于数组来说有更多的方法可以调用减少了我们自己编写这个麻烦。

    • 代码

    package exp1.test4;
    import java.util.LinkedList;
    /**
     * Created by 春旺 on 2017/9/25.
     */
    public class Linked<T> implements LinkedInterface<T> {
        LinkedList linked = new LinkedList<T>();
        @Override
        public void add(Object newEntry) {
            linked.add(newEntry);
        }
        @Override
        public void remove(Object anEntry) {
            linked.remove(anEntry);
        }
        @Override
        public boolean contains(Object anEntry) {
            boolean b = false;
            if (linked.contains(anEntry))
                b = true;
            return b;
        }
    }
    
    • 测试
    package exp1.test4;
    
    import org.junit.Test;
    
    import static org.junit.Assert.*;
    
    /**
     * Created by 春旺 on 2017/9/25.
     */
    public class LinkedTest {
        Linked list = new Linked();
        @Test
        public void add() throws Exception {
            assertEquals(false,list.contains(1));
            list.add(1);
            assertEquals(true,list.contains(1));
    
        }
    
        @Test
        public void remove() throws Exception {
            list.add(1);
            list.add(2);
            assertEquals(true,list.contains(1));
            assertEquals(true,list.contains(2));
            list.remove(2);
            assertEquals(false,list.contains(2));
            list.remove(1);
            assertEquals(false,list.contains(1));
        }
    
        @Test
        public void contains() throws Exception {
            assertEquals(false,list.contains("20162324"));
            list.add("20162324");
            list.add("春旺");
            assertEquals(true,list.contains("春旺"));
            assertEquals(false,list.contains("道巴"));
    
        }
    }
    

    项目五 源码分析

    ArrayList

    • 方法比较多我就分析了常用的几个方法。
    • add方法
    public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    
    
    • 加入元素,再加入之前把数组的的大小先扩大之后再加入元素,在赋值给elementData的最后有个个元素
      ,在把size加大
     public void add(int index, E element) {
            rangeCheckForAdd(index);
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }
    
    • 这个方法与上面的那个方法很相似只是将原先在最后加入得元素改成了在index处插入,并且原先在这个位置的元素并没有被删除只是向后移动了而已。
    • 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;  
    
            return oldValue;
        }
    
    • 这个方法在删除元素时的做法与加入元素时相反在删除元素之后就将size减小。

    • clear方法

      public void clear() {
            modCount++;
    
            // clear to let GC do its work
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    
            size = 0;
        }
    
    • 遍历数组将每一个元素变为null,最后是大小变为0;

    LikedList

    • 私有方法
    private E unlinkFirst(Node<E> f) {
            // assert f == first && f != null;
            final E element = f.item;
            final Node<E> next = f.next;
            f.item = null;
            f.next = null; // help GC
            first = next;
            if (next == null)
                last = null;
            else
                next.prev = null;
            size--;
            modCount++;
            return element;
        }
    
        /**
         * Unlinks non-null last node l.
         */
        private E unlinkLast(Node<E> l) {
            // assert l == last && l != null;
            final E element = l.item;
            final Node<E> prev = l.prev;
            l.item = null;
            l.prev = null; // help GC
            last = prev;
            if (prev == null)
                first = null;
            else
                prev.next = null;
            size--;
            modCount++;
            return element;
        }
    
    • 这两个方法就是为了之后的Remove做的准备。remove有很多的形式,所以有了这两个方法来删除最后一项和第一项。

    • 静态方法

    private void linkFirst(E e) {
            final Node<E> f = first;
            final Node<E> newNode = new Node<>(null, e, f);
            first = newNode;
            if (f == null)
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
        }
    
     void linkLast(E e) {
            final Node<E> l = last;
            final Node<E> newNode = new Node<>(l, e, null);
            last = newNode;
            if (l == null)
                first = newNode;
            else
                l.next = newNode;
            size++;
            modCount++;
        }
    
        void linkBefore(E e, Node<E> succ) {
            // assert succ != null;
            final Node<E> pred = succ.prev;
            final Node<E> newNode = new Node<>(pred, e, succ);
            succ.prev = newNode;
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            size++;
            modCount++;
        }
    
    • 这三个方法是服务于add的相关的方法,用来加入元素并且将大小不断地扩大容量。

    • 体会

    对于java源代码的分析我最大的体会就是复用性,在我们平时写代码的时候可能不太注意这一点,而在分析源代码是我就发现一个最大的特点就是,他的代码几乎是没有重复,写出来来很多的小的方法,然后就相互调用,大大的提高的方法。
    
    还有一点就是在分析的过程中最大的就是源代码实现方法的方式,他们的思路很清晰,我们可以借鉴他们的思路来实现更多的方法,来使我们的程序更高效。
    
  • 相关阅读:
    SDOI2008 Sandy的卡片
    BZOJ2555 Substring
    CTSC2012 熟悉的文章
    递增
    丢失的牛
    【模板】点分治
    陌上花开(三维偏序)
    Holes(河鼠入洞)
    弹飞河鼠
    树状数组1
  • 原文地址:https://www.cnblogs.com/CHUNWANG/p/7598310.html
Copyright © 2020-2023  润新知