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;
}
可以看到,contains的源代码非常简单,返回indexOf(o) >= 0,调用了indexOf()方法;
我们先来了解一下indexOf()方法的实现:
- 返回第一次出现的指定元素的索引
- 在这个列表中,如果该列表不包含指定元素返回-1
- 如果指定元素为null,则遍历列表找出null的索引位置并返回
- 若指定元素不为null,同样遍历列表找出并返回指定元素的第一次索引位置
再来看contains方法的实现:
- 如果列表包含指定元素返回true,否则返回false
- 如果indexOf(o) >= 0则表明在列表中能找出指定元素o的索引位置
- 若indexOf(o)=-1则在列表中不存在指定元素,返回false
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;
}
- 首先用rangeCheck(index)方法检查传进来的指标index是否越界,要知道rangeCheck方法无返回值,if(index>=size),抛出IndexOutOfBoundsException(outOfBoundsMsg(index));
- modCount++;这个列表的次数已经结构修改。结构修改是那些改变列表的大小,或扰乱它在这样一个时尚的迭代过程中可能产生不正确的结果。(这个姑且看看,不是很懂)
- numMoved的值表示被删除元素后面的元素个数
- 接着if后的代码作用是把指标后的元素按位往前挪一位,最后一个元素设为null
- 返回删除的元素
1.3 结合1.1与1.2,回答ArrayList存储数据时需要考虑元素的类型吗?
答案是不需要,可以通过以下例子来说明:
1.4 分析add源代码,回答当内部数组容量不够时,怎么办?
以下是add的源代码:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
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++;
}
有两种常用的add方式,一是直接在列表末尾添加新元素,二是在指定位置上插入新元素;
从以上代码可以看出,无论是哪种add方法,在ArrayList中都不存在内部数组容量不够的问题,因为add方法会使数组容量自动增加。
1.5 分析private void rangeCheck(int index)源代码,为什么该方法应该声明为private而不声明为public?
封装思想,将具体的实现细节隐藏,而把功能作为整体提供给类的外部使用,用户不需要知道rangeCheck方法如何实现,只需要知道结果就行。
2. HashSet原理
2.1 将元素加入HashSet(散列集)中,其存储位置如何确定?需要调用那些方法?
先来看看HashSet的add方法如何实现:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
Set集中没有重复对象,如果添加Set集中的相同对象,则新对象覆盖原对象;
可以看出add方法调用了map.put()方法,put方法又调用了putVal方法,具体实现不管,但是可以看出调用了hash()函数,而hash函数可以帮助找到对象的索引位置。
3. ArrayListIntegerStack
题集jmu-Java-05-集合之5-1 ArrayListIntegerStack
3.1 比较自己写的ArrayListIntegerStack与自己在题集jmu-Java-04-面向对象2-进阶-多态、接口与内部类中的题目5-3自定义接口ArrayIntegerStack,有什么不同?(不要出现大段代码)
首先相同之处是都实现了IntegerStack接口,继承了接口中的各种方法:
interface IntegerStack {
public Integer push(Integer item);
public Integer pop();
public Integer peek();
public boolean empty();
public int size();
}
再者不同之处是ArrayListIntegerStack内部实现用ArrayList列表,ArrayIntegerStack内部实现用Array数组。
就光Array数组必须设置容量而ArrayList列表不需要来说,ArrayListIntegerStack就省事儿多了。
因为在重写各种方法时列表不需要考虑是否越界的问题,而数组需要多考虑这一问题。
3.2 简单描述接口的好处.
- 接口实现扩展功能,让不同的类之间有了联系,却不相互干涉;
- 类可以实现多接口,接口中的方法可以不全部实现,体现接口的灵活性。
4. Stack and Queue
4.1 编写函数判断一个给定字符串是否是回文,一定要使用栈,但不能使用java的Stack类(具体原因自己搜索)。请粘贴你的代码,类名为Main你的学号。
import java.util.LinkedList;
import java.util.Scanner;
public class Main201521123007 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str = in.next();
String[] s = str.split("");
LinkedList<String> stack = new LinkedList<String>();
for (String string : s) {
stack.add(string);
}
int i = 0;
for (; i < s.length / 2; i++) {
if (stack.pollLast().equals(s[i])) {
continue;
} else {
System.out.println(str + "不是回文");
break;
}
}
if (i == s.length / 2)
System.out.println(str + "是回文");
in.close();
}
}
4.2 题集jmu-Java-05-集合之5-6 银行业务队列简单模拟。(不要出现大段代码)
Queue<Integer> q1=new ArrayDeque<Integer>();
Queue<Integer> q2=new ArrayDeque<Integer>();
for (int i = 0; i < n; i++) {
if(q1.size()==2){//A窗口奇编号,2倍速
System.out.printf(q1.poll()+" "+q1.poll()+" ");//A窗口输出
if(q2.size()>=1)//B窗口偶编号,单倍速
System.out.printf(q2.poll()+" ");//B窗口输出
}
if(No[i]%2==1)
q1.add(No[i]);//奇编号加入q1队列
else
q2.add(No[i]);//偶编号加入q2队列
}
while(q1.size()>1)
System.out.printf(q1.poll()+" ");
if(q1.size()==1)//控制输出最后不含空格
System.out.printf(q1.poll()+"");
while(q2.size()>1)
System.out.printf(q2.poll()+" ");
if(q2.size()==1)//控制输出最后不含空格
System.out.printf(q2.poll()+"");
5. 统计文字中的单词数量并按单词的字母顺序排序后输出
题集jmu-Java-05-集合之5-2 统计文字中的单词数量并按单词的字母顺序排序后输出 (不要出现大段代码)
public static void main(String[] args) {
Set<String> strSet = new TreeSet<String>();//TreeSet本身实现有序
Scanner in = new Scanner(System.in);
int m = 10;
while (in.hasNext()) {
String str = in.next();
if(str.equals("!!!!!"))//结束输入
break;
else if (!strSet.contains(str))
strSet.add(str);//添加到strSet
}
System.out.println(strSet.size());//打印strSet大小,即文字中的单词数量
if (strSet.size() <= 10)//打印格式,单词数小于等于10,全部打印
for (String s : strSet) {
System.out.println(s);
}
else//单词数大于10,按单词的字母顺序排序后输出前十
for (String s : strSet) {
if (m-- <= 0)
break;
System.out.println(s);
}
in.close();
}
5.1 实验总结
- Set集不含重复对象
- Set无序,但实现类TreeSet按特定方式排序
6. 选做:加分考察-统计文字中的单词数量并按出现次数排序
题集jmu-Java-05-集合之5-3 统计文字中的单词数量并按出现次数排序(不要出现大段代码)
6.1 伪代码
Map<String, Integer> cm = new TreeMap<String, Integer>();//因为键对象不可重复,值对象可重复,让单词对应键String,除此案次数对应值Integer
while (in.hasNext()) {
String str = in.next();
if (str.equals("!!!!!"))//结束输入
break;
else if (!cm.containsKey(str))//判断键对象是否存在
cm.put(str, 1);//新键值对
else {//已存在键对象
int n = (int) cm.get(str);//<k,v>获取v值
cm.put(str, n + 1);//v值+1,存入TreeMap
}
}
List<Map.Entry<String, Integer>> arrayList = new ArrayList<Map.Entry<String, Integer>>(cm.entrySet());//创建一个列表接收键值对
Collections.sort(arrayList, new Comparator<Map.Entry<String, Integer>>() {//匿名内部类,比较
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return ((Integer) o2.getValue()) - ((Integer) o1.getValue());
}
});
int n=10;
for (Map.Entry<String, Integer> entry : arrayList) {//控制输出
if(n--==0)
break;
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + "=" + value);
}
6.2 实验总结
- 用Map的put(k,v)方法向集合中加入新元素
- 用get方法检索键对象映射的值对象
- TreeMap是按键对象排序的,如果要按值对象排序则要写一个比较方法
7. 面向对象设计大作业-改进
7.1 完善图形界面(说明与上次作业相比增加与修改了些什么)
7.2 使用集合类改进大作业
LinkedList<Shopcart> list;
public Shopcart Add(Product goods,double sum){
Shopcart sc=new Shopcart(goods);
sc.sum=sum;
list.add(sc);
return sc;
}