201621123061《Java程序设计》第八次学习总结
1. 本周学习总结
以你喜欢的方式(思维导图或其他)归纳总结集合相关内容。

2. 书面作业
1. ArrayList代码分析
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;
}
ArrayList的contains方法调用了indexOf方法。indexOf方法是通过对ArrayList型的对象的遍历,假如对象o找到和它相等的值,则放回该值的位置,否则返回-1。contains方法则是根据indexOf(o) >= 0是否成立来判断,若成立则返回true,即包含,不成立返回false,即不包含。
1.2 解释E remove(int index)源代码
源代码如下:
public E remove(int index) {
rangeCheck(index); //检查是否在范围内
modCount++; //初始值为0
E oldValue = elementData(index); //保存旧数据
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved); //将移除位置之后所有的元素都向前挪动一个位置
elementData[--size] = null; //将最后一个元素置为空
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
首先判断要删除的位置是否超出的范围:如果超出,则抛出异常,否则删除该位置的元素,并且将移除位置之后所有的元素都向前挪动一个位置,将最后一个元素置为空。
1.3 结合1.1与1.2,回答ArrayList存储数据时需要考虑元素的具体类型吗?
不需要。ArrayLis存储是用Object[]数组实现的,Object是所有类的父类,所以不需要考虑元素的类型。
1.4 分析add源代码,回答当内部数组容量不够时,怎么办?
源代码如下:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保下一个元素进来有空间
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // DEFAULT_CAPACITY = 10,默认长度为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); //增加原来容量的一半。
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; //MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
}
1.5 分析private void rangeCheck(int index)源代码,为什么该方法应该声明为private而不声明为public?
源代码如下:
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
rangeCheck方法用来判断是否超出容量范围,没有返回值,假如超出范围了就直接抛出异常。使用private是因为用户不需要知道rangeCheck方法是如何操作,因为在进行各个方法的调用时需要该方法时就会自动被调用,开发者不需要自己手动进行判断是否越界。
2. HashSet原理
2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?
首先要调用hashCode方法得到相应的哈希值,然后对哈希值进行计算,算出在哈希表中对应的位置。如果对应的位置上没有值,则将元素放在该位置上,如果该位置上有别的值,则调用equals方法比较位置上的值和要加入的元素的值,如果为true,则说明两个值相等,而HashSet不允许有重复的值,则用新元素代替就元素,如果结果为false,就通过散列冲突的解决办法解决。
2.2 将元素加入HashSet中的时间复杂度是多少?是O(n)吗?(n为HashSet中已有元素个数)
将元素加入HashSet中不需要遍历,时间复杂度为O(1)。
2.3 选做:尝试分析HashSet源代码后,重新解释2.1
源代码如下:
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean containsKey(Object key) { //如果此映射包含对于指定键(key)的映射关系,则返回true
return getEntry(key) != null;
}
final Entry<K,V> getEntry(Object key) { //通过key获取value
int hash = (key == null) ? 0 : hash(key.hashCode());//
for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
调用contains方法,contains又调用map.containsKey方法,该方法又调用getEntry方法来获取value。containsKey对返回的Keyvalue判断,如果为空在返回false,否则返回true。
3. ArrayListIntegerStack
题集jmu-Java-05-集合之ArrayListIntegerStack
3.1 比较自己写的ArrayListIntegerStack与自己在题集jmu-Java-04-面向对象2-进阶-多态、接口与内部类中的题目自定义接口ArrayIntegerStack,有什么不同?(不要出现大段代码)
- ArrayListIntegerStack利用ArrayList实现栈的存储,ArrayList是长度可变化的数组,不必考虑栈满的情况。
- ArrayIntegerStack利用长度不可变数组来实现栈的存储,说数组不可变,其实是因为一开始就要设定好数组的长度,需要考虑栈满的情况。
3.2 结合该题简单描述接口的好处,需以3.1为例详细说明,不可泛泛而谈。
接口对类的所有共性方法进行声明,实现这个接口的类再对方法进行重写。在3.1中,ArrayListIntegerStack和ArrayIntegerStack都有共同的方法,但是对这些方法的实现,对栈的存储方式不一样(重写的方法又不一样)。接口的方法在不同的类中实现,实现起来又能有不一样的功能,这样会比较方便,弥补了类不能被多继承的缺憾。
4. Stack and Queue
4.1 编写函数判断一个给定字符串是否是回文,一定要使用栈(请利用Java集合中已有的类),但不能使用java的Stack类(具体原因自己搜索)与数组。请粘贴你的代码,类名为Main你的学号。

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

使用了Queue接口的实现类Deque。
5. 统计文字中的单词数量并按单词的字母顺序排序后输出
题集jmu-Java-05-集合之5-2 统计文字中的单词数量并按单词的字母顺序排序后输出 (作业中不要出现大段代码)
5.1 实验总结

这题关键是要用TreeSet,可以自动排序。
3.码云及PTA
题目集:jmu-Java-05-集合
3.1. 码云代码提交记录
在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图

3.2 截图PTA题集完成情况图
需要有两张图(1. 排名图。2.PTA提交列表图)


3.3 统计本周完成的代码量
需要将每周的代码统计情况融合到一张表中。

| 周次 | 行数 | 新增行数 | 文件数 | 新增文件数 |
|---|---|---|---|---|
| 1 | 91 | 91 | 5 | 5 |
| 2 | 504 | 413 | 18 | 13 |
| 3 | 1092 | 588 | 28 | 10 |
| 5 | 1158 | 129 | 34 | 6 |
| 6 | 1539 | 381 | 40 | 6 |
| 7 | 2023 | 484 | 49 | 9 |
| 8 | 2477 | 454 | 57 | 8 |
| 9 | 2709 | 232 | 63 | 6 |
浙公网安备 33010602011771号