201521123010 《Java程序设计》第7周学习总结

  • 1. 本周学习总结

以你喜欢的方式(思维导图或其他)归纳总结集合相关内容。
参考资料:
XMind


  • 2. 书面作业

①ArrayList代码分析

  • 1.1 解释ArrayList的contains源代码

A:

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中的每个元素e调用o.equals(e),方法,若加入ArrayList中有n个元素,那么会调用n次o.equals(e),只要有一次o.equals(e)返回了下标,那么ArrayList.contains(o)返回下标,否则返回-1。自己理解为:如果o为null,那么就去找elementData[]里是否有为null的对象,有则返回下标,没有则返回-1。如果o不为null,就通过equals去比较elementData[] 中是否有与o相同的对象,有则返回下标没有则返回-1。所以我认为这里判断 o==null 主要就用来确定是否要调用o.equals()。

  • 1.2 解释E remove(int index)源代码

A:

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

源代码如上。E remove(int index)源代码所要表达的其实也就是将ArrayList里其中的一个元素删除,这个被删除元素之后的元素都往前移一位。在rangeCheck(int index)里,index也就是被删除元素的索引,通过索引判断元素是否在ArrayList范围内。我理解为以上意思。

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

A:

应是不需要考虑的。首先,根据以前的内容可以知道,初始数组的数据类型都为Object类,而所有数据的默认父类也都为Object类,所以对于一个初始数组是不用考虑元素的类型的,Object类会转换各数据的类型。其次,因为ArrayList是一个数组列表,所以满足了以上条件,故ArrayList存储数据时不需要考虑元素的类型。

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

A:

     public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!! 将容量设置为size + 1
    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);//赋予旧容量的1.5倍给新容量  
        if (newCapacity - minCapacity < 0)//判断新容量是否足够
            newCapacity = minCapacity;  
        if (newCapacity - MAX_ARRAY_SIZE > 0) 
            newCapacity = hugeCapacity(minCapacity);  
        elementData = Arrays.copyOf(elementData, newCapacity); //引用1.5倍旧容量的新容量指向新数组
    }  

源代码如上。当数组容量不够的时候,会自动对数组容量进行扩容。而如何进行扩容,先用if来判断是否超出容量,然后用grow(minCapacity);来进行扩容。其余查阅到的就在代码上进行粗略注释。

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

A:

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

设置为private的话外部就不能看到用户也不能获取,从1.1可以看出rangeCheck(int index)本就在系统内部进行,并且其作用也为保证语句操作在容量范围内,若某个语句操作超过了范围用户也可以直接发现越界,那也就没有用public声明的必要了。


②HashSet原理

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

A:

当向HashSet中存入一个元素时,HashSet会调用该对象的HashCode()方法来得到该对象的hashCode值,然后根据该HashCode值来决定该对象在HashSet中存储位置。
查阅可知,HashSet实质上是通过HashMap()来实现的,而对于存放在HashSet中的对象,也需要通过equals()HashCode()方法结合起来保证其唯一性。

  • 2.2 选做:尝试分析HashSet源代码后,重新解释1.1

A:

HashSet的定义:
  public class HashSet<E>
  extends AbstractSet<E>
  implements Set<E>, Cloneable, java.io.Serializable
  //HashSet继承了AbstractSet,实现了Set接口。

HashSet定义的属性:
  private transient HashMap<E,Object> map;
  private static final Object PRESENT = new Object();

由此可知,HashSet可看为通过一个HashMap存储元素,元素是存放在HashMap的Key中,而Value统一使用一个Object对象。所以每当查找其中某一个对象时,首先会调用对象的hashCode()方法获得该对象的哈希码表,再找到存储区域,之后再用equal()方法比较。所以每次都需重写以上两种方法。而1.1是加入ArrayList中有n个元素,那么会调用n次o.equals(e),每次都只需重写一种方法。


③ArrayListIntegerStack

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

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

A:

区别在于,4-5-3:ArrayIntegerStack为内部数组实现存储。空间固定,会出现栈满的情况。出栈时通过移动指针判断。5-5-1:ArrayListIntegerStack为动态数组实现存储,会自动扩容故不会有栈满。出栈时使用1.2的remove()方法即可。

  • 3.2 简单描述接口的好处.

A:

在java中最好避免重复方法或类,而使用接口可以达到多重继承的目的以解决前一句话的问题。使用接口可以操作不同的类,达到相同方法不同实现这一点。如3.1都继承了IntegerStack接口,这样就可以根据自己的需求,去以不同的方式去实现。


④Stack and Queue

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

A:

贴上主函数为:
public class Main201521123010 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc=new Scanner(System.in);
        StringStack stack=new ArrayListStringStack();
        
        String hw=sc.next();
        boolean flag = true;
        for(int i=0;i<hw.length();i++)
        {
            stack.push(String.valueOf(hw.charAt(i)));
        }
        for(int i=0;i<hw.length();i++)
        {
            if(String.valueOf(hw.charAt(i)).equals(stack.pop()))
            	{
            	flag=true;
            	}
            else
            {
                flag=false;
                break;
            }
        }
        if (flag) {
            System.out.println("Y");
        } else {
            System.out.println("N");
        }
        }

}
  • 4.2 题集jmu-Java-05-集合之5-6 银行业务队列简单模拟。(不要出现大段代码)

A:

 while(!l1.isEmpty()||!l2.isEmpty())
        {
            Integer a1=l1.poll();
            if(a1!=null)
            {
                if(l1.isEmpty()&&l2.isEmpty())
                System.out.println(a1);
                else
                System.out.print(a1+" ");
            }
            Integer a2=l1.poll();
            if(a2!=null)
            {
                if(l1.isEmpty()&&l2.isEmpty())
                System.out.println(a2);
                else
                System.out.print(a2+" ");
            }
            Integer b=l2.poll();
            if(b!=null)
            {
                if(l1.isEmpty()&&l2.isEmpty())
                System.out.println(b);
                else
                System.out.print(b+" ");
            }
        }

最开始不熟练poll方法,写完了大致就一致卡在a1a2的定义上,查阅了相关资料后,知道为获取并移除次队列的头后,便知道直接用就可以了。。


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

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

  • 5.1 实验总结

A:

    TreeSet<String> set=new TreeSet<String>(); //二叉排序树
    if(set.size() < 10) //若小于十个 全输出
    for(String str : set)
    {
       System.out.println(str);
    }
    else 
    {   
       for (int i = 0; i < 10 ; i++) //输出前十个
    {   
       System.out.println(set.toArray()[i]); //转换为数组输出
    }

排序问题用TreeSet就好了,因为是要按字母排序,TreeSet会默认排好序的。


⑦面向对象设计大作业-改进

  • 7.1 完善图形界面(说明与上次作业相比增加与修改了些什么)

A:

能力有限。。。做不完那么多。。。


  • 3. 码云上代码提交记录及PTA实验总结

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

  • 3.1. 码云代码提交记录

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


  • 3.2. PTA实验

编程(5-1, 5-2, 5-3(选做), 5-6)
实验总结已经在作业中体现,不用写。


posted @ 2017-04-08 19:21  徐鹿林  阅读(222)  评论(0编辑  收藏  举报