201871010114-李岩松《面向对象程序设计(java)》第十二周学习总结
李岩松0198 人气:1
项目 |
内容 |
这个作业属于哪个课程 |
https://www.cnblogs.com/nwnu-daizh/ |
这个作业的要求在哪里 |
https://www.cnblogs.com/nwnu-daizh/p/11435127.html |
作业学习目标 |
(1) 掌握Vetor、Stack、Hashtable三个类的用途及常用API; (2) 掌握ArrayList、LinkList两个类的用途及常用API; (3) 了解java集合框架体系组成; (4) 掌握Java GUI中框架创建及属性设置中常用类的API; (5) 了解Java GUI中2D图形绘制常用类的API; |
第一部分:总结第九章、第十章理论知识
一、 Collection集合
1.1 集合概述
在前面基础班我们已经学习过并使用过集合ArrayList<E> ,那么集合到底是什么呢?
* **集合**:集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
* 数组的长度是固定的。集合的长度是可变的。
* 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
1.2 集合框架
JAVASE提供了满足各种需求的API,在使用这些API前,先了解其继承与接口操作架构,才能了解何时采用哪个类,以及类之间如何彼此合作,从而达到灵活应用。
集合按照其存储结构可以分为两大类,分别是单列集合`java.util.Collection`和双列集合`java.util.Map`,今天我们主要学习`Collection`集合,在day04时讲解`Map`集合。
* **Collection**:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是`java.util.List`和`java.util.Set`。其中,`List`的特点是元素有序、元素可重复。`Set`的特点是元素无序,而且不可重复。`List`接口的主要实现类有`java.util.ArrayList`和`java.util.LinkedList`,`Set`接口的主要实现类有`java.util.HashSet`和`java.util.TreeSet`。
从上面的描述可以看出JDK中提供了丰富的集合类库,为了便于初学者进行系统地学习,接下来通过一张图来描述整个集合类的继承体系。
其中,橙色框里填写的都是接口类型,而蓝色框里填写的都是具体的实现类。这几天将针对图中所列举的集合类进行逐一地讲解。
集合本身是一个工具,它存放在java.util包中。在`Collection`接口定义着单列集合框架中最最共性的内容。
1.3 Collection 常用功能
Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:
* `public boolean add(E e)`: 把给定的对象添加到当前集合中 。
* `public void clear()` :清空集合中所有的元素。
* `public boolean remove(E e)`: 把给定的对象在当前集合中删除。
* `public boolean contains(E e)`: 判断当前集合中是否包含给定的对象。
* `public boolean isEmpty()`: 判断当前集合是否为空。
* `public int size()`: 返回集合中元素的个数。
* `public Object[] toArray()`: 把集合中的元素,存储到数组中。
方法演示:
~~~java
import java.util.ArrayList;
import java.util.Collection;
public class Demo1Collection {
public static void main(String[] args) {
// 创建集合对象
// 使用多态形式
Collection<String> coll = new ArrayList<String>();
// 使用方法
// 添加功能 boolean add(String s)
coll.add("小李广");
coll.add("扫地僧");
coll.add("石破天");
System.out.println(coll);
// boolean contains(E e) 判断o是否在集合中存在
System.out.println("判断 扫地僧 是否在集合中"+coll.contains("扫地僧"));
//boolean remove(E e) 删除在集合中的o元素
System.out.println("删除石破天:"+coll.remove("石破天"));
System.out.println("操作之后集合中元素:"+coll);
// size() 集合中有几个元素
System.out.println("集合中有"+coll.size()+"个元素");
// Object[] toArray()转换成一个Object数组
Object[] objects = coll.toArray();
// 遍历数组
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
// void clear() 清空集合
coll.clear();
System.out.println("集合中内容为:"+coll);
// boolean isEmpty() 判断是否为空
System.out.println(coll.isEmpty());
}
}
~~~
> tips: 有关Collection中的方法可不止上面这些,其他方法可以自行查看API学习。
二、Iterator迭代器
2.1 Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口`java.util.Iterator`。`Iterator`接口也是Java集合中的一员,但它与`Collection`、`Map`接口有所不同,`Collection`接口与`Map`接口主要用于存储元素,而`Iterator`主要用于迭代访问(即遍历)`Collection`中的元素,因此`Iterator`对象也被称为迭代器。
想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:
* `public Iterator iterator()`: 获取集合对应的迭代器,用来遍历集合中的元素的。
下面介绍一下迭代的概念:
* **迭代**:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Iterator接口的常用方法如下:
* `public E next()`:返回迭代的下一个元素。
* `public boolean hasNext()`:如果仍有元素可以迭代,则返回 true。
接下来我们通过案例学习如何使用Iterator迭代集合中元素:
~~~java
public class IteratorDemo {
public static void main(String[] args) {
// 使用多态方式 创建对象
Collection<String> coll = new ArrayList<String>();
// 添加元素到集合
coll.add("串串星人");
coll.add("吐槽星人");
coll.add("汪星人");
//遍历
//使用迭代器 遍历 每个集合对象都有自己的迭代器
Iterator<String> it = coll.iterator();
// 泛型指的是 迭代出 元素的数据类型
while(it.hasNext()){ //判断是否有迭代元素
String s = it.next();//获取迭代出的元素
System.out.println(s);
}
}
}
~~~
> tips::在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生java.util.NoSuchElementException没有集合元素的错误。
2.2 迭代器的实现原理
我们在之前案例已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例来演示Iterator对象迭代元素的过程:
在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
2.3 增强for
增强for循环(也称for each循环)是**JDK1.5**以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
~~~java
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
~~~
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
练习1:遍历数组
~~~java
public class NBForDemo1 {
public static void main(String[] args) {
int[] arr = {3,5,6,87};
//使用增强for遍历数组
for(int a : arr){//a代表数组中的每个元素
System.out.println(a);
}
}
}
~~~
练习2:遍历集合
~~~java
public class NBFor {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("小河神");
coll.add("老河神");
coll.add("神婆");
//使用增强for遍历
for(String s :coll){//接收变量s代表 代表被遍历到的集合元素
System.out.println(s);
}
}
}
~~~
> tips: 新for循环必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。
三、 List集合
3.1 List接口介绍
`java.util.List`接口继承自`Collection`接口,是单列集合的一个重要分支,习惯性地会将实现了`List`接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
看完API,我们总结一下:
List接口特点:
1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
2. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
> tips:我们在基础班的时候已经学习过List接口的子类java.util.ArrayList类,该类中的方法都是来自List中定义。
3.2 List接口中常用方法
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:
- `public void add(int index, E element)`: 将指定的元素,添加到该集合中的指定位置上。
- `public E get(int index)`:返回集合中指定位置的元素。
- `public E remove(int index)`: 移除列表中指定位置的元素, 返回的是被移除的元素。
- `public E set(int index, E element)`:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
List集合特有的方法都是跟索引相关,我们在基础班都学习过,那么我们再来复习一遍吧:
```java
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List<String> list = new ArrayList<String>();
// 往 尾部添加 指定元素
list.add("图图");
list.add("小美");
list.add("不高兴");
System.out.println(list);
// add(int index,String s) 往指定位置添加
list.add(1,"没头脑");
System.out.println(list);
// String remove(int index) 删除指定位置元素 返回被删除元素
// 删除索引位置为2的元素
System.out.println("删除索引位置为2的元素");
System.out.println(list.remove(2));
System.out.println(list);
// String set(int index,String s)
// 在指定位置 进行 元素替代(改)
// 修改指定位置元素
list.set(0, "三毛");
System.out.println(list);
// String get(int index) 获取指定位置元素
// 跟size() 方法一起用 来 遍历的
for(int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
//还可以使用增强for
for (String string : list) {
System.out.println(string);
}
}
}
```
四、List的子类
4.1 ArrayList集合
`java.util.ArrayList`集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以`ArrayList`是最常用的集合。
许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。
4.2 LinkedList集合
`java.util.LinkedList`集合数据存储的结构是链表结构。方便元素添加、删除的集合。
> LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解下
实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。这些方法我们作为了解即可:
* `public void addFirst(E e)`:将指定元素插入此列表的开头。
* `public void addLast(E e)`:将指定元素添加到此列表的结尾。
* `public E getFirst()`:返回此列表的第一个元素。
* `public E getLast()`:返回此列表的最后一个元素。
* `public E removeFirst()`:移除并返回此列表的第一个元素。
* `public E removeLast()`:移除并返回此列表的最后一个元素。
* `public E pop()`:从此列表所表示的堆栈处弹出一个元素。
* `public void push(E e)`:将元素推入此列表所表示的堆栈。
* `public boolean isEmpty()`:如果列表不包含元素,则返回true。
LinkedList是List的子类,List中的方法LinkedList都是可以使用,这里就不做详细介绍,我们只需要了解LinkedList的特有方法即可。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。(了解即可)
方法演示:
~~~java
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> link = new LinkedList<String>();
//添加元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
System.out.println(link);
// 获取元素
System.out.println(link.getFirst());
System.out.println(link.getLast());
// 删除元素
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while (!link.isEmpty()) { //判断集合是否为空
System.out.println(link.pop()); //弹出集合中的栈顶元素
}
System.out.println(link);
}
}
~~~
五、Set接口
`java.util.Set`接口和`java.util.List`接口一样,同样继承自`Collection`接口,它与`Collection`接口中的方法基本一致,并没有对`Collection`接口进行功能上的扩充,只是比`Collection`接口更加严格了。与`List`接口不同的是,`Set`接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
`Set`集合有多个子类,这里我们介绍其中的`java.util.HashSet`、`java.util.LinkedHashSet`这两个集合。
> tips:Set集合取出元素的方式可以采用:迭代器、增强for。
5.1 HashSet集合介绍
`java.util.HashSet`是`Set`接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。`java.util.HashSet`底层的实现其实是一个`java.util.HashMap`支持,由于我们暂时还未学习,先做了解。
`HashSet`是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:`hashCode`与`equals`方法。
我们先来使用一下Set集合存储,看下现象,再进行原理的讲解:
~~~java
public class HashSetDemo {
public static void main(String[] args) {
//创建 Set集合
HashSet<String> set = new HashSet<String>();
//添加元素
set.add(new String("cba"));
set.add("abc");
set.add("bac");
set.add("cba");
//遍历
for (String name : set) {
System.out.println(name);
}
}
}
~~~
输出结果如下,说明集合中不能存储重复元素:
~~~
cba
abc
bac
~~~
> tips:根据结果我们发现字符串"cba"只存储了一个,也就是说重复的元素set集合不存储。
2.2 HashSet集合存储数据的结构(哈希表)
什么是哈希表呢?
在**JDK1.8**之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。
看到这张图就有人要问了,这个是怎么存储的呢?
为了方便大家的理解我们结合一个存储流程图来说明一下:
总而言之,**JDK1.8**引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。
5.3 HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一
创建自定义Student类
~~~java
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
~~~
~~~java
public class HashSetDemo2 {
public static void main(String[] args) {
//创建集合对象 该集合中存储 Student类型对象
HashSet<Student> stuSet = new HashSet<Student>();
//存储
Student stu = new Student("于谦", 43);
stuSet.add(stu);
stuSet.add(new Student("郭德纲", 44));
stuSet.add(new Student("于谦", 43));
stuSet.add(new Student("郭麒麟", 23));
stuSet.add(stu);
for (Student stu2 : stuSet) {
System.out.println(stu2);
}
}
}
执行结果:
Student [name=郭德纲, age=44]
Student [name=于谦, age=43]
Student [name=郭麒麟, age=23]
~~~
5.3 LinkedHashSet
我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?
在HashSet下面有一个子类`java.util.LinkedHashSet`,它是链表和哈希表组合的一个数据存储结构。
演示代码如下:
~~~java
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
结果:
bbb
aaa
abc
bbc
~~~
5.9 可变参数
在**JDK1.5**之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:
```
修饰符 返回值类型 方法名(参数类型... 形参名){ }
```
其实这个书写完全等价与
```
修饰符 返回值类型 方法名(参数类型[] 形参名){ }
```
只是后面这种定义,在调用时必须传递数组,而前者可以直接传递数据即可。
**JDK1.5**以后。出现了简化操作。**...** 用在参数上,称之为可变参数。
同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组(这就是简单之处),直接将数组中的元素作为实际参数进行传递,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。
代码演示:
```java
public class ChangeArgs {
public static void main(String[] args) {
int[] arr = { 1, 4, 62, 431, 2 };
int sum = getSum(arr);
System.out.println(sum);
// 6 7 2 12 2121
// 求 这几个元素和 6 7 2 12 2121
int sum2 = getSum(6, 7, 2, 12, 2121);
System.out.println(sum2);
}
/*
* 完成数组 所有元素的求和 原始写法
public static int getSum(int[] arr){
int sum = 0;
for(int a : arr){
sum += a;
}
return sum;
}
*/
//可变参数写法
public static int getSum(int... arr) {
int sum = 0;
for (int a : arr) {
sum += a;
}
return sum;
}
}
```
> tips: 上述add方法在同一个类中,只能存在一个。因为会发生调用的不确定性
> 注意:如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置。
第十章图形程序设计知识点总结:
1、swing概述:swing基于AWT架构之上,Swing是指被绘制的用户界、面类,AWT是指像事件处理这样的窗口工具箱的底层机制,Swing可以让用户随意的选择喜欢的感官。
2、框架:没有包含在其他窗口中的窗口被称为框架(frame),在AWT中有一个Frame类,是用来描述框架的,这个类在Swing版本中是JFrame(绝大数的Swing组件都有J开头),它是极少数几个不绘制在画布上的Swing组件之一,它的修饰部件(如按钮,标题栏,图标等)由用户的窗口系统绘制,而不是由Swing绘制,Swing用来绘制框架里的内容。
JFrame.setVisible(true)方法可以让框架可见,
JFrame.show()可以让框架可见并且置于其他窗口的前面。
JFrame.setDefaultCloseOperation(int i)可以定义关闭这个框架时候的响应动作,让程序退出的常量是JFrame.EXIT_ON_CLOSE。(以上方法都不是静态方法!)在初始化完后,main方法退出,这个时候程序并没有终止,终止的只是主线程,事件调度线程保持程序处于激活状态,直到关闭框架或者调用System.exit。
3、改变框架:
3.1、Component类:setVisible(boolean bool)设置窗口是否显示;
set||getSize(int w,int h||Dimension d)设置/获取大小;
set||getLocation(int x,int y)设置获取位置,setBounds(int x,int y,int w,int h)设置位置和大小。
3.2、windows类:toBack()将窗口移动到桌面窗口栈的后面 ;
toFront()将窗口移动到桌面的前面;
setLocationByPlatfrom(boolean bool)由平台选择一个合适的位置显示窗口。
3.3、Frame类: isResizable(boolean bool)是否可以让用户改变大小;
setTitle(String str)设置标题;
setIconImage(Image img)设置框架的图标。
setUndecorate(boolean bool)框架显示中的标题栏以及关闭按钮这些是否显示;
setExtendedState(int state)设置窗口的状态,如Frame.ICONIFIED可以让窗口最小化。
3.4、Toolkit类:getDefaultToolkit()返回一个默认的工具箱;
Dimension getScreen()返回用户屏幕的尺寸;
Image getImage(String filename)加载得到一个指定的图像对象。
4、绘制组件:绘制一个组件,需要定义一个扩展JComponent的类,并覆盖其中的paintComponent(Graphics g)方法,在JAVA中,所有的绘制都必须使用Craphics对象。只要窗口需要重新绘图时,事件处理器就会通告组件,从而执行所有组件的paintComponent方法。不用自己调用paintComponent方法,在应用程序需要重新绘图的时候,这个方法会自动的被调用,如果需要强制重新绘制组件,那么要调用的是repaint方法,他将引发采用相应配置的Graphics对象调用所有组件的paintComponent方法。
4.1、JFrame类:getContentPane()返回框架里的内容窗口;
add(Component comp)将一个给定的组件添加到该框架的内容窗口中。
4.2、Component类:repaint()重新绘制组件。
4.3、JPanel类是一个可以包含其他组件的容器,但同样也可以在其上面进行绘制。
5、绘制2D图形:主要是用java.awt.Graphics2D类去绘制图形的。图形的类主要在java.awt.geom里。要掌握这些之间的关系。
paintComponent方法可以自动获得一个Graphics对象,可以把他强制转型成Graphics2D对象。
第二部分:实验部分
1、实验目的与要求
(1) 掌握Vetor、Stack、Hashtable三个类的用途及常用API;
(2) 掌握ArrayList、LinkList两个类的用途及常用API。
(3) 掌握Java GUI中框架创建及属性设置中常用类的API;
(4) 应用结对编程(Pair programming),体验程序开发中的两人合作。
2、实验内容和步骤
实验1: 导入第9章示例程序,测试程序并进行代码注释。
测试程序1:
l 使用JDK命令运行编辑、运行以下三个示例程序,结合运行结果理解程序;
掌握Vetor、Stack、Hashtable三个类的用途及常用API
//示例程序1 import java.util.Vector; class Cat { private int catNumber; Cat(int i) { catNumber = i; } void print() { System.out.println("Cat #" + catNumber); } } public class Cats{ public static void main(String[] args){ Vector<Cat> cats= new Vector<Cat>(); for(int i=0; i<7; i++) cats.addElement(new Cat(i)); for(int i=0; i<cats.size(); i++) (cats.elementAt(i)).print(); } }
运行结果:
//示例程序2
package 集合; import java.util.Stack; public class Stacks { static String[] months = { "金", "银", "铜", "铁" }; public static void main(String[] args) { Stack<String> stk = new Stack<String>(); for (int i = 0; i < months.length; i++) stk.push(months[i]); System.out.println(stk); System.out.println("element2=" + stk.elementAt(2)); while (!stk.empty()) { System.out.println(stk.pop()); } } }
运行结果:
//示例程序3 import java.util.*; class Counter { int i = 1; public String toString() { return Integer.toString(i); } } public class Statistics { public static void main(String[] args) { Hashtable ht = new Hashtable(); for (int i = 0; i < 10000; i++) { Integer r = new Integer((int) (Math.random() * 20)); if(ht.containsKey(r)) ((Counter)ht.get(r)).i++; else ht.put(r, new Counter()); } System.out.println(ht); }
运行结果:
测试程序2:
l 使用JDK命令编辑运行ArrayListDemo和LinkedListDemo两个程序,结合程序运行结果理解程序;
import java.util.*; public class ArrayListDemo { public static void main(String[] argv) { ArrayList al = new ArrayList(); // Add lots of elements to the ArrayList... al.add(new Integer(11)); al.add(new Integer(12)); al.add(new Integer(13)); al.add(new String("hello")); // First print them out using a for loop. System.out.println("Retrieving by index:"); for (int i = 0; i < al.size(); i++) { System.out.println("Element " + i + " = " + al.get(i)); } } }
运行结果:
package 集合; import java.util.LinkedList; import java.util.ListIterator; public class LinkedListDemo { public static void main(String[] argv) { LinkedList l = new LinkedList(); l.add(new Object()); l.add("Hello"); l.add("zhangsan"); ListIterator li=l.listIterator(0);// listIterator(int index) 构造器,可以从指定下标处开始遍历 while(li.hasNext()) System.out.println(li.next()); if(l.indexOf("Hello")<0)//public int indexOf(int ch): 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。 System.out.println("Lookup does not work"); else System.out.println("Lookup works"); } }
运行结果:
l 在Elipse环境下编辑运行调试教材360页程序9-1,结合程序运行结果理解程序;
l 掌握ArrayList、LinkList两个类的用途及常用API。
package 集合; import java.util.*; /** * This program demonstrates operations on linked lists. * @version 1.12 2018-04-10 * @author Cay Horstmann */ public class LinkedListTest { public static void main(String[] args) { var a = new LinkedList<String>(); a.add("Amy"); a.add("Carl"); a.add("Erica"); var b = new LinkedList<String>(); b.add("Bob"); b.add("Doug"); b.add("Frances"); b.add("Gloria"); // merge the words from b into a ListIterator<String> aIter = a.listIterator(); Iterator<String> bIter = b.iterator(); while (bIter.hasNext()) { if (aIter.hasNext()) aIter.next(); aIter.add(bIter.next()); } System.out.println(a); // remove every second word from b bIter = b.iterator(); while (bIter.hasNext()) { bIter.next(); // skip one element if (bIter.hasNext()) { bIter.next(); // skip next element bIter.remove(); // remove that element } } System.out.println(b); // bulk operation: remove all words in b from a a.removeAll(b); System.out.println(a); } }
运行结果:
实验2:导入第10章示例程序,测试程序并进行代码注释。
测试程序1:
l 运行下列程序,观察程序运行结果。
package 集合; import javax.swing.JFrame; public class SimpleFrameTest { public static void main(String[] args) { JFrame frame=new JFrame(); frame.setBounds(0,0,300,200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
运行结果:
l 在elipse IDE中调试运行教材407页程序10-1,结合程序运行结果理解程序;与上面程序对比,思考异同;
l 掌握空框架创建方法;
l 了解主线程与事件分派线程概念;
l 掌握GUI顶层窗口创建技术。
package 图像程序设计; import java.awt.EventQueue; import javax.swing.JFrame; public class SimpleFrameTest { public static void main(String[] args) { EventQueue.invokeLater(()-> { SimpleFrame frame=new SimpleFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//是设置用户在此窗体上发起 "close" 时默认执行的操作。必须指定以下选项之一: frame.setVisible(true);//setVisible方法:程序框是不是在界面可见的 frame.setTitle("Hello world");//用于改变标题栏的文字 }); } }
运行结果:
测试程序2:
l 在elipse IDE中调试运行教材412页程序10-2,结合运行结果理解程序;
l 掌握确定框架常用属性的设置方法。
package 图像程序设计; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Image; import java.awt.Toolkit; import javax.swing.ImageIcon; import javax.swing.JFrame; public class SizedFrameTest{ public static void main(String[] args) { EventQueue.invokeLater(()-> { JFrame frame=new SizedFrame(); frame.setTitle("SizedFrame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } class SizedFrame extends JFrame{ public SizedFrame() { //get screen dimensions Toolkit kit=Toolkit.getDefaultToolkit();//调用Toolkit类的静态方法,getDefaultTookit得到Tookit对象 Dimension screenSize=kit.getScreenSize();//得到屏幕的尺寸 int screenHeight=screenSize.height; int screenWidth=screenSize.width; setSize(screenWidth/2,screenHeight/2); setLocationByPlatform(true); //set frame icon Image img=new ImageIcon("F:\\照片\\2019-05\\3e22741e711cf0b01c0e52dc4efc587b.jpg").getImage(); setIconImage(img); } }
运行结果:
测试程序3:
l 在elipse IDE中调试运行教材418页程序10-3,结合运行结果理解程序;
l 掌握在框架中添加组件;
l 掌握自定义组件的用法。
package 图像程序设计; import java.awt.EventQueue; import javax.swing.JFrame; public class NotHelloWorld { public static void main(String[] args) { EventQueue.invokeLater(()-> { JFrame frame=new NotHelloWorldFrame(); frame.setTitle("NotHelloWorld"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
package 图像程序设计; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.JComponent; public class NotHelloWorldComponent extends JComponent { public static final int MESSAGE_X=75; public static final int MESSAGE_Y=100; private static final int DFFAULT_WIDTH=300; private static final int DFFAULT_HEIGHT=300; public void paintComponent(Graphics g) { g.drawString("Not a Hello,World program", MESSAGE_X, MESSAGE_Y); } public Dimension getPreferredSize() { return new Dimension( DFFAULT_WIDTH,DFFAULT_HEIGHT); } }
package 图像程序设计; import javax.swing.JFrame; public class NotHelloWorldFrame extends JFrame { public NotHelloWorldFrame() { add(new NotHelloWorldComponent()); pack(); } }
运行结果:
关于结对编程:
l 以下图片是一个结对编程场景:两位学习伙伴坐在一起,面对着同一台显示器,使用着同一键盘,同一个鼠标,他们一起思考问题,一起分析问题,一起编写程序
l 关于结对编程的阐述可参见以下链接:
http://www.cnblogs.com/xinz/archive/2011/08/07/2130332.html
http://en.wikipedia.org/wiki/Pair_programming
l 对于结对编程中代码设计规范的要求参考:
http://www.cnblogs.com/xinz/archive/2011/11/20/2255971.html
实验总结:
我的感受:本周主要学习了Vetor、Stack、Hashtable三个类的用途及常用API,ArrayList、LinkList两个类的用途及常用API,同时对于集合的知识进行了更加深入的学习,同时也学习了图形用户界面设计有关的知识,通过本章的学习我了解了如何用一些组件去画字,图形。了解了创建框架时的一些常用API,图形用户界面的一些基础的设计操作,比如窗口显示不同图形,文字等等,觉得很有意思;但实际用这些知识自己去设计图形还是会有一定的难度。通过练习题集练习学过的内容,对学过的知识进行了再巩固,加深了理解。
第一章 Collection集合
## 1.1 集合概述
在前面基础班我们已经学习过并使用过集合ArrayList<E> ,那么集合到底是什么呢?
* **集合**:集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
* 数组的长度是固定的。集合的长度是可变的。
* 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。
## 1.2 集合框架
JAVASE提供了满足各种需求的API,在使用这些API前,先了解其继承与接口操作架构,才能了解何时采用哪个类,以及类之间如何彼此合作,从而达到灵活应用。
集合按照其存储结构可以分为两大类,分别是单列集合`java.util.Collection`和双列集合`java.util.Map`,今天我们主要学习`Collection`集合,在day04时讲解`Map`集合。
* **Collection**:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是`java.util.List`和`java.util.Set`。其中,`List`的特点是元素有序、元素可重复。`Set`的特点是元素无序,而且不可重复。`List`接口的主要实现类有`java.util.ArrayList`和`java.util.LinkedList`,`Set`接口的主要实现类有`java.util.HashSet`和`java.util.TreeSet`。
从上面的描述可以看出JDK中提供了丰富的集合类库,为了便于初学者进行系统地学习,接下来通过一张图来描述整个集合类的继承体系。
![](img\Collection集合体系图.png)
其中,橙色框里填写的都是接口类型,而蓝色框里填写的都是具体的实现类。这几天将针对图中所列举的集合类进行逐一地讲解。
集合本身是一个工具,它存放在java.util包中。在`Collection`接口定义着单列集合框架中最最共性的内容。
## 1.3 Collection 常用功能
Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:
* `public boolean add(E e)`: 把给定的对象添加到当前集合中 。
* `public void clear()` :清空集合中所有的元素。
* `public boolean remove(E e)`: 把给定的对象在当前集合中删除。
* `public boolean contains(E e)`: 判断当前集合中是否包含给定的对象。
* `public boolean isEmpty()`: 判断当前集合是否为空。
* `public int size()`: 返回集合中元素的个数。
* `public Object[] toArray()`: 把集合中的元素,存储到数组中。
方法演示:
~~~java
import java.util.ArrayList;
import java.util.Collection;
public class Demo1Collection {
public static void main(String[] args) {
// 创建集合对象
// 使用多态形式
Collection<String> coll = new ArrayList<String>();
// 使用方法
// 添加功能 boolean add(String s)
coll.add("小李广");
coll.add("扫地僧");
coll.add("石破天");
System.out.println(coll);
// boolean contains(E e) 判断o是否在集合中存在
System.out.println("判断 扫地僧 是否在集合中"+coll.contains("扫地僧"));
//boolean remove(E e) 删除在集合中的o元素
System.out.println("删除石破天:"+coll.remove("石破天"));
System.out.println("操作之后集合中元素:"+coll);
// size() 集合中有几个元素
System.out.println("集合中有"+coll.size()+"个元素");
// Object[] toArray()转换成一个Object数组
Object[] objects = coll.toArray();
// 遍历数组
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
// void clear() 清空集合
coll.clear();
System.out.println("集合中内容为:"+coll);
// boolean isEmpty() 判断是否为空
System.out.println(coll.isEmpty());
}
}
~~~
> tips: 有关Collection中的方法可不止上面这些,其他方法可以自行查看API学习。
## 第二章 Iterator迭代器
## 2.1 Iterator接口
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口`java.util.Iterator`。`Iterator`接口也是Java集合中的一员,但它与`Collection`、`Map`接口有所不同,`Collection`接口与`Map`接口主要用于存储元素,而`Iterator`主要用于迭代访问(即遍历)`Collection`中的元素,因此`Iterator`对象也被称为迭代器。
想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:
* `public Iterator iterator()`: 获取集合对应的迭代器,用来遍历集合中的元素的。
下面介绍一下迭代的概念:
* **迭代**:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
Iterator接口的常用方法如下:
* `public E next()`:返回迭代的下一个元素。
* `public boolean hasNext()`:如果仍有元素可以迭代,则返回 true。
接下来我们通过案例学习如何使用Iterator迭代集合中元素:
~~~java
public class IteratorDemo {
public static void main(String[] args) {
// 使用多态方式 创建对象
Collection<String> coll = new ArrayList<String>();
// 添加元素到集合
coll.add("串串星人");
coll.add("吐槽星人");
coll.add("汪星人");
//遍历
//使用迭代器 遍历 每个集合对象都有自己的迭代器
Iterator<String> it = coll.iterator();
// 泛型指的是 迭代出 元素的数据类型
while(it.hasNext()){ //判断是否有迭代元素
String s = it.next();//获取迭代出的元素
System.out.println(s);
}
}
}
~~~
> tips::在进行集合元素取出时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会发生java.util.NoSuchElementException没有集合元素的错误。
## 2.2 迭代器的实现原理
我们在之前案例已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例来演示Iterator对象迭代元素的过程:
![](img\迭代器原理图.bmp)
在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
## 2.3 增强for
增强for循环(也称for each循环)是**JDK1.5**以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
~~~java
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
~~~
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
#### 练习1:遍历数组
~~~java
public class NBForDemo1 {
public static void main(String[] args) {
int[] arr = {3,5,6,87};
//使用增强for遍历数组
for(int a : arr){//a代表数组中的每个元素
System.out.println(a);
}
}
}
~~~
#### 练习2:遍历集合
~~~java
public class NBFor {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("小河神");
coll.add("老河神");
coll.add("神婆");
//使用增强for遍历
for(String s :coll){//接收变量s代表 代表被遍历到的集合元素
System.out.println(s);
}
}
}
~~~
> tips: 新for循环必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。
加载全部内容