• [ Java学习 ] 泛型类的应用实验


    成文原因:

    这篇文章是我这周所做的 Java 实验题的一个小总结。

    这次实验让我深刻赞同了我们 Java 老师在这节实验课前告诉我们的话:

    最重要的是把问题想明白,它要怎么拆分成几个类,每个类里究竟需要哪些方法,具体细节怎么实现。当你真正把这些问题想清楚了以后,剩下的编程,其实就是很简单的事情了。难度往往不是难在编程,而是分解问题为一个个小问题后,逐一解决它们的能力。

      做完实验以后再来看老师这句话,觉得不能同意更多。

      我贴上来的代码有两份。

      前一份是未完成的代码,之所以未完成,是因为:写到一半时,觉得这样的结构设计太不合理了,如果照着这么写下去,会有许多重复的代码片段不断地出现,于是就想着这么去改进…怎样才能尽可能减少方法,但是提高代码的复用性呢?

      于是,果断放弃了前一种没写完的,不太优的结构,第二份代码才是写完时真正提交的最终版本。

      除了代码,我把实验报告的心得部分也一并贴了上来用以自警

    -------------------------------下面是实验题目------------------------------

     

     

    -------------------------------下面是代码------------------------------

    /*
      前一份是未完成的代码,之所以未完成,是因为:写到一半时,觉得这样的结构设计太不合理了,如果照着这么写下去,会有许多重复的代码片段不断地出现,于是就想着这么去改进…怎样才能尽可能减少方法,但是提高代码的复用性呢?
    
      于是,果断放弃了前一种没写完的,不太优的结构,第二份代码才是写完时真正提交的最终版本。
    
    */
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.*;
    class Customer
    {
    	private String name;
    	private String fNum; // flight number,表示他所定的航线的航线号
    	private int sum; //买了多少票
    	
    	Customer()
    	{
    	}
    	
    	Customer(String n, String f, int s)
    	{
    		name = n;
    		fNum = f;
    		sum = s;
    	}
    	
    	public void setName(String n)
    	{
    		name = n;
    	}
    	
    	public String getName()
    	{
    		return name;
    	}
    	
    	public void setSum(int s)
    	{
    		sum = s;
    	}
    	
    	public int getSum()
    	{
    		return sum;
    	}
    	
    	public void setfNum(String f)
    	{
    		fNum = f;
    	}
    	
    	String getfNum()
    	{
    		return fNum;
    	}
    }
    
    class Flight
    {
    	private static int sum = 0; //航线计数
    	private int order; //航线排列号
    	private String destination;//终点站名
    	private String FNum; //航班号
    	private int limit; //乘客限额
    	private int free; //余票数量
    	private LinkedList<Customer> booked; //已预定客户列表
    	private LinkedList<Customer> waiting; //等候替补客户名单
    	
    	Flight()
    	{
    		
    	}
    	
    	Flight(int o, String d, String F, int l)
    	{
    		order = o;
    		destination = d;
    		FNum = F;
    		limit = l;
    	}
    	
    	public int getOrder()
    	{
    		return order;
    	}
    	
    	public String getDestination()
    	{
    		return destination;
    	}
    	
    	public String getFNum()
    	{
    		return FNum;
    	}
    	
    	public int getLimit()
    	{
    		return limit;
    	}
    	
    	public int getFree()
    	{
    		return free;
    	}
    	
    	public void addFree(int f)
    	{
    		free += f;
    	}
    	
    	public void subFree(int f)
    	{
    		free -= f;
    	}
    	
    	public LinkedList<Customer> getBooked()
    	{
    		return booked;
    	}
    	
    	public LinkedList<Customer> getWaiting()
    	{
    		return waiting;
    	}
    	
    	public void showInfo() //show information
    	{
    		System.out.println("航线排列号为:" + order + " 终点站为:" + destination);
    		System.out.println("航班号为:" + FNum + " 成员定额为: " + limit + " 剩余票数为: " + free);
    		System.out.println("已订票客户有:");
    		
    		Iterator<Customer> it = booked.iterator();
    		for (; it.hasNext(); )
    		{
    			System.out.println(it.next().getName() + " ");
    		}
    		System.out.println();
    		System.out.println("等候替补客户有:");
    		for ( it = waiting.iterator(); it.hasNext(); )
    		{
    			System.out.println(it.next().getName() + " ");
    		}
    		System.out.println();
    	}
    }
    
    class Menu
    {
    	private ArrayList<Flight> flights;
    	Flight temp;
    	
    	public void init()
    	{
    		Flight f = new Flight(1, "北京","K2", 20);
    		flights.add(f);
    		f = new Flight(2, "北京","K3", 23);
    		flights.add(f);
    		f = new Flight(3, "成都","K4", 25);
    		flights.add(f);
    	}
    	
    	public void addFlight(Flight flight) //加入一条航线
    	{
    		flights.add(flight);
    	}
    	
    	public void query() //查询
    	{
    		Scanner in = new Scanner(System.in);
    		int order = in.nextInt(); //次序
    		Flight temp;
    		
    		Iterator<Flight> it = flights.iterator();
    		
    		for ( ; it.hasNext(); )
    		{
    			temp = it.next();
    			if (temp.getOrder() == order)
    			{
    				temp.showInfo();
    				return;
    			}
    		}				
    		System.out.println("没有检索到相关信息");	
    	}
    	
    	public void book() //订票
    	{
    		System.out.println("请输入航班号,您的姓名,以及您想要订购的票数");
    		Scanner in = new Scanner(System.in);
    		Flight temp;
    		
    		String tp, tp1; //tp 为航班号,tp1为姓名
    		int tem; // temporary
    		
    		tp = in.next();
    		tp1 = in.nextLine();
    		tem = in.nextInt();
    		
    		
    		Customer c = new Customer(tp1, tp, tem); //构造函数参数依次为:姓名、 航线号、 所购票数
    		Iterator<Flight> it = flights.iterator();
    
    		Flight temp;
    		
    		for ( ; it.hasNext(); )
    		{
    			temp = it.next();
    			if (temp.getFNum() == tp)
    			{
    				if (temp.getFree() >= tem)
    				{
    					temp.subFree(tem);
    					temp.getBooked().add(c);
    					System.out.println("购票成功");
    				}
    				else
    				{
    					temp.getWaiting().add(c);
    					System.out.println("抱歉,票数暂时不够!");
    				}
    				return;
    			}
    		}
    		
    		 System.out.println("输入的航线不存在!");
    		
    		
    	}
    	
    	public void cancel() //退票
    	{
    		System.out.println("请输入航班号,您的姓名,以及您想要退票的票数");
    		Scanner in = new Scanner(System.in);
    		Flight temp;
    		
    		String tp, tp1; //tp 为航班号,tp1为姓名
    		int tem; // temporary
    		
    		tp = in.next();
    		tp1 = in.nextLine();
    		tem = in.nextInt();
    
    		Iterator<Flight> it = flights.iterator();
    
    		Flight temp;
    		
    		for ( ; it.hasNext(); )
    		{
    			temp = it.next();
    			if (temp.getFNum() == tp) //确认航班号确实存在
    			{
    				for ( Iterator<Customer> it2= temp.getBooked().iterator(); it2.hasNext();  )
    				{
    					Customer now = it2.next();
    					if (now.getName() == tp1 && now.getfNum() == tp) //确认该顾客确实定了该航班的机票
    					{
    						temp.addFree(tem);
    						System.out.println("退票成功");
    						if (now.getSum() == tem) //如果顾客将自己买的票全部退票,则从买票列表删除该顾客
    							temp.getBooked().remove(now);	
    					}
    				}
    				
    				for ( Iterator<Customer> it2= temp.getWaiting().iterator(); it2.hasNext();  ) //遍历该航班的waiting列表,看是否有满足条件的购票请求可以满足
    				{
    					Customer now = it2.next();
    					if (now.getSum() <= temp.getFree())
    				}
    			}
    		}
    		
    		 System.out.println("输入信息有误");
    	}
    	
    	public void menu() //显示菜单
    	{
    		System.out.println("----------");
    		System.out.println("1.航线查询"); 
    		System.out.println("2.办理退票");
    		System.out.println("3.办理退票");
    		System.out.println("4.退出系统");
    		System.out.println("----------");
    		
    		Scanner in = new Scanner(System.in);
    		int order = in.nextInt(); //指令
    		
    		switch(order)
    		{
    		case 1: query(); break;
    		case 2: book(); break;
    		case 3: cancel(); break;
    		case 4: System.exit(0); in.close();break;
    		default: System.out.println("输入错误,请 重新运行订票系统!");
    		}
    		menu();
    	}
    }
    
    public class test 
    {
    	
    	public static void main(String args[] )
    	{
    		Menu m = new Menu();
    		m.menu();
    	}
    
    }
    

    //这份才是真正完整的,也是我提交的最终版本
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.*;
    class Customer
    {
    	private String name;
    	private String fNum; // flight number,表示他所定的航线的航线号
    	private int sum; //买了多少票
    	
    	Customer()
    	{
    	}
    	
    	Customer(String n, String f, int s)
    	{
    		name = n;
    		fNum = f;
    		sum = s;
    	}
    	
    	public String getName()
    	{
    		return name;
    	}
    	
    	public int getSum()
    	{
    		return sum;
    	}
    	
    	public String getfNum()
    	{
    		return fNum;
    	}
    	
    	public void setSum(int s)
    	{
    		sum = s;
    	}
    }
    
    class Flight
    {
    	private static int sum = 0; //航线计数
    	private int order; //航线排列号
    	private String destination;//终点站名
    	private String FNum; //航班号
    	private int limit; //乘客限额
    	private int free; //余票数量
    	private LinkedList<Customer> booked; //已预定客户列表
    	private LinkedList<Customer> waiting; //等候替补客户名单
    	
    	Flight()
    	{
    		
    	}
    	
    	Flight(int o, String d, String F, int l)
    	{
    		order = o;
    		destination = d;
    		FNum = F;
    		limit = free = l;
    		booked = new LinkedList<Customer>();
    		waiting = new LinkedList<Customer>();
    	}
    	
    	public String getDestination()
    	{
    		return destination;
    	}
    	
    	public String getFNum()
    	{
    		return FNum;
    	}
    	
    	public void showInfo() //show information
    	{
    		System.out.println("航线排列号为:" + order + " 终点站为:" + destination);
    		System.out.println("航班号为:" + FNum + " 成员定额为: " + limit + " 剩余票数为: " + free);
    		System.out.println();
    		System.out.println("已订票客户有:");
    		
    		Iterator<Customer> it = booked.iterator();
    		for (; it.hasNext(); )
    		{
    			System.out.println(it.next().getName() + " ");
    		}
    		System.out.println();
    		System.out.println("等候替补客户有:");
    		for ( it = waiting.iterator(); it.hasNext(); )
    		{
    			System.out.println(it.next().getName() + " ");
    		}
    		System.out.println();
    	}
    	
    	public void isbook(Customer c)
    	{
    		
    		if (c.getSum() > free) //检验是否有足够余票可供该顾客订票
    		{
    			System.out.println("抱歉,票数暂时不足!");
    			waiting.add(c);
    			return;
    		}
    		
    		book(c); //先判断可不可以订票,确认可以再订票
    	}
    	
    	public void book(Customer c) //这个函数可重用,在退票以后,遍历 waiting 链表之前
    	{
    		for (Iterator<Customer> it = booked.iterator();  it.hasNext(); ) //判断该顾客之前是否有订过该航班的票
    		{
    			Customer now = it.next();
    			if (now.getName().equals(c.getName()))
    			{
    				now.setSum(now.getSum() + c.getSum());
    				free -= c.getSum();
    				System.out.println("顾客" + c.getName() + "订票成功");
    				System.out.println("一共成功订票" + now.getSum() + "张,航班号为" + FNum );
    				return;
    			}
    		}
    		
    		booked.add(c);
    		free -= c.getSum();
    		System.out.println("顾客" + c.getName() + "订票成功");
    		System.out.println("一共成功订票" + c.getSum() + "张,航班号为" + FNum );
    	}
    	
    	public void cancel(Customer c)
    	{
    		Iterator<Customer> it = booked.iterator();
    		
    		boolean found = false;
    		for ( ; it.hasNext(); )
    		{
    			Customer now = it.next();
    			if (now.getName().equals(c.getName()))
    			{
    				found = true;
    				free += c.getSum();
    				System.out.println("退票成功");
    				if (now.getSum() == c.getSum())//如果顾客将自己买的票全部退票,则从买票列表删除该顾客
    				{
    					booked.remove(now);
    					break;
    				}
    			}
    		}
    		if (!found) System.out.println("退票失败,您没有定该航班的机票!");
    		System.out.println();
    		
    		it = waiting.iterator();
    		for ( ; it.hasNext(); )
    		{
    			Customer now = it.next();
    			if (now.getfNum().equals(FNum) && now.getSum() <= free)
    				book(now);
    		}
    	}
    }
    
    class Menu
    {
    	private ArrayList<Flight> flights;
    	Flight temp;
    	
    	public void init()
    	{
    		flights = new ArrayList<Flight>();
    		Flight f = new Flight(1, "北京","k2", 20);
    		addFlight(f);
    		f = new Flight(2, "北京","k3", 23);
    		addFlight(f);
    		f = new Flight(3, "成都","k4", 25);
    		addFlight(f);
    	}
    	
    	public void addFlight(Flight flight) //加入一条航线
    	{
    		flights.add(flight);
    	}
    	
    	public void query() //查询
    	{
    		System.out.println("请输入要查询的目的地城市:");
    		Scanner in = new Scanner(System.in);
    		String d = in.next();
    		Flight temp;
    		
    		Iterator<Flight> it = flights.iterator();
    		
    		boolean found = false;
    		for ( ; it.hasNext(); )
    		{
    			temp = it.next();
    			if (temp.getDestination().equals(d))
    			{
    				found = true;
    				temp.showInfo();
    			}
    		}				
    		if (!found)System.out.println("没有检索到相关信息");	
    	}
    	
    	public void book() //订票
    	{
    		Scanner in = new Scanner(System.in);
    		System.out.println("请输入订票人数:");
    		int t = in.nextInt();
    		
    		Flight temp; // 航班类临时变量
    		String tp, tp1; //tp 为航班号,tp1为姓名
    		int tem; // temporary
    		
    		for (int i = 0; i < t; i++)
    		{
    			System.out.println("请输入航班号,您的姓名,以及您想要订购的票数");
    			
    			tp = in.next();
    			tp1 = in.next();
    			tem = in.nextInt();
    			
    			Customer c = new Customer(tp1, tp, tem); //构造函数参数依次为:姓名、 航线号、 所购票数
    			Iterator<Flight> it = flights.iterator();
    			
    			boolean found = false;
    			for ( ; it.hasNext(); )
    			{
    				temp = it.next();
    				if (temp.getFNum().equals(tp))
    				{
    					temp.isbook(c);
    					found = true;
    					break;
    				}
    			}
    			
    			 if (!found) System.out.println("输入的航线不存在!");
    			 System.out.println();
    		}
    		
    	}
    	
    	public void cancel() //退票
    	{
    		Scanner in = new Scanner(System.in);
    		System.out.println("请输入退票人数:");
    		int t = in.nextInt();
    		Flight temp; // 航班类临时变量
    		String tp, tp1; //tp 为航班号,tp1为姓名
    		int tem; // temporary
    		
    		for (int i = 0; i < t; i++)
    		{
    			System.out.println("请输入航班号,您的姓名,以及您想要退票的票数");
    			tp = in.next();
    			tp1 = in.next();
    			tem = in.nextInt();
    			
    			Customer c = new Customer(tp1, tp, tem); //构造函数参数依次为:姓名、 航线号、 所购票数
    			Iterator<Flight> it = flights.iterator();
    
    			boolean found = false;
    			for ( ; it.hasNext(); )
    			{
    				temp = it.next();
    				if (temp.getFNum().equals(tp)) //确认航班号确实存在
    				{
    					temp.cancel(c);
    					found = true;
    					break;
    				}
    			}
    			 if (!found) System.out.println("输入信息有误");
    			 System.out.println();
    		}		
    	}
    	
    	public void menu() //显示菜单
    	{
    		System.out.println("----------");
    		System.out.println("1.航线查询"); 
    		System.out.println("2.办理订票");
    		System.out.println("3.办理退票");
    		System.out.println("4.退出系统");
    		System.out.println("----------");
    		
    		Scanner in = new Scanner(System.in);
    		int order = in.nextInt(); //指令
    		
    		switch(order)
    		{
    		case 1: query(); break;
    		case 2: book(); break;
    		case 3: cancel(); break;
    		case 4: System.exit(0); in.close();break;
    		default: System.out.println("输入错误,请重新运行订票系统!");
    		}
    		menu();
    	}
    }
    
    public class test 
    {	
    	public static void main(String args[] )
    	{
    		Menu m = new Menu();
    		m.init();
    		m.menu();
    	}
    }
    

    -------------------------------这些是实验心得体会------------------------------

    五、心得体会(要详细,编程中碰到的问题及解决方案)

    搜过的资料(都是超链接,可直接点击

    Java中关于nextInt()、next()和nextLine()的理解

     java获取用户输入的字符串!...

    JAVA中几种读取文件为字符串

    eclipse中如何去除警告:Class is a raw type. References to generictype Class<T> should be parameterized

    解决“List is a raw type. References to generic type List”提示的问题

    java泛型问题 关于警告:XXis a raw type【转】

    什么是rawType

     java出现Resourceleak: 'XXX' is never closed 解决方案

    初始化ArrayList的两种方法

    java:String使用equals和==比较的区别

     java.lang.NullPointerException 空指针异常问题

    Java_List元素的遍历和删除

     Java LinkedList基本用法

     java中System.exit()方法

    Java入门系列:实例讲解ArrayList用法

    改进和思考:

    1.        在写 Menu类 的 book() 和 cancel() 函数时,发现其实有大量重叠部分,因为 cancel() 函数在删除完以后,也是要遍历该航线的 Waiting列列表,看有没有 Customer 对象能够完成之前没能完成的订票。也就是说,book()函数里已经实现过的功能,还需要在 cancel()函数里在实现一次。

    这样导致的结果,就是代码看上去又拖沓又冗长,于是想了个办法,在航班类里加入 book() 和 cancel() 函数,并且将 Customer类对象作为参数传到航班类里,这样就能直接调用 Flight 类的函数来完成订票退票,可以提高代码的复用性。

    而且,如果传入 Customer类对象,那么,其实航班类的很多get函数都可以直接去掉了,一下子使代码简洁多了,看起来终于舒服多了,之前的一堆get函数很是拖沓…

    从这个优化的过程感受到的就是:

    不要急着敲代码,而是先想想能不能有更好的思路,比如这题,刚开始时就没有想到特别透彻清楚明白的程度,导致后来,实现函数的时候才发现,完全不用那么繁琐,明明有更简单的方法来实现,我为什么要弄得那么复杂?

    所以,先别急着敲代码,而是应该先把每一个细节琢磨清楚,多问问自己:还能不能再简化一点?能不能再把代码写优美一点?一拿到题目就做,往往是最浪费时间的方法,因为后面用来修改和优化的时间会更多。我应该做的是,每次把所有优化的可能考虑周全,尽量把类里的方法减少到最少,同时提高这些方法的利用率,我觉得这才是实验里最为关键的部分。

    2.      着手于简化、简化再简化

    将不必要的get 和 set 函数都去掉,例如 Customer类,该题不考虑顾客改名的情况,故而不需要  name 的 set方法;此外,该题没有一个顾客同时买多个航线的飞机票的情况,就算真的要处理这种情况,按照我的代码设计的逻辑,也是要新建一个 Customer 对象的,因为我觉得这样做更方便处理。

      再说详细一些就是,如果aaa同时买了 K2 和 K3 航班的票,那么,我打算采取的,不是将这这个航班的购票数都存在一个 Customer的对象里,而是打算再建立一个 Customer对象,保存 K3 的航班线名臣和K3的订票数。因为在办理订票和退票时,我们都是根据航班号来查航线的。如果把不同的航班号,存在同一个 Customer对象里,其实无形中加大了查找特定某航线的难度。

      所以,照着这么说,航线名也是不会改的,如果这个顾客买的某个航线的票,全都被他自己后来退光了,那也只需要在那个航线的 booked 链表里删掉这个顾客的信息即可

      这么想来,其实 fNum 的 set 方法也可以去掉,因为就本题的考虑,根本用不到这个方法。

      唯一需要保留的 set 方法,是sum的set方法,因为可能存在退票但没有退完的情况,这时就需要改变 Customer对象的订票数了。

      同理,对于 Flight 类,也应进行一次这样的考虑和排查。因为方法是为了解决问题而设计的,不是为了写一个方法而去写一个方法。所以,如果能更简单地解决问题,就不要把问题弄复杂了!~

    3.        情况考虑要比题目设置更加周全一些

    题目好像没提到一点,其实在进行订票时,也应该进行一轮该航班的 booked 列表的遍历。

    因为,考虑真实情况时,同一个顾客是可以多次订票的,所以,我们需要先知道顾客之前有没有订过票,订过和没订过的处理方式是不同的。

    4.      语法点和知识不太熟练,导致的失误

    4.1. 在进行字符串比较时,又忘了两个字符串之间是不能直接用 == 来判断相等的,而是应该用 equals 函数,又一次把 C++的语法规则套在Java上用了…说明我学的还是不到位啊!

    4.2. 此外,用于读取 String对象的 next 和 nextLine,必须弄清楚两者的区别,正确选择用哪个,否则用了 equals 来比较以后,得到的结果仍然是不相等

    4.3. 使用泛型前,要先对其进行初始化,否则会出现空指针错误

    -------------------------------其他相关文章------------------------------

     [ Java学习 ] 类的其他文章汇总(都是超链接,可直接点击):

    [ Java学习 ] 实验 银行业务模拟

    [ Java学习 ] 破除思维定势之C++ 和 Java 的差异001

    [ Java学习 ] 破除思维定势之C++ 和 Java 的差异002

    [ Java学习 ] 破除思维定势之C++ 和 Java 的差异003

    [ Java学习 ] 包语句package等语句的汇总整理

    [ Java学习 ] Java变量以及内存分配(非常重要)

    [ Java学习 ] 其他知识总结(重要)

    [ Java学习 ] “goto语句“和 “continue + 标号”的不同待遇

    [ Java学习 ] toString方法 和equals方法

     [ Java学习] 正则表达式与模式匹配

    [ Java学习 ] 查阅资料整理001

    [ Java学习 ] 查阅资料整理002

    [ Java学习] 查阅资料整理 003

    [ Java学习] 查阅资料整理 004

    [ Java学习 ] 一道Java好题的详细题解 001

    [ Java学习 ] 一些Java程序 001

    [ Java学习 ] 一些Java程序 002

  • 相关阅读:
    java.lang.UnsatisfiedLinkError: No implementation found for
    target release 1.5 conflicts with default source release 1.7
    (转)makefile里PHONY的相关介绍
    Hint: A potential Change-Id was found, but it was not in the footer (last paragraph) of the commit message
    linux jdk版本随时切换
    提高Service的优先级
    第一章、数字图像的描述
    gluas图形处理——导读
    图像处理学习过程——网站,视频,书籍(长期更新)
    基数排序
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789349.html
Copyright © 2020-2023  润新知