20172302 《Java软件结构与数据结构》第四周学习总结


2018年学习总结博客总目录:[第一周](https://www.cnblogs.com/hzy0628/p/9606767.html) [第二周](https://www.cnblogs.com/hzy0628/p/9655903.html) [第三周](https://www.cnblogs.com/hzy0628/p/9700082.html) [第四周](https://www.cnblogs.com/hzy0628/p/9737321.html)

教材学习内容总结

第六章 列表

1.列表是对象的有序集合,在 List 界面中定义。 List 接口表示集合框架中的列表。列表可以具有重复的元素。并且我们可以在列表中存储多个空值。

2.列表集合 是一种概念性的表示方法,其思想是使事物以线性列表的方式进行组织,就像栈和队列一样,列表也可以使用数组和链表来实现。列表集合没有内在的容量大小,它可以随着需要而增大。列表集合更一般化,可以在列表的中间和末端添加和删除元素。

3.列表可以分为有序列表、无序列表、索引列表。

  • 有序列表,是基于列表中元素的某种特性的。列表基于某个关键值排序,对于已经添加到有序列表中的元素,只要给定了元素的关键值,同时列表已经定义了元素的所有关键值,那么它在列表中就有一个固定的位置。
  • 无序列表,各个元素的位置并不基于元素的任何内在特性,但是不要被名字误导, 无序列表中的元素是按照特殊顺序放置,只是这种顺序与元素本身无关,列表的使用者会决定列表的顺序。
  • 索引列表,与无序列表类似,索引列表的各个元素之间也不存在能够决定他们在列表中顺序的内在关系。列表的使用者决定了元素的顺序,不过,除此之外,其每个元素都能够从一个数字索引值得到引用,该索引值从列表的头开始从0连续增加直到列表末端。当列表发生改变,索引值就响应的调整以保持顺序和连续性。索引列表为他的元素维护一段连续的数字索引值。

4.列表的总体UML图

5.Java集合API中的列表所定义的一些基本操作,见下表

操作 描述
add 向列表末端添加一个元素
add(int index, E element) 在列表的指定位置插入指定元素
get(int index) 返回列表中指定位置的元素
remove(int index) 移除列表中指定位置的元素
remove(Object o) 从此列表中移除第一次出现的指定元素(如果存在)
set(int index, E element) 用指定元素替换列表中指定位置的元素
size() 返回列表中的元素数

6.①无序列表的使用:学习计划;②索引列表的使用:Josephus问题。

7.列表ADT
(1)列表的常见操作

操作 描述
removeFirst 从列表中删除第一个元素
removeLast 从列表中删除最后一个元素
remove 从列表中删除某个元素
first 查看位于列表前端的元素
last 查看位于列表末端的元素
isEmpty 确定列表是否为空
size 确定列表中的元素数

(2)接口ListADT的代码

import java.util.Iterator;

public interface ListADT<T> extends Iterable<T>
{
   
    public T removeFirst();

   
    public T removeLast();


    public T remove(T element);

 
    public T first();

   
    public T last();

    public boolean contains(T target);

   
    public boolean isEmpty();

 
    public int size();

  
    public Iterator<T> iterator();

    public String toString();
}

(3)有序列表接口类代码

public interface OrderedListADT<T> extends ListADT<T>
{
  
    public void add(T element);
}

(4)无序列表接口类代码

public interface UnorderedListADT<T> extends ListADT<T>
{
    
    public void addToFront(T element);  

  
    public void addToRear(T element); 


    public void addAfter(T element, T target);
}

8.使用数组实现列表

  • ArrayList类的头和类级代码:
public abstract class ArrayList<T> implements ListADT<T>, Iterable<T>
{
    private final static int DEFAULT_CAPACITY = 100;
    private final static int NOT_FOUND = -1;
	
    protected int rear;
    protected T[] list; 
    protected int modCount;


    public ArrayList()
    {
        this(DEFAULT_CAPACITY);
    }

   
    public ArrayList(int initialCapacity)
    {
        rear = 0;
        list = (T[])(new Object[initialCapacity]);
		modCount = 0;
    }
}
  • remove操作及find方法
public T remove(T element)
    {
        T result;
        int index = find(element);

        if (index == NOT_FOUND)
            throw new ElementNotFoundException("ArrayList");

        result = list[index];
        rear--;
		
        // shift the appropriate elements 
        for (int scan=index; scan < rear; scan++)
            list[scan] = list[scan+1];
 
        list[rear] = null;
		modCount++;

        return result;
    }
private int find(T target)
    {
        int scan = 0; 
		int result = NOT_FOUND;
 
        if (!isEmpty())
            while (result == NOT_FOUND && scan < rear)
                if (target.equals(list[scan]))
                    result = scan;
                else
                    scan++;

        return result;
    }
  • contains操作:这里也将调用find方法
public boolean contains(T target)
    {
        return (find(target) != NOT_FOUND);
    }
  • 添加操作
    • 有序列表的add操作
public void add(T element)
    {
		if (!(element instanceof Comparable))
			throw new NonComparableElementException("OrderedList");
		
		Comparable<T> comparableElement = (Comparable<T>)element;
        
		if (size() == list.length)
            expandCapacity();

        int scan = 0;  
		
		// find the insertion location
        while (scan < rear && comparableElement.compareTo(list[scan]) > 0)
            scan++;

		// shift existing elements up one
        for (int shift=rear; shift > scan; shift--)
            list[shift] = list[shift-1];

		// insert element
        list[scan] = element;
        rear++;
		modCount++;
    }
- 无序列表的addAfter操作
public void addAfter(T element, T target)
    {
        if (size() == list.length)
            expandCapacity();

        int scan = 0;
		
		// find the insertion point
        while (scan < rear && !target.equals(list[scan])) 
            scan++;
      
        if (scan == rear)
            throw new ElementNotFoundException("UnorderedList");
    
        scan++;
		
		// shift elements up one
        for (int shift=rear; shift > scan; shift--)
            list[shift] = list[shift-1];

		// insert element
		list[scan] = element;
        rear++;
		modCount++;
    }

9.使用链表实现列表

  • LinkedList类的类头、类级函数和构造函数:
public abstract class LinkedList<T> implements ListADT<T>, Iterable<T>
{
    protected int count;
    protected LinearNode<T> head, tail;
	protected int modCount;
    
    /**
     * Creates an empty list.
     */
    public LinkedList()
    {
        count = 0;
        head = tail = null;
		modCount = 0;
	}
}

教材学习中的问题和解决过程

  • 问题1:对于书上97页所提及的“Serializable接口是为了某个对象能使用串行化进行存储”,什么是串行化,又是怎么实现的?

  • 问题1解决方案:(1)Java串行化即Java序列化,一个对象随着创建而存在,随着程序结束而结束。那如果我要保存一个对象的状态呢?Java序列化能够将对象的状态写入byte流存储起来,也从其他地方将byte流读取出来,重新构造一个新的对象。这种机制允许你将对象通过网络进行传播,并且可以随时把对象持久化到数据库、文件系统中。简而言之,序列化就是将一个对象的状态保存起来,而反序列化就是将已经保存的流对象恢复成原来的对象。
    (2)如何实现序列化?
    实现序列化有一个条件,即实现序列化的类必须实现java.io.Serializable接口。之后可以利用ObjectInputStream的readOjbect()方法和OjbectOutputStream的writeObject()方法进行对象的读和写,即反序列化和序列化。
    a) Java对象:在java中要想使一个java对象可以实现序列化与反序列化,必须让该类实现java.io.Serializable接口,java.io.Serializable接口定义如下:

