201621123063《Java程序设计》第8周实验报告

1. 本周学习总结

2. 书面作业

1. ArrayList代码分析

1.1 解释ArrayList的contains源代码

以下是ArrayList的contains源代码:


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


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

可以看到,ArrayList的contains方法就是遍历ArrayList,用equals方法逐个和ArrayList中的成员比较是否相同,若ArrayList中存在传入的元素返回true,否则返回false(包括传入参数为null的情况)。

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

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

删除ArrayList中指定位置的元素。 用rangeCheck()方法检查索引范围,把删掉元素后的所有元素前移一位,原来的最后一个元素的位置置null。

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

不需要,Object类是所有类的终极父类,但要注意不能存放基本数据类型(如int,double型)。

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

add源代码如下:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    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);
    }
    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);
    }

可以看出,当内部数组容量不够时,调用grow方法生成一个容量大小为原来数组1.5倍的新数组,用Arrays.copyOf()方法把原数组中的数据拷贝到新数组中。

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

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

rangeCheck()方法用于越界判断,越界时抛出异常声明,只需要在ArrayList类中调用,因此声明为private

2. HashSet原理

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

调用hashCode()方法得出将存入的元素对应的hashcode的值,以此得到元素在哈希表中的存放位置,HashSet中不存放相同的元素,因此再调用equals()方法比较将存入的元素和该位置已有的元素是否相同,相同则不存入,不相同则用解决散列冲突的方法将元素添加入HashSet中。

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

是O(1),直接根据哈希码找到元素在哈希表中的对应位置并插入。

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

以下是HashSet的add()方法源码:

public boolean add(E e) {  
   return map.put(e, PRESENT)==null;  
   }  

可以看出,HashSet底层使用HashMap来保存所有元素
以下是HashMap的put方法

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
}
 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

1.调用hash函数得到key的HashCode值
2.通过HashCode值与数组长度-1逻辑与运算得到一个index值
3.遍历索引位置对应的链表,如果Entry对象的hash值与hash函数得到的hash值相等,并且该Entry对象的key值与put方法传过来的key值相等则,将该Entry对象的value值赋给一个变量,将该Entry对象的value值重新设置为put方法传过来的value值。将旧的value返回。
4.添加Entry对象到相应的索引位置

3. ArrayListIntegerStack

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

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

最主要的区别就是数据结构的不同,ArrayListIntegerStack是采用ArrayList实现,而ArrayIntegerStack采用数组实现,前者不用担心栈满,出栈时直接调用ArrayList的remove()方法。

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

以3.1为例,实现了IntegerStack接口后,不论是用ArrayList还是数组实现都可以,它们所实现的功能都是借口中抽象的。接口可以被多个类声明,只要根据接口写出具体实现的类,对多人并行开发来说很重要。

4. Stack and Queue

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

public class Main201621123063 {

	public static void main(String[] args) {
		while(true)
		{
		Scanner in = new Scanner(System.in);
		String str = in.nextLine();
		if(isHuiWen(str) == true)
			System.out.println("是回文");
		else
			System.out.println("不是回文");
		}

	}
	public static boolean isHuiWen(String str)
	{
		 List<Character>  stack = new ArrayList<Character>();//用ArrayList的add(),remove()来模拟进栈和出栈
		  List<Character>  stack2 = new ArrayList<Character>();
		  int halfLength = str.length()/2;
		  
		  for(int i = 0;i < halfLength;i++){
		   stack.add(str.charAt(i));
		   stack2.add(str.charAt(str.length()-i-1));
		  }
		  boolean flag = true;
		  for(int i = halfLength-1;i >= 0;i--){
		   if(stack.remove(i) != stack2.remove(i)){
		    flag = false;
		    break;
		   }
		  }
		  return flag;
	}
}

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

使用LinkedList实现类

if(aQueue.size()<2) 
		{
			System.out.println(aQueue.removeFirst());
			while(!bQueue.isEmpty())
				System.out.print(" "+bQueue.removeFirst());
		}
		else
		{
			System.out.print(aQueue.removeFirst());
			System.out.print(" "+aQueue.removeFirst());
			System.out.print(" "+bQueue.removeFirst());
		}
		if(bQueue.isEmpty())
		{
			System.out.print(aQueue.removeFirst());
			while(!aQueue.isEmpty())
				System.out.print(" "+aQueue.removeFirst());
		}
		while(!aQueue.isEmpty()&& !bQueue.isEmpty())
		{
			System.out.print(" "+aQueue.removeFirst());
			System.out.print(" "+aQueue.removeFirst());
			System.out.print(" "+bQueue.removeFirst());
		}
		while(!aQueue.isEmpty())
		{
			System.out.print(" "+aQueue.removeFirst());
		}
		while(!bQueue.isEmpty()) 
		{
			System.out.print(" "+bQueue.removeFirst());
		}

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

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

5.1 实验总结

用TreeSet可以直接实现按字母顺序排序

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

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

6.1 伪代码

1.用HashMap存储统计单词数量
2.实现比较器先按次数降序,然后再按key字母升序
3.输出出现次数前十的单词

6.2 实验总结

if(map.containsKey(str)) 
				map.put(str, map.get(str)+1);

把String作为Value,出现次数为key值,统计输出

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

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

购物车中使用List来储存GoodsInfomation类对象

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

3.码云及PTA

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

3.1. 码云代码提交记录

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

3.2 截图PTA题集完成情况图

需要有两张图(1. 排名图。2.PTA提交列表图)

3.3 统计本周完成的代码量

周次 | 行数 | 新增行数 | 文件数 | 新增文件数 |

  • | :-: | :-: | :-: | :-:
    1 | 226 | 226 | 45 | 45 |
    2 | 377 | 377 | 7 | 7 |
    3 | 712 | 281 | 42| 9 |
    4 | 166 | 166 | 2 | 2|
    5 | 253 | 253 | 4 | 4|
    6 | 484 | 484 | 9 | 9|
    7 | 269 | 269 |1 | 1 |
    8 | 301 | 32 | 5 | 4|
posted @ 2017-11-11 16:46  Yelz  阅读(275)  评论(1编辑  收藏  举报