1. 本周学习总结
以你喜欢的方式(思维导图或其他)归纳总结集合相关内容。
思维导图:
2. 书面作业
2.1ArrayList代码分析
2.1.1 解释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;
}
查找资料:
contains方法中直接调用indexOf方法,indexOf方法中采用equals方法判断
个人理解:查看源代码可以发现,当对象为null,则比较集合中是否含有为null的元素,对象不为null时则比较集合中是否含有该元素。若含有该对象,则返回true。根据这个源代码,感觉如果想找到两个list中不同的部分,可以用ArrayList的contains方法。
2.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;
}
查找资料:JDK的方法介绍
移除此列表中指定位置上的元素
个人理解:阅读源代码可以发现,首先要判断一下该位置是否越界,如果没有越界就将该元素后面的元素整体前移。因为删除了一个元素,数组后面必然会空出位置,所以最后做的就是把数组最后一个元素置为null。
2.1.3 结合1.1与1.2,回答ArrayList存储数据时需要考虑元素的具体类型吗?
查找资料:
ArrayList存的数据是Object类的,取出时是Object,需要强制转化。
个人理解:不需要。所有的类都有超级父类Object,而ArrayList存的数据又是Object类的,这样应该任意元素的类型都是可以存的,就是取出来的时候要转化一下。
2.1.4 分析add源代码,回答当内部数组容量不够时,怎么办?
源代码:
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++;
}
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);
}
个人理解:查看第一个源代码可以发现,add方法会先用 ensureCapacityInternal()方法判断是否有位置进行添加,如果需要进行数组容量的增加则会用ensureExplicitCapacity()方法,而后使用grow(minCapacity)方法进行数组的扩充。
2.1.5 分析private void rangeCheck(int index)源代码,为什么该方法应该声明为private而不声明为public?
源代码:
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* A version of rangeCheck used by add and addAll.
原因:
阅读源代码下面的注释A version of rangeCheck used by add and addAll.
,我认为rangeCheck()方法是用来判断add、addAll方法是否超出了数组容量范围,而add、addAll跟rangeCheck()方法同属于一个类里面,并且private修饰的成员变量以及成员方法只供本类使用
。rangeCheck()属于类内部的方法,一般不会声明为public,因此声明为private更合适。
2.2HashSet原理
2.2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?
存储位置的确定:
个人理解:
HashSet是用哈希表存储的,当要存储一个对象时会先计算哈希值,然后根据哈希值找到该元素在表中的位置,如果表中已经有元素了,就要用到equals方法比较两个元素是否相同,如果不同则添加进去。
查找资料:
HashSet的底层用哈希散列表来存储对象(默认长度为16的数组),
假如:Set set=new HashSet();
set.add(obj);
内部存储过程为:定义h=obj.hashCode,得到obj对象的哈希码h,再对h进行hash散列运算,对数组长度进行求余,假如长度为16,则返回一个0-15之间的值,然后这个值就是存在HashSet数组中的下标。如果下标位置没有对象(不起冲突),则把obj加到该位置;如果已近有对象(起冲突),则用equals判断两对象是否相等,相等则舍弃obj,不相等,则把obj以节点的方式加在该对象下面。
调用方法:equals方法和hashCode方法。
2.2.2 将元素加入HashSet中的时间复杂度是多少?是O(n)吗?(n为HashSet中已有元素个数)
时间复杂度:不是O(n)。由上一题已知HashSet的存储过程,是通过计算哈希值来确定元素应该存储的位置,然后根据比较结果决定是否添加元素,跟元素的个数n并没有关系。所以它的时间复杂度是O(1)。
2.3.ArrayListIntegerStack
题集jmu-Java-05-集合之ArrayListIntegerStack
2.3.1 比较自己写的ArrayListIntegerStack与自己在题集jmu-Java-04-面向对象2-进阶-多态、接口与内部类中的题目自定义接口ArrayIntegerStack,有什么不同?(不要出现大段代码)
不同:这次写ArrayListIntegerStack类是用 ArrayList数据类型实现方法和接口的,而ArrayIntegerStacks类是用Integer数据类型实现方法和接口的。
2.3.2 结合该题简单描述接口的好处,需以3.1为例详细说明,不可泛泛而谈。
好处:由两个程序代码可以发现ArrayListIntegerStack类和ArrayIntegerStacks类都是继承IntegerStack接口的,但是它们实现接口的数据类型不一样,同样的方法实现方式也是不一样的,这体现了面向接口编程的多态性,同一种方法可以有不同的实现。
2.4.Stack and Queue
2.4.1 编写函数判断一个给定字符串是否是回文,一定要使用栈(请利用Java集合中已有的类),但不能使用java的Stack类(具体原因自己搜索)与数组。请粘贴你的代码,类名为Main你的学号。
先插入一个查找的资料:
插入主要部分代码:(其他的函数不粘贴,与05-集合之ArrayListIntegerStack题目的代码基本一样)
运行截图:
2.4.2 题集jmu-Java-05-集合之银行业务队列简单模拟(只粘贴关键代码)。请务必使用Queue接口,并说明你使用了Queue接口的哪一个实现类?
关键代码:(这一题做了很久,感觉需要考虑的情况很多,所以主函数里面的代码很长,不过好像是我把题目给做复杂了,对比一位学霸的代码比我的简洁多了。。。)
实现类:使用了LinkedList实现类。
2.5.统计文字中的单词数量并按单词的字母顺序排序后输出
题集jmu-Java-05-集合之5-2 统计文字中的单词数量并按单词的字母顺序排序后输出 (作业中不要出现大段代码)
2.5.1 实验总结
总结:本题老师在实验课中有提了思路和一些细节的处理,所以做起来还是比较快的。我存在的问题就是第一遍做的时候没有用到TreeSet排序,直接输出了,后来用TreeSet排序再输出就可以了。
2.6 选做:统计文字中的单词数量并按出现次数排序
题集jmu-Java-05-集合之5-3 统计文字中的单词数量并按出现次数排序(不要出现大段代码)
2.6.1 伪代码
步骤:
1.根据上一题,已经做好了单词数量的统计,虽然本题不用字母排序但还是为了方便沿用上一题TreeSet
2.要改变的是需要统计每个单词出现的次数,考虑用HashMap实现对每一个单词进行次数统计
3.重写Collections中的sort方法,对集合中的每个单词次数进行比较并排序
4.输出
2.6.2 实验总结
总结:这一题感觉做起来比较难,特别是第二步的实现。虽然想用HashMap数据类型但是不知道用什么方法,后来是参考同学的代码,发现可以用containsKey的方法进行单词次数统计。
2.7 选做 面向对象设计大作业-改进
2.7.1 使用集合类改进大作业或者简述你的面向对象设计大作业中,哪里使用到了集合类。
使用集合类:购物车中的商品条目和商品编号用到了LinkedHashMap
2.7.2 进一步完善图形界面(仅需出现改进的后的图形界面截图)
使用JTable改进了一下图形界面,截图如下:
查看购物车:
添加商品:
删除商品:
3.码云及PTA
题目集:jmu-Java-05-集合
3.1 码云代码提交记录
在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图
3.2 截图PTA题集完成情况图
需要有两张图(1. 排名图。2.PTA提交列表图)
排名图:
提交列表图:
3.3 统计本周完成的代码量
需要将每周的代码统计情况融合到一张表中。
周数 | 行数 | 新增行数 | 文件数 | 新增文件数 |
---|---|---|---|---|
1 | 57 | 57 | 5027 | 5027 |
2 | 400 | 400 | 10 | 10 |
3 | 508 | 508 | 23 | 13 |
5 | 609 | 609 | 31 | 8 |
6 | 612 | 612 | 40 | 9 |
7 | 584 | 584 | 46 | 6 |
8 | 432 | 432 | 50 | 4 |
9 | 620 | 620 | 56 | 6 |