zoukankan      html  css  js  c++  java
  • 201521123082 《Java程序设计》第7周学习总结

    201521123082 《Java程序设计》第7周学习总结

    标签(空格分隔): Java


    1. 本周学习总结

    以你喜欢的方式(思维导图或其他)归纳总结集合相关内容。


    2. 书面作业

    1.ArrayList代码分析###

    1.1 解释ArrayList的contains源代码####

    Answer:
    先贴上源码:

    个人解析:
    ArrayList中允许存放相同的元素,我们可以使用contains()方法来存放不重复有序的元素集合。
    在源码中我们可以看出contains方法中调用indexOf方法来判断是否包含对象。在indexOf方法中,如果对象为空,elementData[i]也为空,返回i;如果对象不为空,调用equals方法,进行比较,如果与element[i]相同,返回i。


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

    Answer:
    先贴上源码:

    remove(int index)删除ArrayList数组中指定位置上的元素并返回该元素。

    关键解释如下:

    /*numMoved就是index后面的所有的元素个数,即删除的元素后需要移动的元素个数 */
    int numMoved = size - index - 1; 
    
    /*将index后面的所有元素全部往前移动 */
    if (numMoved > 0) 
        System.arraycopy(elementData, index+1, elementData, index, 
        numMoved); 
        
    /*将最后多余的引用置为null. */
        elementData[--size] = null; 
    

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

    Anser:
    1.结合1.1和1.2以及上课内容可以知道ArrayList是一个数组列表,ArrayList只能包含对象类型(Object)。
    2.ArrayList在存放的时候可以是不同种类型的元素,因为ArrayList可以存储Object。所以任何类型的元素都是可以在ArrayList储存。

    ArrayList对象的大小可按照其中存储的数据进行动态增减,所以在声明ArrayList对象时并不需要指定它的长度。但是由于ArrayList会把插入其中的所有数据当作为object类型来处理,在存储或检索值类型时会发生装箱和拆箱操作,带来很大的性能耗损。另外,ArrayList没有泛型的实现,也就是ArrayList不是类型安全的,在我们使用ArrayList处理数据时,很可能会报类型不匹配的错误。


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

    Answer:
    先贴上源码:

     /**
         * Appends the specified element to the end of this list.
         *
         * @param e element to be appended to this list
         * @return <tt>true</tt> (as specified by {@link Collection#add})
         */
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
        
    private void ensureCapacityInternal(int minCapacity) {
            if (elementData == 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);
        }
    
        /**
         * The maximum size of array to allocate.
         * Some VMs reserve some header words in an array.
         * Attempts to allocate larger arrays may result in
         * OutOfMemoryError: Requested array size exceeds VM limit
         */
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
        /**
         * Increases the capacity to ensure that it can hold at least the
         * number of elements specified by the minimum capacity argument.
         *
         * @param minCapacity the desired minimum capacity
         */
        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;
        }
    

    关键代码处的解释:

    // 确定ArrarList的容量。  
        // 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1”  
        public void ensureCapacity(int minCapacity) {  
            // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的  
            modCount++;  
            int oldCapacity = elementData.length;  
            // 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”  
            if (minCapacity > oldCapacity) {  
                Object oldData[] = elementData;  
                int newCapacity = (oldCapacity * 3)/2 + 1;  
                //如果还不够,则直接将minCapacity设置为当前容量
                if (newCapacity < minCapacity)  
                    newCapacity = minCapacity;  
                elementData = Arrays.copyOf(elementData, newCapacity);  
            }  
        }  
     
        // 添加元素e  
        public boolean add(E e) {  
            // 确定ArrayList的容量大小  
            ensureCapacity(size + 1);  // Increments modCount!!  
            // 添加e到ArrayList中  
            elementData[size++] = e;  
            return true;  
        }  
    

    引用及参考:ArrayList简介
    java中数组列表ArrayList的使用


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

    Answer:
    源码:

    /**
         * Checks if the given index is in range.  If not, throws an appropriate
         * runtime exception.  This method does *not* check if the index is
         * negative: It is always used immediately prior to an array access,
         * which throws an ArrayIndexOutOfBoundsException if index is negative.
         */
        private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    

    个人理解:
    用private声明别的用户或者类不能调用,而public则任何用户和类都可以调用。rangeCheck用于边界检查,在类内调用就可以了。

    关于rangeCheck(intindex)源码和ArrayList的学习可以参考:ArrayList 的实现原理


    2.HashSet原理###

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

    Answer:
    个人认识:散列集只能存储不重复的对象.散列表采用Hash算法决定集合元素的存储位置。
    (1)链表是HashSet的存储形式,我们每添加一个元素时,调用hashCode()方法得到其hashCode值,然后确定存储位置。
    (2)hashCode()方法和equals()方法。


    2.2 选做:尝试分析HashSet源代码后,重新解释1.1####

    Answer:
    贴上源码和解释:

    public class HashSet<E> 
    	 extends AbstractSet<E> 
    	 implements Set<E>, Cloneable, java.io.Serializable 
     { 
    	 // 使用 HashMap 的 key 保存 HashSet 中所有元素
    	 private transient HashMap<E,Object> map; 
    	 // 定义一个虚拟的 Object 对象作为 HashMap 的 value 
    	 private static final Object PRESENT = new Object(); 
    	 ... 
    	 // 初始化 HashSet,底层会初始化一个 HashMap 
    	 public HashSet() 
    	 { 
    		 map = new HashMap<E,Object>(); 
    	 } 
    	 // 以指定的 initialCapacity、loadFactor 创建 HashSet 
    	 // 其实就是以相应的参数创建 HashMap 
    	 public HashSet(int initialCapacity, float loadFactor) 
    	 { 
    		 map = new HashMap<E,Object>(initialCapacity, loadFactor); 
    	 } 
    	 public HashSet(int initialCapacity) 
    	 { 
    		 map = new HashMap<E,Object>(initialCapacity); 
    	 } 
    	 HashSet(int initialCapacity, float loadFactor, boolean dummy) 
    	 { 
    		 map = new LinkedHashMap<E,Object>(initialCapacity 
    			 , loadFactor); 
    	 } 
    	 // 调用 map 的 keySet 来返回所有的 key 
    	 public Iterator<E> iterator() 
    	 { 
    		 return map.keySet().iterator(); 
    	 } 
    	 // 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 Set 里元素的个数
    	 public int size() 
    	 { 
    		 return map.size(); 
    	 } 
    	 // 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空,
    	 // 当 HashMap 为空时,对应的 HashSet 也为空
    	 public boolean isEmpty() 
    	 { 
    		 return map.isEmpty(); 
    	 } 
    	 // 调用 HashMap 的 containsKey 判断是否包含指定 key 
    	 //HashSet 的所有元素就是通过 HashMap 的 key 来保存的
    	 public boolean contains(Object o) 
    	 { 
    		 return map.containsKey(o); 
    	 } 
    	 // 将指定元素放入 HashSet 中,也就是将该元素作为 key 放入 HashMap 
    	 public boolean add(E e) 
    	 { 
    		 return map.put(e, PRESENT) == null; 
    	 } 
    	 // 调用 HashMap 的 remove 方法删除指定 Entry,也就删除了 HashSet 中对应的元素
    	 public boolean remove(Object o) 
    	 { 
    		 return map.remove(o)==PRESENT; 
    	 } 
    	 // 调用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素
    	 public void clear() 
    	 { 
    		 map.clear(); 
    	 } 
    	 ... 
     }
    
    • 对于 HashSet 而言,它是基于 HashMap 实现的
    • HashSet封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
      HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。

    3.ArrayListIntegerStack###

    题集jmu-Java-05-集合之5-1 ArrayListIntegerStack

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

    Answer:

    • ArrayIntegerStack是内部实现数组,实例化的时候需要规定大小
    • ArrayListIntegerStack是动态数组,可以用list可以自动扩容
    • ArrayList可以直接找到元素,进行删除,返回的操作

    源码:

    public ArrayIntegerStack(int n) {
    		this.stack = new Integer[n];
    	}
    
    public ArrayListIntegerStack(){
    		list =new ArrayList<Integer>();
    	}
    

    3.2 简单描述接口的好处.####

    Answer:
    接口是一种规范,同样的方法和操作可以有不同的实现,也可以供不同的类使用。上面一题就是很好的例子。


    4.Stack and Queue###

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

    Answer:

    //ArrayListStringStack的代码
    interface StringStack {
    	public String push(String item);
    
    	public String pop();
    
    	public String peek();
    
    	public boolean empty();
    
    	public int size();
    }
    
    class ArrayListStringStack implements StringStack {
    	private List<String> list;
    
    	public ArrayListStringStack() {
    		list = new ArrayList<String>();
    	}
    
    	@Override
    	public String push(String item) {
    		if (item == null)
    			return null;
    		list.add(item);
    		return item;
    	}
    
    	@Override
    	public String pop() {
    		if (list.isEmpty())
    			if (list.size() == 0)
    				return null;
    		return list.remove(list.size() - 1);
    	}
    
    	@Override
    	public String peek() {
    		if (list.size() == 0)
    			return null;
    		return list.get(size() - 1);
    	}
    
    	@Override
    	public boolean empty() {
    		if (list.size() == 0)
    			return true;
    		return false;
    	}
    
    	@Override
    	public int size() {
    		return list.size();
    	}
    
    	@Override
    	public String toString() {
    		return list.toString();
    	}
    
    }
    

    主代码及实现结果:


    4.2 题集jmu-Java-05-集合之5-6 银行业务队列简单模拟。(不要出现大段代码)####

    Aswer:

    题目要求A窗口每处理完2个顾客时,B窗口处理完1个顾客。给定到达银行的顾客序列,请按业务完成的顺序输出顾客序列。假定不考虑顾客先后到达的时间间隔,并且当不同窗口同时处理完2个顾客时,A窗口顾客优先输出。
    其实就是A、B两个队Queue1和Queue2分别按要求输出,关键是判断两个队列的元素是最后一个输出。
    源码和实现结果如下:


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

    题集jmu-Java-05-集合之5-2 统计文字中的单词数量并按单词的字母顺序排序后输出 (不要出现大段代码)

    5.1 实验总结####

    Answer:
    关键源码:

    while (input.hasNext()) {
    			String word = input.next();
    			if (word.equals("!!!!!"))
    				break;
    			//不同的单词加入集合中
    			else if (!str.contains(word))
    				str.add(word);
    		}
    

    运行结果:


    6.选做:加分考察-统计文字中的单词数量并按出现次数排序###

    题集jmu-Java-05-集合之5-3 统计文字中的单词数量并按出现次数排序(不要出现大段代码)

    6.1 伪代码####

    Answer:

    //步骤1
    Map<String, Integer> map = new TreeMap<String,Integer>();
    /*1.输入单词放入map直到出现“!!!”停止
    .....
    .....
    */
    
    //步骤2
    List<Map.Entry<String, Integer>> arrayList = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
    /*用Collections.sort()方法对arrayList存放Map的键值进行排序
    ......
    ......
    */
    
    //步骤3
    for (Map.Entry<String, Integer> entry : arrayList) {
    /*
    按要求输出
    ......
    ......
    */
    }
    


    6.2 实验总结####

    Answer:
    了解Map和List的区别,题目中无法对Map的值排序,转为list后sort来实现功能。
    对于Map,有以下比较好的链接:
    map的详细用法


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

    7.1 完善图形界面(说明与上次作业相比增加与修改了些什么)####

    Answer:
    在上次作业中页面设计已完成得差不多,查看下图:

    本次完善了注册界面设计,如下:

    完善购物车信息,用表格显示的设计:

    可以用Set储存用户账号和商品,可以避免出现账号相同和物品重复的现象。


    3. 码云上代码提交记录及PTA实验总结##

    题目集:jmu-Java-05-集合

    3.1. 码云代码提交记录
    在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图


    3.2. PTA实验
    编程(5-1, 5-2, 5-3(选做), 5-6)
    实验总结已经在作业中体现,不用写。


  • 相关阅读:
    《DSP using MATLAB》Problem 7.16
    《DSP using MATLAB》Problem 7.15
    《DSP using MATLAB》Problem 7.14
    线性基
    P2476-记忆化搜索
    树状数组(板子)
    Codeforces Round #633 (Div. 2) C. Powered Addition
    Codeforces Round #633 (Div. 2) B. Sorted Adjacent Differences
    思维,暴力,打表
    RMQ倍增板子(区间最值查询问题)(静态)
  • 原文地址:https://www.cnblogs.com/moyi-h/p/6682138.html
Copyright © 2011-2022 走看看