zoukankan      html  css  js  c++  java
  • 201521123122 《java程序设计》第七周学习总结

    201521123122 《java程序设计》第七周实验总结


    1. 本周学习总结

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


    2. 书面作业

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

    1.elementData 是"Object[]类型的数组",它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数 ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10。elementData数组的大小会根据ArrayList容量的增长而动态的增长
    2.“null”的含义:在JVM规范中是这么说的:

    ,也就是说null是指一个不确定的对象,在java中,null对象不能使用equal函数,所以要区分是否为null。

    3.代码的意思就是验证ArrayList中是否包含所查询的对象,如果存在,则返回其对象所在的位置,不存在的话,返回-1;

    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;
    }
    
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    

    1.rangeCheck函数的作用在于,如果想要删除的位置在size外面,则抛出一个IndexOutOfBoundsException的异常。
    2.主要是把index这个位置的元素取出来,然后后面的元素位置依次向前进一位,然后最后一个元素设置为null;总体size减1;

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


    应考虑是否为基本数据类型,除基本数据类型外的其他类型都可以存储。

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


    同理,先贴代码:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // ensureCapacityInternal用来调整容量
        elementData[size++] = e;
        return true;
    }  
    
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    
        ensureExplicitCapacity(minCapacity);
    }
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0) //如果超出容量,则调用grow方法增加容量
            grow(minCapacity);
    }   
    
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); //增加原来容量的一半(右移一位就是/2),也就是说新List的容量是旧的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); //把旧数组拷贝至新数组,这里说明了并不是增加原来数组的大小,而是引用了一个大小为原来数组1.5倍的新数组。
    }  
    

    从代码以及写的注释中可以看出,如果超出容量,会调用一个grow方法,引用一个新数组,其大小为原来数组的1.5倍,然后把旧数组拷贝至新数组。

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


    rangeCheck代码在上面,我就不复制了。其根本原因还在于java的封装性,因为用户在用这个函数的时候,完全不用去考虑其内部结构,只需知道能否使用就可以了。


    HashSet原理

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

    1.set中不能存储相同的元素,所以要用equal()方法来保证元素的唯一性
    2.从HashSet中访问元素时,HashSet先计算该元素的hashCode值,然后到该hashCode对应的位置取出该元素。所以要调用HashCode算法。

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


    以下转自博客http://www.cnblogs.com/ITtangtang/p/3948538.html

    对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,
    源代码如下:

    public class HashSet<E>  
       extends AbstractSet<E>  
       implements Set<E>, Cloneable, java.io.Serializable  
    4{  
       static final long serialVersionUID = -5024744406713321676L;  
     
       // 底层使用HashMap来保存HashSet中所有元素。  
       private transient HashMap<E,Object> map;  
         
       // 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。  
       private static final Object PRESENT = new Object();  
     
       /** 
        * 默认的无参构造器,构造一个空的HashSet。 
        *  
        * 实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。 
        */  
       public HashSet() {  
       map = new HashMap<E,Object>();  
       }  
     
       /** 
        * 构造一个包含指定collection中的元素的新set。 
        * 
        * 实际底层使用默认的加载因子0.75和足以包含指定 
        * collection中所有元素的初始容量来创建一个HashMap。 
        * @param c 其中的元素将存放在此set中的collection。 
        */  
       public HashSet(Collection<? extends E> c) {  
       map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));  
       addAll(c);  
       }  
     
       /** 
        * 以指定的initialCapacity和loadFactor构造一个空的HashSet。 
        * 
        * 实际底层以相应的参数构造一个空的HashMap。 
        * @param initialCapacity 初始容量。 
        * @param loadFactor 加载因子。 
        */  
       public HashSet(int initialCapacity, float loadFactor) {  
       map = new HashMap<E,Object>(initialCapacity, loadFactor);  
       }  
     
       /** 
        * 以指定的initialCapacity构造一个空的HashSet。 
        * 
        * 实际底层以相应的参数及加载因子loadFactor为0.75构造一个空的HashMap。 
        * @param initialCapacity 初始容量。 
        */  
       public HashSet(int initialCapacity) {  
       map = new HashMap<E,Object>(initialCapacity);  
       }  
     
       /** 
        * 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。 
        * 此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。 
        * 
        * 实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。 
        * @param initialCapacity 初始容量。 
        * @param loadFactor 加载因子。 
        * @param dummy 标记。 
        */  
       HashSet(int initialCapacity, float loadFactor, boolean dummy) {  
       map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);  
       }  
     
       /** 
        * 返回对此set中元素进行迭代的迭代器。返回元素的顺序并不是特定的。 
        *  
        * 底层实际调用底层HashMap的keySet来返回所有的key。 
        * 可见HashSet中的元素,只是存放在了底层HashMap的key上, 
        * value使用一个static final的Object对象标识。 
        * @return 对此set中元素进行迭代的Iterator。 
        */  
       public Iterator<E> iterator() {  
       return map.keySet().iterator();  
       }  
     
       /** 
        * 返回此set中的元素的数量(set的容量)。 
        * 
        * 底层实际调用HashMap的size()方法返回Entry的数量,就得到该Set中元素的个数。 
        * @return 此set中的元素的数量(set的容量)。 
        */  
       public int size() {  
       return map.size();  
       }  
     
       /** 
        * 如果此set不包含任何元素,则返回true。 
        * 
        * 底层实际调用HashMap的isEmpty()判断该HashSet是否为空。 
        * @return 如果此set不包含任何元素,则返回true。 
        */  
       public boolean isEmpty() {  
       return map.isEmpty();  
       }  
     
       /** 
        * 如果此set包含指定元素,则返回true。 
        * 更确切地讲,当且仅当此set包含一个满足(o==null ? e==null : o.equals(e)) 
        * 的e元素时,返回true。 
        * 
        * 底层实际调用HashMap的containsKey判断是否包含指定key。 
        * @param o 在此set中的存在已得到测试的元素。 
        * @return 如果此set包含指定元素,则返回true。 
        */  
       public boolean contains(Object o) {  
       return map.containsKey(o);  
       }  
     
       /** 
        * 如果此set中尚未包含指定元素,则添加指定元素。 
        * 更确切地讲,如果此 set 没有包含满足(e==null ? e2==null : e.equals(e2)) 
        * 的元素e2,则向此set 添加指定的元素e。 
        * 如果此set已包含该元素,则该调用不更改set并返回false。 
        * 
        * 底层实际将将该元素作为key放入HashMap。 
        * 由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key 
        * 与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true), 
        * 新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变, 
        * 因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中, 
        * 原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。 
        * @param e 将添加到此set中的元素。 
        * @return 如果此set尚未包含指定元素,则返回true。 
        */  
       public boolean add(E e) {  
       return map.put(e, PRESENT)==null;  
       }  
     
       /** 
        * 如果指定元素存在于此set中,则将其移除。 
        * 更确切地讲,如果此set包含一个满足(o==null ? e==null : o.equals(e))的元素e, 
        * 则将其移除。如果此set已包含该元素,则返回true 
        * (或者:如果此set因调用而发生更改,则返回true)。(一旦调用返回,则此set不再包含该元素)。 
        * 
        * 底层实际调用HashMap的remove方法删除指定Entry。 
        * @param o 如果存在于此set中则需要将其移除的对象。 
        * @return 如果set包含指定元素,则返回true。 
        */  
       public boolean remove(Object o) {  
       return map.remove(o)==PRESENT;  
       }  
     
       /** 
        * 从此set中移除所有元素。此调用返回后,该set将为空。 
        * 
        * 底层实际调用HashMap的clear方法清空Entry中所有元素。 
        */  
       public void clear() {  
       map.clear();  
       }  
     
       /** 
        * 返回此HashSet实例的浅表副本:并没有复制这些元素本身。 
        * 
        * 底层实际调用HashMap的clone()方法,获取HashMap的浅表副本,并设置到  HashSet中。 
        */  
       public Object clone() {  
           try {  
               HashSet<E> newSet = (HashSet<E>) super.clone();  
               newSet.map = (HashMap<E, Object>) map.clone();  
               return newSet;  
           } catch (CloneNotSupportedException e) {  
               throw new InternalError();  
           }  
       }  
    }
    

    ArrayListIntegerStack

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

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

    1.ArrayListIntegerStack是用ArrayList对象存储的,ArrayIntegerStack是用Integer存储的。
    2.ArrayIntegerStack在出栈的时候需要移动top指针,ArrayListIntegerStack不需要top指针,调用ArrayList自有的remove()方法就可以。

    3.2 简单描述接口的好处.

    简单来说,就是可以通过一个接口来控制不同的类。

    Stack and Queue

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

    import java.util.Scanner;
    import java.util.List;
    import java.util.ArrayList;
    
    @SuppressWarnings("unused")
    public class Main201521123122{
        public static void main(String[] args) {
            
            @SuppressWarnings("resource")
            Scanner sc=new Scanner(System.in);
            System.out.println("请输入字符串");
            ArrayListStringStack Stack=new ArrayListStringStack();
            String n= sc.next();
            for(int i=0;i<n.length();i++)
            {
                Stack.push(String.valueOf(n.charAt(i)));
            }
            for(int j=0;j<n.length();j++){
                if(String.valueOf(n.charAt(j)).equals(Stack.pop())){
                    System.out.println("是回文");
                    break;
                }
                else {
                    System.out.println("不是回文");
                    break;
                }
                        
            }
        }
    public class ArrayListStringStack implements StringStack {
        
        private ArrayList<String> list;
            
        public ArrayListStringStack() {
            list=new ArrayList<String>();
        }
        public String push(String item) {
            if(item==null)
                return null;
            list.add(item);
            return item;
        }
        
        @Override
        public String pop() {
            if(list.isEmpty())
                return null;
            return list.remove(list.size()-1);
        }
    }
    public interface StringStack {
    
        public String push(String item);
        public String pop();
    }
    

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

    只需设置两个队列,然后奇数队列出两个,偶数队列出一个,知道其中一个为空,然后输出剩下的队列
    代码如下:

     int n=in.nextInt();
         for( int i = 0; i < n; i++ ) {  
               int x=in.nextInt();  
               if( x % 2==0 )  qB.add( x );  
               else qA.add( x );  
           }  
    

    偶数放在B窗口,奇数放在A窗口

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

    输出两个A,在输出一个B

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

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

    代码如下:

    public static void main(String[] args) {
            // TODO Auto-generated method stub
            Set<String>set=new TreeSet();
            Scanner in=new Scanner(System.in);
            while(in.hasNext()){
                String str=in.next();
                if(str.equals("!!!!!"))break;
                set.add(str);
            }
            System.out.println(set.size());
            if(set.size()<10)
                for (String string : set) {
                    System.out.println(string);
                    
                }
            else{
                for (int i = 0; i < 10; i++) {
                    System.out.println(set.toArray()[i]);
                    
                }
            }
    
        }
        
    

    5.1 实验总结

    用while(in.hasNext()),来拆分文章中的单词,而使用Treeset会自动将单词排好序,直接输出就可以。

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

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

    3.1. 码云代码提交记录

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

  • 相关阅读:
    Converting PDF to Text in C#
    Working with PDF files in C# using PdfBox and IKVM
    Visualize Code with Visual Studio
    Azure Machine Learning
    Building Forms with PowerShell – Part 1 (The Form)
    ML.NET is an open source and cross-platform machine learning framework
    Microsoft Visual Studio Tools for AI
    Debugging Beyond Visual Studio – WinDbg
    Platform.Uno介绍
    Hawk-数据抓取工具
  • 原文地址:https://www.cnblogs.com/fenm/p/6682807.html
Copyright © 2011-2022 走看看