亲宝软件园·资讯

展开

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仅仅作为遍历操作出现。

加载全部内容

相关教程
猜你喜欢
用户评论