1. 本周学习总结
2. 书面作业
1. ArrayList代码分析
1.1 解释ArrayList的contains
源代码
contains
的源代码及解释:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) { //找到o返回当前位置i,否则返回-1
if (o == null) { //当o为null时
for (int i = 0; i < size; i++) //判断ArrayList中是否含有null元素,有返回当前位置i,没有返回-1
if (elementData[i]==null)
return i;
} else { //当o不为null时,用equals方法判断ArrayList中是否含有该元素,有返回当前位置i,没有返回-1
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
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
//最后一个元素置为空,size自减一次
return oldValue; //返回被删除的元素
}
private void rangeCheck(int index) { //判断要删除的位置是否合理
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
1.3 结合1.1与1.2,回答ArrayList存储数据时需要考虑元素的具体类型吗?
不需要,ArrayList内部数组是Object数组实现的,Object类是超级父类,所以只要存储进去的数据类型是引用数据类型而不是基本数据类型,就可以将其存储进去
1.4 分析add源代码,回答当内部数组容量不够时,怎么办?
public boolean add(E e) {
ensureCapacityInternal(size + 1); //size+1为需要的最小容量
elementData[size++] = e; //将e加入列表
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //当数组是默认长度的空数组时,取10和传入参数的最大值,即最小数组容量最小为10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //DEFAULT_CAPACITY = 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); //扩容1.5倍
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;
}
1.5 分析private void rangeCheck(int index)
源代码,为什么该方法应该声明为private而不声明为public?
源代码:
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
修饰为private体现了封装性,这里以remove方法为例,用户或其他类调用remove方法时,remove方法会自动调用rangeCheck方法判断数组下标是否出界,用户或其他类不需要知道rangeCheck这个方法,只要知道remove方法是否删除成功即可。
2. HashSet原理2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?
2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?
先用HasCode方法
确定要加入的位置,若要加入的位置没有其他元素,则将该元素加入该位置,若要加入的位置有其他元素,用equals方法
判断这个位置的桶中是否有相同元素,若有,则不加入,若没有,则将该元素加入该位置
2.2 将元素加入HashSet中的时间复杂度是多少?是O(n)吗?(n为HashSet中已有元素个数)
时间复杂度为O(1)而不是O(n),因为将元素加入HashSet不需要遍历HashSet中的元素,是直接计算出要加入的位置,然后直接添加,所以时间复杂度为O(1)。
2.3 选做:尝试分析HashSet源代码后,重新解释2.1
3. ArrayListIntegerStack
3.1 比较自己写的ArrayListIntegerStack与自己在题集jmu-Java-04-面向对象2-进阶-多态、接口与内部类
中的题目自定义接口ArrayIntegerStack
,有什么不同?(不要出现大段代码)
本次题集中栈的定义
以前题集中栈的定义
不同之处:
- 两次题集栈的实现方式不同,本次题集用列表实现栈,以前题集用长度一定的数组实现栈。
- 动态数组实现不用另外设栈顶指针,用
list.get(list.size()-1)
即可获得栈顶元素,数组实现需要栈顶指针来获得栈顶元素及判断是否满栈 - 动态数组实现不用判断栈满的条件,因为动态数组容量不够时会自动扩容,数组实现以为长度一定,所以需要判断满栈情况
- 动态数组获取元素个数用
list.size()
即可实现,数组实现需要将栈顶指针加1获得元素个数
总之,动态数组因为有很多现成的方法及自动扩容的能力,使得用动态数组实现栈比用数组实现栈来的方便,快捷
3.2 结合该题简单描述接口的好处,需以3.1为例详细说明,不可泛泛而谈。
用接口最大的好处就是提高编程的灵活性,本题ArrayIntegerStack实现了IntegerStack接口,IntegerStack接口中定义了入栈,出栈,获取栈顶元素,判断是否是空栈,返回栈中元素个数五个方法,这五个方法只有方法名,没有方法体,之后的类实现这个接口后,编程人员可以用各种各样不同的方式实现这个接口,比如列表实现或是数组实现,方便编程人员的使用
4. Stack and Queue
4.1 编写函数判断一个给定字符串是否是回文,一定要使用栈(请利用Java集合中已有的类),但不能使用java的Stack
类(具体原因自己搜索)与数组。请粘贴你的代码,类名为Main你的学号
代码截图:
运行结果:
4.2 题集jmu-Java-05-集合
之银行业务队列简单模拟(只粘贴关键代码)。请务必使用Queue
接口,并说明你使用了Queue接口的哪一个实现类?
代码截图:
使用了LinkList的实现类
5. 统计文字中的单词数量并按单词的字母顺序排序后输出
5.1实验总结
首先根据题目确定要用Set接口的实现类TreeSet,接着将除了!!!!!
之外的所有单词加入TreeSet中,TreeSet会对加入其中的单词进行排序,最后如果TreeSet中的元素个数小于10个的话,将其所有的元素输出,如果TreeSet中的元素个数大于10个,输出前十个元素,用TreeSet的size()方法输出单词的总数量
6. 选做:统计文字中的单词数量并按出现次数排序
6.1 伪代码
- 用HashMap实现从单词到数量映射的存储
- 将HashMap转化为ArrayList,用Comparator匿名内部类实现排序
- 输出不重复的单词的总数量
- 不重复的单词数量小于10个,输出所有单词,不重复的单词数量大于10个,输出排名前十的单词
6.2 实验总结
- 首先根据题目的要求要实现单词数量的递减排序,若单词数量相同,则实现首字母递增排序,这里不能用TreeMap,因为TreeMap只能对键值实现递增排序,所以只要用HashMap,然后再将HashMap转化为ArrayList,对列表运用Comparator比较器进行排序即可
- 单词插入HashMap中时,要先判断原来的HashMap是否已经包含该单词,若有,新的次数等于原来的次数加1,然后重新加入HashMap中,若没有,则将次数置为1,加入HashMap中
这一题比较难的是将HashMap转化为ArrayList,然后用Comparator比较器结合匿名内部类实现排序,将代码展示如下:
7. 选做 面向对象设计大作业-改进
7.1 使用集合类改进大作业或者简述你的面向对象设计大作业中,哪里使用到了集合类。
购物车类存储商品信息用到ArrayList列表
3.码云及PTA
3.1. 码云代码提交记录
3.2 截图PTA题集完成情况图
3.3 统计本周完成的代码量
周次 | 总代码量 | 新增代码量 | 总文件数 | 新增文件数 |
---|---|---|---|---|
2 | 343 | 343 | 10 | 10 |
3 | 498 | 498 | 8 | 8 |
5 | 788 | 788 | 26 | 26 |
6 | 536 | 536 | 16 | 16 |
7 | 776 | 776 | 9 | 9 |
8 | 846 | 846 | 4 | 4 |
9 | 668 | 668 | 12 | 12 |