• Java 第七周总结


    1. 本周学习总结

    2. 书面作业

    1.ArrayList代码分析

    1.1 解释ArrayList的contains源代码

    • 我们知道ArrayList是允许重复的,有序的元素的集合,但当我们想用它来放入不同的元素时,就可以使用contains()方法
    • 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;
      		  }
       		  public boolean equals(Object obj) {
       		 return (this == obj);
       		 }
    
    • 如果对象不为null,最终调用的是equals方法,进行比较。如果相同返回true,不同返回false。但是由于equals的局限性,对于新建两个对象,虽然代表同一个,但是由于虚拟机在开辟怕两个存储空间,所以也会被判断为是两个东西。所以一般都要重写equals方法。

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

    • remove(int)用于删除ArrayList数组容器中指定位置int上的元素(从0开始),并返回此元素.
        public E remove(int index) { 
        
        RangeCheck(index); 
        
        modCount++; 
        
        E oldValue = elementData[index]; 
        //numMoved需要移动的元素个数,也就是index后面的所有的元素个数 
        int numMoved = size - index - 1; 
        
        //将index后面的所有元素全部往前依次移动一个位置 
        if (numMoved > 0) 
        System.arraycopy(elementData, index+1, elementData, index, 
        numMoved); 
        
        //经过arraycopy的移位,数组容器的最个位置被腾空, 
        //但是仍然持有某个对象的引用,需要把这个多余的引用置为null. 
        elementData[--size] = null; // Let gc do its work 
        
        return oldValue; 
        }
    
    • 如果是remove((Integer)a)则是删除a这个元素,如图:

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

    • 首先,ArrayList是一个数组列表,初始数组数据类型都为Object类型,而Object又是所有类的父类,也就是说数组内的原色可以是任意类型。
    • 所以,任何类型的元素都是可以存储在ArrayList中的

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

    • 会把当前容量的1.5倍值赋给新的容量
         public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        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++;//定义于ArrayList的父类AbstractList,用于存储结构修改次数  
          
            // overflow-conscious code  
            if (minCapacity - elementData.length > 0)  
                grow(minCapacity);  
        }  
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//有些虚拟机会在数组内保留一些头部信息,尝试分配更大的容量可能会导致内存溢出  
        //容量扩容的精髓  
        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);  
            //将原来数组的值copy新数组中去, ArrayList的引用指向新数组(如果数据量很大还是建议初始化的时候指定容量的大小,提高效率)  
            elementData = Arrays.copyOf(elementData, newCapacity);  
        }  
    

    https://zhidao.baidu.com/question/135667727998224005.html

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

      private void rangeCheck(int index) {
    if (index >= size)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    
    • 使用private 声明,说明这个方法是用户无法获取到的,只能在代码内部自动进行。
    • rangeCheck()方法被以下方法调用:
      • get(int index)
      • set(int index, E element)
      • remove(int index)
    • 这些方法在调用了rangeCheck()方法后,会马上调用elementData(int index)方法来获取指定位置元素的值。这两个方法调用保证了0 < index < size();
    • rangeCheck()方法保证index在ArrayList长度范围之内(index < size()),并在越界时抛出IndexOutOfBoundsException异常elementData()中的数组访问代码会在index < 0时抛出ArrayIndexOutOfBoundsException异常

    作者:Han Yi
    链接:https://www.zhihu.com/question/56689381/answer/150114817
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    2.HashSet原理

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

    • HashSet类,是存在于java.util包中的类[1]  。同时也被称为集合,该容器中只能存储不重复的对象。
    • 系统采用 Hash 算法决定集合元素的存储位置
    • implements Set<E>, Cloneable, java.io.Serializable 使用 HashMap 的 key 保存 HashSet 中所有元素
    • 初始化 HashSet,底层会初始化一个 HashMap
    • 调用 HashMap 的 containsKey 判断是否包含指定 key
    • equals() 方法,分别对各属性进行判断,是否相等
    • hashCode() 方法,有可能两者并不相等,但是hash码相同,所以要结合起来比较

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

    • 当从HashSet集合中查找某个对象时,Java系统首先调用对象的hashCode()方法获得该对象的哈希码表,然后根据哈希吗找到相应的存储区域,最后取得该存储区域内的每个元素与该对象进行equals方法比较
    • 所以hashmap需要重写hashCode和equals
    • 但是对于list,就只要重写equals方法

    3.ArrayListIntegerStack

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

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

    • 主要在于数组和动态数组的区别
    
    	class ArrayintegerStack implements IntegerStack{
    		private Integer[] arr;
    	}
    
    
    
    	class ArrayListIntegerStack implements IntegerStack{
    		ArrayList<Integer> list=new ArrayList<Integer>();
    	}
    
    
    • ArrayList不用设定头指针,可以通过序号直接找到元素,进行删除,返回的操作

    3.2 简单描述接口的好处.

    • 方便让代码知道,需要实现哪些功能,这些功能也不止有这个类可以使用,其他类也可以用。
    • 接口也是一种规范,同样的操作可以有不同的实现方式,但是最后都是要面向接口。就比如金牛的插座和西门子的插座,内部构造,原材料什么的有可能不同,但是对于用户来说,都是把插头插上就可以用了。

    4.Stack and Queue

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

    package Test;
    
    import java.util.ArrayList;
    import java.util.Scanner;
    
    interface IntegerStack{
    	public String push(String item);
    	public String pop();
    	public String peek();
    	public boolean empty();
    	public int size();
    
    }
    
    
    class ArrayListIntegerStack implements IntegerStack{
    	ArrayList<String> list=new ArrayList<String>();
    	
    	@Override
    	public String push(String item) {
    		if(item==null)
    			return null;
    		list.add(item);
    		return item;		
    	}
    
    	@Override
    	public String pop() {
    		if(!list.isEmpty()){
    			return list.remove(list.size()-1);
    		}
    		return null;
    	}
    
    	@Override
    	public String peek() {
    		if(list.size()==0)
    			return null;
    		else 
    			return list.get(list.size()-1);
    	}
    
    	@Override
    	public boolean empty() {
    		if(list.size()==0)
    			return true;
    		else 
    			return false;
    	}
    
    	@Override
    	public int size() {
    		return list.size();
    	}
    
    	@Override
    	public String toString() {
    		return list.toString(); 
    	}	
    }
    
    
    public class Main201521123043{
    	public static void main(String[] arge){
    		ArrayListIntegerStack a=new ArrayListIntegerStack();
    		int i;
    		Scanner in=new Scanner(System.in);
    		String m=in.next();
    		Integer n = null;
    		for(i=0;i<m.length();i++)
    			a.push(String.valueOf(m.charAt(i)));
    		for(i=0;i<m.length();i++)
    		{
    			if(String.valueOf(m.charAt(i)).equals(a.pop()))
    				continue;
    			else{
    				System.out.println("false");
    				break;
    			}
    		}
    		
    		if(i==m.length())
    			System.out.println("true");
    	}
    	
    }
    
    

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

    • 定义了两个队列,一个数组
    Queue<Integer> qa = new LinkedList<Integer>();
    		Queue<Integer> qb = new LinkedList<Integer>();
    		Scanner input=new Scanner (System.in);
    
    • 单数的加入队列qa,复数的加入队列qb
    for(int i=1;i<size+1;i++)
    		{
    			num=Integer.parseInt(str[i]);
    			if(num%2==0) qb.offer(num);
    			else qa.offer(num);
    		}
    		for(int i=0;i<str.length-1;)
    		{
    			if(qa.size()!=0&&i<str.length-1) list[i++]=qa.poll();
    			if(qa.size()!=0&&i<str.length-1) list[i++]=qa.poll();
    			if(qb.size()!=0&&i<str.length-1) list[i++]=qb.poll();
    		}
    
    for(int i=0;i<str.length-1;i++)
    		{
    			if(i!=str.length-2) System.out.printf("%d ",list[i]);
    			else System.out.printf("%d",list[i]);
    		}
    

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

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

    	//按空格分开,加入到set里,重复的删除
    		while(in.hasNext())
    		{
    			a=in.next();
    			if(a.equals("!!!!!"))
    				break;
    			set.add(a);
    			//System.out.println(a);
    		}
    

    ```

    	//最后单词总数
    	System.out.println(set.size());
    
    <p>
    
    	//利用二叉树排序排序
    	final TreeSet ts=new TreeSet(set);
    	ts.comparator();
    
    <p>
    
    	//转换为数组输出
    	String[] str=(String[]) ts.toArray(new String[ts.size()]);
    
    
    ###5.1 实验总结
    - Hashset本身没有排序方法,这里有两种方法,一种是把他保存在ArrayList里,再用Collections.sort()来排序
    - 另一种就是使用二叉排序树
    - 要把集合(List,Set)里的元素放入数组时,可以使用toArray(),方便逐个输出
    
    ##6.选做:加分考察-统计文字中的单词数量并按出现次数排序
    >题集jmu-Java-05-集合之5-3 统计文字中的单词数量并按出现次数排序(不要出现大段代码)
    
    
    ###6.1 伪代码
    - 输入同5-2,不变
    - 相同的单词输入Map里
    
    

    Map<String,Integer> coun =new TreeMap<String,Integer>();
    if(set.contains(a))
    {
    if(coun.containsKey(a))
    coun.put(a, coun.get(a)+1);
    else
    coun.put(a, 2);
    }
    set.add(a);

    - 因为排序要求有变,所以通过collection比较器来实现排序
    
    

    List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(coun.entrySet());
    Collections.sort(list,new Comparator<Map.Entry<String,Integer>>(){

    		@Override
    		public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
    			return (o2.getValue() - o1.getValue());
    		}
    		
    	});
    
    
    ###6.2 实验总结
    - Map以按键/数值对的形式存储数据,和数组非常相似,在数组中存在的索引
    - 关于怎么使用,一般是选择Map的子类,而不直接用Map类。如:HashMap,TreeMap ```Map<String,Integer> coun =new HashMap<String,Integer>();```
    - remove(Object key) 从map中删除键和关联的值
    - put(Object key,Object valus)将指定值与指定键相关联
    ![](http://images2015.cnblogs.com/blog/1109779/201704/1109779-20170407191208425-1160558043.jpg)
    ![](http://images2015.cnblogs.com/blog/1109779/201704/1109779-20170407191216050-2044717545.jpg)
    
    
    
    
    ##7.选做加分:面向对象设计大作业-改进
    
    ###7.1 完善图形界面(说明与上次作业相比增加与修改了些什么)
    ![](http://images2015.cnblogs.com/blog/1109779/201704/1109779-20170408205913660-1793297223.png)
    
    
    - 增加了购物车界面,两个界面之间的转换正在完善
    
    
    ###7.2 使用集合类改进大作业
    - 购物车列表使用的是list
    
    #3. 码云上代码提交记录
    ![](http://images2015.cnblogs.com/blog/1109779/201704/1109779-20170408204418816-1187133334.jpg)
  • 相关阅读:
    NLP 基础问题及解析
    linux 命令精简
    linux 文件属性及操作
    linux 文件编辑命令vim
    NLP attention 简述
    数据结构
    2020 走进新时代
    条件随机场CRF 摘要
    linux的jdk、tomcat、tomcat安装等
    VMware所在磁盘满了、linux中date修改、ssh、eclipse的使用问题等
  • 原文地址:https://www.cnblogs.com/ycll/p/6664869.html
Copyright © 2020-2023  润新知