publicinterface Serializable {

}

b) 序列化主要依赖java.io.ObjectOutputStream类,该类对java.io.FileOutputStream进一步做了封装,这里主要使用ObjectOutputStream类的writeObject()方法实现序列化功能

/**

     *将对象序列化到磁盘文件中

     *@paramo

     *@throwsException

     */

    publicstaticvoid writeObject(Object o) throws Exception{

       File f=new File("d:""user.tmp");

       if(f.exists()){

           f.delete();

       }

       FileOutputStream os=new FileOutputStream(f);

       //ObjectOutputStream 核心类

       ObjectOutputStream oos=new ObjectOutputStream(os);

       oos.writeObject(o);

       oos.close();

       os.close();

    }

代码调试中的问题和解决过程

  • 问题1:Josephus问题中的代码中numPeople,skip分别代表什么意思?

  • 问题1解决方案:把书上代码敲入后,运行了两次,去对比书上给出的那个7个元素的结果,

    这时便可理解numPeople代表总的人数,而skip代表的则是每隔几个元素删除一个元素,每3个人在这里实际上是每隔2个人。

  • 问题2:做PP6.17时,关于compareTo方法如何去编写遇到了些问题

  • 问题2解决方案:要求是首先按照系排序课程,再按照课程号排序,一开始我是想在Course类下的compareTo方法中只进行系排序,再到实现add方法时再进行课程号排序,可这样始终不行,做起来也很麻烦,最后是在Course类下的compareTo方法中直接用1和-1来表示按照系、课程号排序的一个值,在add方法直接进行排序。
    compareTo方法:

if (prefix.compareTo(course.prefix) > 0)
        {
            return 1;
        }
        else
        {
            if (prefix.compareTo(course.prefix) < 0)
            {
                return -1;
            }
            else
            {
                if (number > course.number)
                {
                    return 1;
                }
                else
                {
                    return -1;

                }
            }
        }

add方法:

public void addCourse(Course course)
    {
        int i=0;
        for(Course course1:list)
        {
            if (course1.compareTo(course)<0)
                i++;
        }

        list.add(i,course);
    }

代码托管

上周代码行数为8867行,现在为10335行,本周共1468行,

上周考试错题总结

  • 上周没有错题

结对及互评

  • 本周结对学习情况
    • 20172308

    • 博客中值得学习的或问题: 博客中代码问题解决过程记录较详细,可适当添加教材内容总结。

    • 结对学习内容:学习第6章内容——列表

其他(感悟、思考等)

感悟

  • 假期学习时间有点短,2号完成了实验博客,学习了本章内容,之后几天做的内容不多,下周要投入多的时间。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/1 15/15
第二周 572/572 1/2 16/31
第三周 612/1184 1/3 13/44
第四周 1468/2652 2/5 13/57

参考资料

posted @ 2018-10-07 20:55  ◕‿◕  阅读(122)  评论(0编辑  收藏
© 2018 GitHub, Inc.