1. 本周学习总结

2. 书面作业

1. ArrayList代码分析

1.1 解释ArrayList的contains源代码

contains的源代码及解释:

public boolean contains(Object o) {
    return indexOf(o) >= 0;
  }  
public int indexOf(Object o) {    //找到o返回当前位置i,否则返回-1
    if (o == null) {           //当o为null时
        for (int i = 0; i < size; i++)        //判断ArrayList中是否含有null元素,有返回当前位置i,没有返回-1  
            if (elementData[i]==null)
                return i;
    } else {                    //当o不为null时,用equals方法判断ArrayList中是否含有该元素,有返回当前位置i,没有返回-1 
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

1.2 解释E remove(int index)源代码

E remove(int index)的源代码及解释:

 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     
                                                           //最后一个元素置为空,size自减一次
        return oldValue;                          //返回被删除的元素
    }
 private void rangeCheck(int index) {     //判断要删除的位置是否合理
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

1.3 结合1.1与1.2,回答ArrayList存储数据时需要考虑元素的具体类型吗?

不需要,ArrayList内部数组是Object数组实现的,Object类是超级父类,所以只要存储进去的数据类型是引用数据类型而不是基本数据类型,就可以将其存储进去

1.4 分析add源代码,回答当内部数组容量不够时,怎么办?

public boolean add(E e) {
    ensureCapacityInternal(size + 1);    //size+1为需要的最小容量
    elementData[size++] = e;               //将e加入列表
    return true;
}

private void ensureCapacityInternal(int minCapacity) {    
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {   //当数组是默认长度的空数组时,取10和传入参数的最大值,即最小数组容量最小为10
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);   //DEFAULT_CAPACITY = 10,    
    }

    ensureExplicitCapacity(minCapacity);   

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)    //需要的最小数组容量大于数组长度时,扩容
        grow(minCapacity);
}

private void grow(int minCapacity) {    
    // overflow-conscious code
    int oldCapacity = elementData.length;      
    int newCapacity = oldCapacity + (oldCapacity >> 1);    //扩容1.5倍
    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);     //将原来的复制到新的数组中
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

1.5 分析private void rangeCheck(int index)源代码,为什么该方法应该声明为private而不声明为public?

源代码:

private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} 

修饰为private体现了封装性,这里以remove方法为例,用户或其他类调用remove方法时,remove方法会自动调用rangeCheck方法判断数组下标是否出界,用户或其他类不需要知道rangeCheck这个方法,只要知道remove方法是否删除成功即可。

2. HashSet原理2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?

2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?

先用HasCode方法确定要加入的位置,若要加入的位置没有其他元素,则将该元素加入该位置,若要加入的位置有其他元素,用equals方法判断这个位置的桶中是否有相同元素,若有,则不加入,若没有,则将该元素加入该位置

2.2 将元素加入HashSet中的时间复杂度是多少?是O(n)吗?(n为HashSet中已有元素个数)

时间复杂度为O(1)而不是O(n),因为将元素加入HashSet不需要遍历HashSet中的元素,是直接计算出要加入的位置,然后直接添加,所以时间复杂度为O(1)。

2.3 选做:尝试分析HashSet源代码后,重新解释2.1

3. ArrayListIntegerStack

3.1 比较自己写的ArrayListIntegerStack与自己在题集jmu-Java-04-面向对象2-进阶-多态、接口与内部类中的题目自定义接口ArrayIntegerStack,有什么不同?(不要出现大段代码)

本次题集中栈的定义

以前题集中栈的定义

不同之处:

  • 两次题集栈的实现方式不同,本次题集用列表实现栈,以前题集用长度一定的数组实现栈。
  • 动态数组实现不用另外设栈顶指针,用list.get(list.size()-1)即可获得栈顶元素,数组实现需要栈顶指针来获得栈顶元素及判断是否满栈
  • 动态数组实现不用判断栈满的条件,因为动态数组容量不够时会自动扩容,数组实现以为长度一定,所以需要判断满栈情况
  • 动态数组获取元素个数用list.size()即可实现,数组实现需要将栈顶指针加1获得元素个数

总之,动态数组因为有很多现成的方法及自动扩容的能力,使得用动态数组实现栈比用数组实现栈来的方便,快捷

3.2 结合该题简单描述接口的好处,需以3.1为例详细说明,不可泛泛而谈。

用接口最大的好处就是提高编程的灵活性,本题ArrayIntegerStack实现了IntegerStack接口,IntegerStack接口中定义了入栈,出栈,获取栈顶元素,判断是否是空栈,返回栈中元素个数五个方法,这五个方法只有方法名,没有方法体,之后的类实现这个接口后,编程人员可以用各种各样不同的方式实现这个接口,比如列表实现或是数组实现,方便编程人员的使用

4. Stack and Queue

4.1 编写函数判断一个给定字符串是否是回文,一定要使用栈(请利用Java集合中已有的类),但不能使用java的Stack类(具体原因自己搜索)与数组。请粘贴你的代码,类名为Main你的学号

代码截图:

运行结果:

4.2 题集jmu-Java-05-集合之银行业务队列简单模拟(只粘贴关键代码)。请务必使用Queue接口,并说明你使用了Queue接口的哪一个实现类?

代码截图:

使用了LinkList的实现类

5. 统计文字中的单词数量并按单词的字母顺序排序后输出

5.1实验总结

首先根据题目确定要用Set接口的实现类TreeSet,接着将除了!!!!!之外的所有单词加入TreeSet中,TreeSet会对加入其中的单词进行排序,最后如果TreeSet中的元素个数小于10个的话,将其所有的元素输出,如果TreeSet中的元素个数大于10个,输出前十个元素,用TreeSet的size()方法输出单词的总数量

6. 选做:统计文字中的单词数量并按出现次数排序

6.1 伪代码

  • 用HashMap实现从单词到数量映射的存储
  • 将HashMap转化为ArrayList,用Comparator匿名内部类实现排序
  • 输出不重复的单词的总数量
  • 不重复的单词数量小于10个,输出所有单词,不重复的单词数量大于10个,输出排名前十的单词

6.2 实验总结

  • 首先根据题目的要求要实现单词数量的递减排序,若单词数量相同,则实现首字母递增排序,这里不能用TreeMap,因为TreeMap只能对键值实现递增排序,所以只要用HashMap,然后再将HashMap转化为ArrayList,对列表运用Comparator比较器进行排序即可
  • 单词插入HashMap中时,要先判断原来的HashMap是否已经包含该单词,若有,新的次数等于原来的次数加1,然后重新加入HashMap中,若没有,则将次数置为1,加入HashMap中

这一题比较难的是将HashMap转化为ArrayList,然后用Comparator比较器结合匿名内部类实现排序,将代码展示如下:

7. 选做 面向对象设计大作业-改进

7.1 使用集合类改进大作业或者简述你的面向对象设计大作业中,哪里使用到了集合类。

购物车类存储商品信息用到ArrayList列表

3.码云及PTA

3.1. 码云代码提交记录

3.2 截图PTA题集完成情况图




3.3 统计本周完成的代码量

周次 总代码量 新增代码量 总文件数 新增文件数
2 343 343 10 10
3 498 498 8 8
5 788 788 26 26
6 536 536 16 16
7 776 776 9 9
8 846 846 4 4
9 668 668 12 12
posted on 2017-11-11 20:23  谢晗-网络1613  阅读(179)  评论(2编辑  收藏  举报