201871010111-刘佳华《面向对象程序设计(java)》第十二周学习总结
实验十 集合与GUI初步
实验时间 2019-11-14
第一部分:基础知识总结
- 第九章知识总结
1.栈(Stack)也是一种特殊的线性表,是一种后进先出 (LIFO)的结构。
栈是限定仅在表尾进行插入和删除运算的线性表,表尾称为栈顶(top),表头称为(bottom)。
栈的物理存储可以用顺序存储结构,也可以用链式存储结构。
2.队列(Queue)是限定所有的插入只能在表的一端进行 ,而所有的删除都在表的另一端进行的线性表。
表中允许插入的一端称为队尾(Rear),允许删除的一端称为队头(Front)。
队列的操作是按先进先出(FIFO)的原则进行的。队列的物理存储可以用顺序存储结构,也可以用链式存储结构。
3.一般将数据结构分为两大类:线性数据结构和非线性数据结构。
线性数据结构:线性表、栈、队列、串、数组和文件。
非线性数据结构:树和图。线性表按其存储结构可分为顺序表和链表;用顺序存储结构存储的线性表称为顺序表;顺序表将线性表中的数据元素依次存放在某个存储区域中。
一维数组就是用顺序方式存储的线性表。用链式存储结构存储的线性表称为链表。
4.集合框架:JAVA集合类库的统一架构。
集合类的作用:Java的集合类提供了一些基本数据结构的支持。
集合类的使用: Java的集合类包含在java.util包中。
集合类的特点一:只容纳对象。
注意:数组可以容纳基本数据类型数据和对象。如果集合类中想使用基本数据类型,又想利用集合类的灵活性,可以把基本数据类型数据封装成该数据类型的包装器对象,然后放入集合中处理。特点二:集合类容纳的对象都是Object类的实例,一旦把一个对象置入集合类中,它的类信息将丢失,这样设计的目的是为了集合类的通用性。因为Object类是所有类的祖先,所以可以在这些集合中存放任何类的对象而不受限制,但在使用集合成员之前必须对它重新造型。
5.JAVA的集合框架实现对各种数据结构的封装,以降低对数据管理与处理的难度。所谓框架就是一个类库的集合,框架中包含很多超类,编程者创建这些超类的子类可较方便的设计设计程序所需的类。
6.Map接口用来维持很多“键-值”对,以便通过键来查找相应的值。
HashMap基于散列表实现(替代Hashtable)。
TreeMap在一个二叉树的基础上实现(map)是一个存储关键字和值的关联或关键字/值对的对象。给定一个关键字,可以得到它的值。关键字和值都是对象。关键字必须是唯一的。但值是可以被复制的。Map接口映射唯一关键字到值。
关键字(key)是以后用于检索值的对象。给定一个关键字和一个值,可以存储这个值到一个Map对象中。当这个值被存储以后,就可以使用它的关键字来检索它,Map循环使用两个基本操作:get( )和put( )。使用 put( )方法可以将一个指定了关键字和值的值加入映射。为了得到值可以通过将关键字作为参数来调用 get( )方法。调用返回该值。
Map接口的实现类主要有HashMap,TreeMap,Hashtable,Properties。HashMap对key进行散TreeMap按照key进行排序。和Set类似,HashMap的速度通常都比TreeMap快,只有在需要排序的功能的时候,才使用TreeMap。
7.Vector类类似长度可变的数组。Vector中只能存放对象。Vector的元素通过下标进行访问。
Vector类关键属性:capacity表示集合最多能容纳的元素个数。capacityIncrement表示每次增加多少容量。size表示集合当前元素个数。
Stack类是Vector的子类。Stack类描述堆栈数据结构,即LIFO。
Hashtable通过键来查找元素。Hashtable用散列码(hashcode)来确定键。
所有对象都有一个散列码,可以通过Object类的hashCode()方法获得。
8.集合框架中的基本接口:Collection:集合层次中的根接口,JDK未提供这个接口的直接实现类。
Set:不能包含重复的元素。对象可能不是按存放的次序存放,也就是说不能像数组一样按索引的方式进行访问,SortedSet是一个按照升序排列元素的Set。List的明显特征是它的元素都有一个确定的顺序。实现它的类有ArrayList和LinkedList。ArrayList中的元素在内存中是顺序存储的。LinkedList中的元素在内存中是以链表方式存储的。
TreeSet是一个有序集合,TreeSet中元素将照升序排列,缺省是按照自然顺序进行排列,意味着TreeSet中元素要实现Comparable接口。可以在构造TreeSet对象时,传递实现了 Comparator接口的比较器对象。HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。通常使用HashSet,需要排序的功能时,使用TreeSet。
- 第十章知识总结(GUI初步)
1.Java的抽象口工具箱( Abstract WindowToolkit, AWT)包含在java.awt包中,它提供了许多用来设计GUI的组件类和容器类。
2.AWT库处理用户界面元素的方法:把图形元素的创建和行为委托给本地GUI工具箱进行处理。
3.Swing用户界面库是非基于对等体的GUI工具箱。Swing具有更丰富并且更方便的用户界面元素集合。Swing对底层平台的依赖很少,因此与平台相关的bug很少。Swing会带来交叉平台上的统一视觉体验。Swing类库被放在 javax.swing 包里。
4.大部分AWT组件都有其 Swing的等价组件。Swing组件的名字一般是在AWT组件名前面添加一个字母“J”,如:JButton,JFrame,JPanel等。
5.通常把由Component类的子类或间接子类创建的对象称为一个组件
6.Swing 组件层次关系
7..组件类的常用API
java.awt.Component 1.0
– boolean isVisible() 检查组件是否可见
– void setVisible(boolean b) 设置组件可见
– void setSize(int width,int height) 把组件缩放到指定宽度和高度
– void setBounds(int x,int y,int width,int height) 移动并缩放组件
– Dimension getSize() 得到组件的大小
– void setSize(Dimension d) 把组件缩放到指定的大小
– void setLocation(int x,int y)
8.容器是Java中能容纳和排列组件的组件。常用的容器是框架(Frame,JFrame)。
Container类提供了一个方法add(),用来在容器类 组件对象中添加其他组件。
容器本身也是一个组件,可以把一个容器添加到 另一个容器里,实现容器嵌套。
框架定位:常用Component类的setLocation和setBounds方法。常用属性:Title:框架标题;IconImage:框架图标。
确定框架大小:通过调用Toolkit类的方法来得到屏幕尺寸信息。
Jframe的结构:它由根面板、层级面板、玻璃面板和内容面板(content pane)四层面板构成。
Swing程序员最关心的是内容面板,也称为内容窗格。
在AWT中可调用add()方法把组件直接添加到AWT Frame中,在Swing中组件则添加到内容窗格里。
其中内容窗格是用来添加组件的,添加代码如下:Container contentPane = getContentPane(); Component c=…; contentPane.add(c);
用户也可以自行创建一个组件类,并在组件上进行绘制,此时需要重载paintComponent()。用户的自建组件也可添加到内容窗格里。
paintComponent(Graphics g)定义在JComponent类中,该方法在窗口需要重新绘图时(如扩大窗口或极小化窗口),被系统自动调用.
paintComponent()方法被调用时,系统就自动产生一个Graphics类型的参数,传递给paintComponent方法中的参数g。
第二部分:实验内容和步骤
1、实验目的与要求
(1) 掌握Vetor、Stack、Hashtable三个类的用途及常用API;
(2) 掌握ArrayList、LinkList两个类的用途及常用API。
(3) 掌握Java GUI中框架创建及属性设置中常用类的API;
(4) 应用结对编程(Pair programming),体验程序开发中的两人合作。
实验1: 导入第9章示例程序,测试程序并进行代码注释。
测试程序1:
l 使用JDK命令运行编辑、运行以下三个示例程序,结合运行结果理解程序;
l 掌握Vetor、Stack、Hashtable三个类的用途及常用API。
1 package Demo; 2 //Vector类举例 3 import java.util.Vector; 4 5 class Cat{ 6 private int catNumber; 7 Cat(int i){ 8 catNumber =i; 9 } 10 void print() { 11 System.out.println("Cat#"+catNumber); 12 } 13 14 } 15 public class Cats { 16 17 public static void main(String[] args) { 18 19 Vectorcats=new Vector (); 20 for(int i=0;i<7;i++) { 21 cats.addElement(new Cat(i));//添加新的Cat对象作为Vector的元素 22 } 23 for(int i=0;i ) { 24 (cats.elementAt(i)).print(); 25 //System.out.println(cats.elementAt(i)); 26 } 27 } 28 29 }
测试代码运行截图:
1 package Demo; 2 3 import java.util.*; 4 5 6 public class Stacks { 7 8 static String[] months= {"jing","ying","tong","tie"};//创建字符串数组 9 public static void main(String[] args) { 10 Stackstk=new Stack ();//创建以字符串数组对象为元素的栈对象 11 for(int i=0;i ) { 12 stk.push(months[i]);//压栈 13 } 14 stk.add("opi");//add方法将字符串opi放置到栈顶 15 16 //System.out.println(stk.lastElement()); 17 //stk.remove(0); 18 System.out.println(stk);//将整个栈输出 19 System.out.println("element 2="+stk.elementAt(2));//访问下标为2的栈元素,其下标与数组一致 20 while(!stk.empty()) 21 System.out.println(stk.pop());//栈不为空时出栈 22 } 23 }
测试代码运行截图:
1 package Demo; 2 3 import java.util.*; 4 import java.util.Map.Entry; 5 6 class Counter { 7 int i = 1; //friendly 8 public String toString() { 9 return Integer.toString(i); 10 } 11 } 12 13 public class Statistics { 14 public static void main(String[] args) { 15 Hashtableht = new Hashtable (); //counter和Integer类对象作为Hashtable的参数 16 for (int i = 0; i < 10000; i++) { 17 Integer r = new Integer((int) (Math.random() * 20)); 18 if(ht.containsKey(r)) //存在键值 19 ((Counter)ht.get(r)).i++; 20 else 21 ht.put(r, new Counter()); //.put(Integer key, Counter value) 22 } 23 System.out.println(ht); 24 /*for(Entry et :ht.entrySet()){ 25 System.out.println(et.getKey()+":"+et.getValue()); 26 }*/ 27 28 } 29 }
程序解析:
该示例检验Math.random()方法的随机性。在理想情况下,该方法应该产生一系列完美的随机分布的数字。为了验证这一点,需要生成数量众多的随机数字,然后计算落在不同范围内的数字量。该程序生成10000个随数,查看它们在0~20之间的分布如何。
测试代码运行截图:
测试程序2:
l 使用JDK命令编辑运行ArrayListDemo和LinkedListDemo两个程序,结合程序运行结果理解程序;
l 在Elipse环境下编辑运行调试教材360页程序9-1,结合程序运行结果理解程序;
l 掌握ArrayList、LinkList两个类的用途及常用API。
1 package Demo; 2 3 import java.util.*; 4 5 public class ArrayListDemo { 6 public static void main(String[] argv) { 7 ArrayList al = new ArrayList(); 8 // 在ArrayList中添加对象元素... 9 al.add(new Integer(11)); 10 al.add(new Integer(12)); 11 al.add(new Integer(13)); 12 al.add(new String("hello")); 13 // 首先用for循环按下标打印出来. 14 System.out.println("Retrieving by index:"); 15 for (int i = 0; i < al.size(); i++) { 16 System.out.println("Element " + i + " = " + al.get(i)); 17 } 18 } 19 }
运行截图:
1 package Demo; 2 3 import java.util.*; 4 public class LinkedListDemo { 5 public static void main(String[] argv) { 6 LinkedList l = new LinkedList(); 7 l.add(new Object()); 8 l.add("Hello"); 9 l.add("zhangsan"); 10 ListIterator li = l.listIterator(0); //获取得带器对象 11 while (li.hasNext()) //返回一个boolearn值,判断有没有下一个 12 System.out.println(li.next()); 13 if (l.indexOf("Hello") < 0) 14 System.err.println("Lookup does not work"); 15 else 16 System.err.println("Lookup works"); 17 } 18 }
运行截图:
- 教材实例程序 9-1
1 package Demo; 2 3 import java.util.*; 4 5 /** 6 * This program demonstrates operations on linked lists. 7 * @version 1.12 2018-04-10 8 * @author Cay Horstmann 9 */ 10 public class LinkedListTest 11 { 12 public static void main(String[] args) 13 { 14 var a = new LinkedList(); 15 a.add("Amy"); 16 a.add("Carl"); 17 a.add("Erica"); 18 19 var b = new LinkedList (); 20 b.add("Bob"); 21 b.add("Doug"); 22 b.add("Frances"); 23 b.add("Gloria"); 24 25 // 把b中的单词合并成a 26 27 ListIterator aIter = a.listIterator(); 28 Iterator bIter = b.iterator(); 29 30 while (bIter.hasNext()) 31 { 32 if (aIter.hasNext()) 33 aIter.next(); 34 aIter.add(bIter.next()); 35 } 36 37 System.out.println(a); 38 39 // 删除b中的每第二个单词 40 41 bIter = b.iterator(); 42 while (bIter.hasNext()) 43 { 44 bIter.next(); // 跳过一个元素 45 if (bIter.hasNext()) 46 { 47 bIter.next(); // 跳过又一个元素 48 bIter.remove(); // 删除此元素 49 } 50 } 51 52 System.out.println(b); 53 54 // 批量操作:从a中删除b中的所有单词 55 56 a.removeAll(b); 57 58 System.out.println(a); 59 } 60 }
运行截图:
迭代器中API:
- hasNext:没有指针下移操作,只是判断是否存在下一个元素
- next:指针下移,返回该指针所指向的元素
- remove:删除当前指针所指向的元素,一般和next方法一起用,这时候的作用就是删除next方法返回的元素
Iterator和ListIterator区别
我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器)。使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了。但是在使用的时候也是有不同的。List和Set都有iterator()来取得其迭代器。对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:
(1)ListIterator有add()方法,可以向List中添加对象,而Iterator不能
(2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
(3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
(4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。
因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。
实验2:导入第10章示例程序,测试程序并进行代码注释。
测试程序1:
l 运行下列程序,观察程序运行结果。
1 package GUI; 2 import javax.swing.*; 3 public class FirstSimpleFrame { 4 public static void main(String[] args) 5 { 6 JFrame frame = new JFrame(); 7 frame.setBounds(0, 0,300, 200); 8 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 9 frame.setVisible(true); 10 } 11 }
运行截图:
l 在elipse IDE中调试运行教材407页程序10-1,结合程序运行结果理解程序;与上面程序对比,思考异同;
l 掌握空框架创建方法;
l 了解主线程与事件分派线程概念;
l 掌握GUI顶层窗口创建技术。
教材程序10-1
1 package GUI; 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 /** 7 * @version 1.34 2018-04-10 8 * @author Cay Horstmann 9 */ 10 public class SimpleFrameTest 11 { 12 public static void main(String[] args) 13 { 14 EventQueue.invokeLater(() -> 15 { 16 var frame = new SimpleFrame(); 17 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭可用 18 frame.setVisible(true); 19 }); 20 } 21 } 22 23 class SimpleFrame extends JFrame 24 { 25 private static final int DEFAULT_WIDTH = 300; 26 private static final int DEFAULT_HEIGHT = 200; 27 28 public SimpleFrame() 29 { 30 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 31 } 32 }
运行结果与FirstSimpleFrame一致。
测试程序2:
l 在elipse IDE中调试运行教材412页程序10-2,结合运行结果理解程序;
l 掌握确定框架常用属性的设置方法。
1 package GUI; 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 /** 7 * @version 1.35 2018-04-10 8 * @author Cay Horstmann 9 */ 10 public class SizedFrameTest 11 { 12 public static void main(String[] args) 13 { 14 EventQueue.invokeLater(() -> 15 { 16 var frame = new SizedFrame(); 17 frame.setTitle("SizedFrame"); 18 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 frame.setVisible(true); 20 }); 21 } 22 } 23 24 class SizedFrame extends JFrame 25 { 26 public SizedFrame() 27 { 28 // 得到屏幕像素对 29 30 Toolkit kit = Toolkit.getDefaultToolkit(); 31 Dimension screenSize = kit.getScreenSize(); 32 33 int screenHeight = screenSize.height; 34 int screenWidth = screenSize.width; 35 //System.out.println(screenSize.height); 36 //System.out.println(screenSize.width); 37 // 设置框架宽度、高度并让平台拾取屏幕位置 38 39 setLocationByPlatform(true); 40 setSize(screenWidth / 2, screenHeight / 2); 41 setLocation(50,50); 42 //setBounds(50, 50, (screenWidth / 2), (screenHeight / 2)); 43 setVisible(true);//设置组件可见性,顶层组件除外 44 45 // 设置帧图标 46 47 Image img = new ImageIcon("C:\\Users\\83583\\Pictures\\Saved Pictures\\timg.jpg").getImage();//修改图标 48 setIconImage(img); 49 } 50 }
运行结果:
测试程序3:
l 在elipse IDE中调试运行教材418页程序10-3,结合运行结果理解程序;
l 掌握在框架中添加组件;
掌握自定义组件的用法。
1 package GUI; 2 3 import javax.swing.*; 4 import java.awt.*; 5 6 /** 7 * @version 1.34 2018-04-10 8 * @author Cay Horstmann 9 */ 10 public class NotHelloWorld 11 { 12 public static void main(String[] args) 13 { 14 15 EventQueue.invokeLater(() -> 16 { 17 var frame = new NotHelloWorldFrame(); 18 frame.setTitle("NotHelloWorld"); 19 20 21 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 22 frame.setVisible(true); 23 }); 24 } 25 } 26 27 /** 28 * A frame that contains a message panel. 29 */ 30 class NotHelloWorldFrame extends JFrame 31 { 32 public NotHelloWorldFrame() 33 { 34 add(new NotHelloWorldComponent()); 35 pack(); 36 } 37 38 39 } 40 41 /** 42 * A component that displays a message. 43 */ 44 class NotHelloWorldComponent extends JComponent 45 { 46 public static final int MESSAGE_X = 75; 47 public static final int MESSAGE_Y = 100; 48 49 private static final int DEFAULT_WIDTH = 300; 50 private static final int DEFAULT_HEIGHT = 200; 51 52 public void paintComponent(Graphics g) 53 { 54 55 g.setColor(Color.red); 56 g.drawString("Not a Hello, World program", MESSAGE_X, MESSAGE_Y); 57 58 } 59 60 61 62 public Dimension getPreferredSize() 63 { 64 return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); 65 } 66 }
运行截图:
第三部分:实验心得
通过本周的学习我了解了新旧集合类的不同, 掌握了Vetor、StacHashtable三个类的用途, 对于HashSet类、TreeSet类的用途以及HashMap、TreeMap两个类的用途尚且理解不是很到位,在后面的学习中应该进行再理解。此外还了解与图形用户界面设计有关的知识,了解了如何用一些组件去画字,图形。了解了创建框架时的一些常用API,图形用户界面的一些基础的设计操作,比如窗口显示不同图形,文字等等,觉得很有意思;但实际用这些知识自己去设计图形还是会有一定的难度。通过练习题集练习学过的内容,对学过的知识进行了再巩固,加深了理解。