201621123086 《Java程序设计》第8周学习总结

1. 本周学习总结

  • List 必须按照插入的顺序保存元素
  • Set不能有重复元素
  • ArrayList ,它长于随机访问元素,但是在List的中阅插入和移除元素时较慢。
  • LinkedList,它进行插入和删除操作代价较低, LinkedList在随机访问方面相对比较慢。LinkedList具有能够直接实现栈的所有功能的方法,因此可以直接将LinkedList作为栈使用。
  • iterator()方放返回的是实现 Iterator的匿名内部类的实例
  • HashMap、HashSet提供快速查询、访问;TreeMap、TreeSet有持续排序特性。
  • 新程序中不应该使用过时的Vector、Hashtable、stack

2. 书面作业

1. ArrayList代码分析

1.1 解释ArrayList的contains源代码

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    /**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     */
    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方法。其内部是用数组实现的,如果在数组中找到传入的元素,则返回其下标数字,如果没有找到则返回-1。根据indexOf方法的返回值,-1代表不包含此元素,若>=0则包含。为防止空指针错误,indexOf方法分为null与非null两种情况。

1.2 解释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

        return oldValue;
    }

答: 此方法作用在于移除某个元素,并将其后面元素左移一位。首先通过rangeCheck(index);方法查询是否传入下标超过边界。numMoved用来记录元素移动个数。
System.arraycopy(elementData, index+1, elementData, index,numMoved);将index+1开始的数组复制到index位。随后将size--,再将最后一位设置为null,返回删除元素。

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

答: 不需要考虑。
理论上来说,ArrayList不能储存基本数据类型,但存至ArrayList的基本数据类型会进行自动包装。

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

答:

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

通过ensureCapacityInternal(size + 1);方法确保容量足够。

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

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

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

此方法先验证elementData是否为空数组,如果为空,则在10与传入的长度参数中选择最大值作为数组长度。
随后,数组长度如果不够,则调用grow(minCapacity);方法。

 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);
    }

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

通过grow(minCapacity);方法。容量增大原来的一半。最后判断数组容量,如果小于0则报错,如果大于最大容量则将容量设为最大容量MAX_ARRAY_SIZE

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

答: 因为面向对象编程需要将一些细节隐藏起来,这样既简化了程序员的编写流程,也增加了安全性。

2. HashSet原理

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

答: 系统通过 Hash 算法决定集合元素的存储位置。调用map.put(e, PRESENT)方法。

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

计算Hash值确定存储位置,如果此位置没有元素,则将其存储在这一位置,如果有元素则判断HASH值是否相同,如果相同则将其赋给此位置,如果不同则继续循环链表加在后面。

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

如果Key值为null,返回0;如果Key值不为空,返回原hash值和原hash值无符号右移16位的值按位异或的结果,在从网上查阅资料后,了解到这是“扰动函数”,作用在于减少碰撞次数,增加效率。

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

答: 时间复杂度为O(1)

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

2.1分析了一部分,但putval方法内部不是很理解。

3. ArrayListIntegerStack

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

实现方式上:private Integer[] stack;List<Integer> stack = new ArrayList<Integer>();两种实现方式各有特点。
ArrayList不存在栈满的情况,因为它会自动扩充容量。
当要删除元素时ArrayList直接调用remove,而数组则是调整top值作为下标。

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

答: 我们在编写此题时,因为题目已经给出了实现方式,所以我们不需要考虑实现方式的优缺点。
但当我们要用LinkedList是现实,如果没有接口,我们就只能重写所有代码。存在接口,实现方式可以被简便的替换,而不影响其他内部方法与实现。
同时我们也可以明确这个接口的作用,使得代码更加规范化、流程化。我们一眼就可以明晰public Integer push(Integer item)是入栈,public Integer pop()是出栈。

4. Stack and Queue

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

package week7;
import java.util.LinkedList;
import java.util.Scanner;



class Stack<Object> {
    private LinkedList<Object> stack = new LinkedList<Object>();
    public void push(Object obj) {
        stack.addFirst(obj);
    }
    
    
    public Object peek() {
        return stack.getFirst();
    }
    public Object pop() {
        return stack.removeFirst();
    }
    public boolean empty() {
        return stack.isEmpty();
    }
    public String toString() {
        return stack.toString();
    }
}


public class Main201621123086 {
    public static void main(String[] args) {
        Stack<Character> stack = new Stack<Character>();
        Scanner sc = new Scanner(System.in);
        char[] str = new char[20];
        while (sc.hasNextLine()){
            String string = sc.nextLine();
        boolean flag = true;
        for (int i = 0; i < string.length(); i++) {
            stack.push(string.charAt(i));
        }
        for (int i = 0; i < string.length(); i++) {
            if (stack.pop() != string.charAt(i)) {
            	System.out.println("不是回文");
            	flag = false;
                break;
            }
        }
        
        if (flag) 
            System.out.println("是回文");}
    }
}

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


LinkedList实现类

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

5.1 实验总结

通过set来过滤重复元素,通过TreeSet排序元素

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

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

主要在商品列表与购物车列表运用了ArrayList集合类。
同时,也可以在购物车列表上运用Hashset来避免重复加入。

7.2 进一步完善图形界面(仅需出现改进的后的图形界面截图)

主要是在购物车上完成了总价的输出,以及解决购物车列表的刷新

3.码云及PTA

3.1. 码云代码提交记录

3.2 截图PTA题集完成情况图


3.3 统计本周完成的代码量

周次 总代码量 新增代码量 总文件数 新增文件数
1 0 0 0 0
2 0 0 0 0
3 619 619 15 15
4 619 0 15 0
5 973 354 25 10
6 1394 421 37 12
7 2001 607 43 6
8 4046 2045 54 11
9 4486 440 64 10
posted @ 2017-11-11 17:25  pirrat  阅读(168)  评论(1编辑  收藏  举报