Java实验05 集合类

第七章 集合
实验7-1 Collection接口对集合的操作
一、实验描述
1、 考核知识点
名称:Collection接口
2、 练习目标
 掌握Collection接口中方法的使用
3、 需求分析
Collection是所有单列集合的父接口,在Collection中定义了单列集合(List和Set)通用的一些方法。为了让初学者熟悉Collection接口中的常用方法,本实验将演示Collection接口中的方法对集合进行操作来学习方法的使用。
4、 设计思路(实现原理)
1) 编写一个类Example01
2) 在类中定义两个Collection集合,并向其中一个集合中添加数据
3) 用Collection接口中的方法对定义的两个集合进行各种操作
二、实验实现

package Example01;


import java.util.*;
public class Example01 {
    public static void main(String[] args) {
        // 定义两个集合col1和col2,在col1中添加"123abc"、123、34.121
        Collection col1 = new ArrayList();
        Collection col2 = new ArrayList();
        col1.add("123abc");
        col1.add(123);
        col1.add(34.121);
        // 分别判断两个集合是否为空并输出结果
        System.out.println("col1 = "+col1);
        System.out.println("col2 = "+col2);
        // 将集合col1中的元素添加到 col2中并输出结果
        col2.addAll(col1);
        // 获取两个集合的交集
        boolean c = col1.retainAll(col2);
        System.out.println("col1和col2集合是否有交集:" + c);
        // 清除集合col2中的元素
        col2.clear();
        System.out.println("清除集合col2中的元素: col2 = "+col2);
        // 获取集合中元素的个数
        System.out.println("集合中col1元素的个数:"+col1.size());
    }
}

运行结果如图7-1所示。

图7-1 运行结果
三、实验总结
1、Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合,如表7-1所示。
表7-1 Collection中的方法
方法声明 功能描述
boolean add(Object o) 向集合中添加一个元素
boolean addAll(Collection c) 将指定Collection中的所有元素添加到该集合中
void clear() 删除该集合中的所有元素
boolean remove(Object o) 删除该集合中指定的元素
boolean removeAll(Collection c) 删除指定集合中的所有元素
boolean isEmpty() 判断该集合是否为空
boolean contains(Object o) 判断该集合中是否包含某个元素
boolean containsAll(Collection c) 判断该集合中是否包含指定集合中的所有元素
Iterator iterator() 返回在该集合的元素上进行迭代的迭代器(Iterator),用于遍历该集合所有元素
int size() 获取该集合元素个数
2、在编译实验时,会得到如图7-2所示的警告,意思是说在使用ArrayList集合时并没有显示的指定集合中存储什么类型的元素,会产生安全隐患,这涉及到泛型安全机制的问题。此警告对程序输出结果没有影响。

图7-2 编译警告
3、在编写程序时,不要忘记使用import java.util.*;语句导包,否则程序将会编译失败,显示类找不到。
实验7-2 List接口的特有方法
一、实验描述
1、 考核知识点
名称:List接口
2、 练习目标
 掌握List接口的常用方法的使用
3、 需求分析
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法。为了熟悉List接口中特有方法的使用,本实验将演示使用List接口中的方法对List集合进行添加、修改等操作。
4、 设计思路(实现原理)
1) 编写一个类Example02
2) 在类中定义两个list集合,并向其中一个集合中添加数据。
3) 用 subList(int fromIndex, int toIndex)方法获取集合的一部分
4) 用set(int index, E element)方法修改一个元素
5) 用add(int index, E element)方法增加一个元素
二、实验实现

package Example02;

import java.util.*;
public class Example02{
    public static void main(String[] args) {
        //在类中定义list集合,并向其中添加数据"abc1","abc2","abc3","abc4",输出list
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        System.out.println("list = "+list);
        //定义newlist集合,用subList()方法获取list集合的前两个元素,输出newlist
        List newlist = new ArrayList();
        newlist = list.subList(0,2);
        System.out.println("newlist = "+newlist);
        //set()方法修改list集合第1个位置元素值为haha,输出list
        list.set(0,"haha");
        System.out.println("set()方法修改list集合第1个位置元素值为haha: "+list);
        //add()方法在list集合第1个位置前增加一个元素QQ,输出list
        list.add(0,"QQ");
        System.out.println("add()方法在list集合第1个位置前增加一个元素QQ: "+list);
    }
}

运行结果如图7-3所示。

图7-3 运行结果
三、实验总结
1、在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
2、List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如表7-2所示。
表7-2 List接口中的常见方法
方法声明 功能描述
void add(int index,Object element) 将元素element插入在List集合的index处
boolean addAll(int index,Collection c) 将集合c所包含的所有元素插入到List集合的index处
Object get(int index) 返回集合索引index处的元素
Object remove(int index) 删除index索引处的元素
Object set(int index, Object element) 将索引index处元素替换成element对象,并将替换后的元素返回
int indexOf(Object o) 返回对象o在List集合中出现的位置索引
int lastIndexOf(Object o) 返回对象o在List集合中最后一次出现的位置索引
List subList(int fromIndex, int toIndex) 返回从索引fromIndex(包括 )到 toIndex(不包括)处所有元素集合组成的子集合

实验7-3 ArrayList集合的存取
一、实验描述
1、 考核知识点
名称:ArrayList集合
2、 练习目标
 了解ArrayList集合的特点
 掌握对ArrayList集合中元素的存取操作
3、 需求分析
ArrayList是List接口的一个实现类,ArrayList集合中大部分方法都是从父类Collection和List继承过来的。为了熟悉ArrayList集合的使用,本实验将演示ArrayList集合的定义、存储元素和取出元素。
4、 设计思路(实现原理)
1) 编写一个类Example03
2) 在类中定义一个ArrayList集合
3) 用add()方法向集合中添加元素
4) 用get()方法获取集合中的指定元素,由于ArrayList集合的索引的取值范围是从0开始的,最后一个索引是size-1。所以,要获取集合中的第2个元素应该是get(1)。
二、实验实现

package Example03;

import java.util.*;
public class Example03{
    public static void main(String[] args) {
        // 在类中定义一个ArrayList集合array,添加元素"lisi","wangwu","jordan",
        //"jackson","white",输出array
        ArrayList array = new ArrayList();
        array.add("lisi");
        array.add("wangwu");
        array.add("jordan");
        array.add("jackson");
        array.add("white");
        System.out.println("array = "+array);
        //输出array集合的第2个元素
        System.out.println("array集合的第2个元素: "+array.get(1));
    }
}

运行结果如图7-4所示。

图7-4 运行结果
三、实验总结
1、在ArrayList内部封装了一个长度可变的数组对象,当存入的元素超过数组长度时,ArrayList会在
内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。
2、索引位置为1的元素是集合中的第二个元素,这就说明集合和数组一样,索引的取值范围是从0开始的,最后一个索引是size-1,在访问元素时一定要注意索引不可超出此范围,否则会抛出角标越界异常IndexOutOfBoundsException。
3、由于ArrayList集合的底层是使用一个数组来保存元素,在增加或删除指定位置的元素时,会导致创建新的数组,效率比较低,因此不适合做大量的增删操作。但这种数组的结构允许程序通过索引的方式来访问元素,因此使用ArrayList集合查找元素很便捷。
实验7-4 LinkedList集合的特殊方法
一、实验描述
1、 考核知识点
名称:LinkedList集合
2、 练习目标
 了解LinkedList集合的特点
 掌握LinkedList集合的特殊方法的使用
3、 需求分析
ArrayList集合在查询元素时速度很快,但在增删元素时效率较低,为了克服这种局限性,可以使用List接口的另一个实现类LinkedList。LinkedList集合除了对于元素的增删操作具有很高的效率,还专门针对元素的增删操作定义了一些特有的方法。为了熟悉这些特殊的方法,本实验将演示如何使用LinkedList中的特殊方法对集合进行增删操作。
4、 设计思路(实现原理)
1) 编写一个类Example04,在该类中定义一个LinkedList集合
2) 分别使用addFirst()和addLast()方法向集合中添加元素
3) 使用peekFirst()方法获取集合中的第一个元素
4) 使用pollFirst()方法获取并移除集合中的第一个元素
5) 使用pollLast()方法获取并移除集合中的最后一个元素
6) 此时,集合中应该没有元素了,用peekLast()方法获取集合中的最后一个元素,由于集合为空,应该返回NULL
二、实验实现

package Example04;

import java.util.*;
public class Example04 {
    public static void main(String[] args) {
        //定义一个LinkedList集合link
        LinkedList link = new LinkedList();
        //将指定元素"abc1"插入此集合的开头
        link.addFirst("abc1");
        //将指定元素"haha"添加到此集合的结尾
        link.addLast("haha");
        //使用peekFirst()方法获取但不移除此集合的第一个元素
        System.out.println("使用peekFirst()方法获取但不移除此集合的第一个元素: "+link.peekFirst());
        //pollFirst()获取并移除此集合的第一个元素,输出link
        System.out.println("pollFirst()获取并移除此集合的第一个元素: "+link.pollFirst());
        System.out.println("输出link: "+link);
        // pollLast()获取并移除此集合的最后一个元素,输出link
        System.out.println("pollLast()获取并移除此集合的最后一个元素"+link.pollLast());
        System.out.println("输出link: "+link);
        // peekLast()获取但不移除此集合的最后一个元素
        System.out.println("peekLast()获取但不移除此集合的最后一个元素: "+link.peekFirst());
    }
}

运行结果如图7-5所示。

图7-5 运行结果
三、实验总结
1、LinkedList集合内部维护了一个双向循环链表,链表中的每一个元素都使用引用的方式来记住它的前一个元素和后一个元素,从而可以将所有的元素彼此连接起来。当插入一个新元素时,只需要修改元素之间的这种引用关系即可,删除一个节点也是如此。正因为这样的存储结构,所以LinkedList集合对于元素的增删操作具有很高的效率。
2、在本实验中,所用的方法及其功能具体如下:
1) peekFirst()方法用于获取LinkedList集合中的第一个元素,如果此列表为空则返回NULL
2) peekLast()方法用于获取LinkedList集合中的最后一个元素,如果此列表为空则返回NULL
3) pollFirst()方法用于获取并移除LinkedList集合中的第一个元素,如果此列表为空则返回NULL
4) pollLast()方法用于获取并移除LinkedList集合中的最后一个元素,如果此列表为空则返回NULL
5) addFirst()方法用于添加LinkedList集合中的第一个元素
6) addLast()方法用于添加LinkedList集合中的最后一个元素
实验7-5 Iterator遍历集合元素
一、实验描述
1、 考核知识点
名称:Iterator接口
2、 练习目标
 掌握Iterator迭代器的使用
3、 需求分析
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口Iterator。为了使初学者熟悉Iterator迭代器的使用,本实验将演示如何使用Iterator迭代器遍历集合中的元素。
4、 设计思路(实现原理)
1) 编写一个类Example05
2) 在类中定义一个List集合,并向集合中添加数据
3) 通过调用List集合的iterator()方法获得迭代器对象
4) 在while循环条件中使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素
二、实验实现
定义Example05类,其代码如下:

package Example05;

import java.util.*;
public class Example05 {
    public static void main(String[] args) {
        //定义一个List集合list,向集合中添加元素"abc1","abc2","abc3","abc4"
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        //调用List集合的iterator()方法获取迭代器对象
        Iterator it = list.iterator();
        //while循环遍历元素
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

运行结果如图7-6所示。

图7-6 运行结果
三、实验总结
1、需要注意的是,在通过next()方法获取元素时,必须保证要获取的元素存在,否则,会抛出NoSuchElementException异常。
2、Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,图7-7演示了Iterator对象迭代元素的过程。

图7-7 遍历元素过程图
实验7-6 foreach循环:简化遍历
一、实验描述
1、 考核知识点
名称:foreach循环
2、 练习目标
 掌握使用foreach循环遍历集合和数组
3、 需求分析
虽然Iterator可以用来遍历集合中的元素,但写法上比较繁琐,为了简化书写,从JDK5.0开始,提供了foreach循环。foreach循环用于遍历数组或集合中的元素。为了让初学者能熟悉foreach循环的使用,本实验将演示如何用foreach循环遍历数组和集合中的元素。
4、 设计思路(实现原理)
1) 编写一个类Example06,
2) 在该类中定义一个List集合,向集合中添加四个元素
3) 用foreach循环遍历集合中的元素
4) 在类中定义一个数组arr,静态初始化数组int[] arr = {3,2,6};
5) 用foreach循环遍历arr中的元素
二、实验实现

package Example06;

import java.util.*;
public class Example06 {
    public static void main(String[] args) {
        // 创建list集合
        List list = new ArrayList();
        list.add("sv");
        list.add("lv");
        list.add("mv");
        list.add("tv");
        System.out.println("遍历集合中的元素:");
        //foreach循环遍历集合中的元素
        for(Object obj : list){
            System.out.println(obj);
        }
        // 定义数组
        int[] arr = { 3, 2, 6 };
        //foreach循环遍历数组中的元素
        System.out.println("遍历数组中的元素");
        for(int i = 0; i < arr.length; i++){
            System.out.println(arr[i]);
        }
    }
}

运行结果如图7-8所示。

图7-8 运行结果
三、实验总结
1、通过实验可以看出,foreach循环在遍历集合时语法非常简洁,没有循环条件,也没有迭代语句,所有这些工作都交给虚拟机去执行了。foreach循环的次数是由容器中元素的个数决定的,每次循环时,foreach中都通过变量将当前循环的元素记住,从而将集合中的元素分别打印出来。
2、使用foreach循环遍历集合和数组时,只能访问集合中的元素,不能对其中的元素进行修改。
实验7-7 ListIterator迭代器的特有方法
一、实验描述
1、 考核知识点
名称:ListIterator接口
2、 练习目标
 掌握ListIterator接口中特有方法的使用
3、 需求分析
ListIterator迭代器是Iterator的子类,该类在父类的基础上增加了一些特有方法。为了让初学者能熟悉ListIterator接口中特有方法的使用,本实验将演示如何用ListIterator接口中的方法向集合中插入元素和逆向遍历集合。
4、 设计思路(实现原理)
1) 编写一个类Example07
2) 在该类中定义一个List集合,向集合中添加四个元素
3) 用ListIterator接口的add()方法向集合中插入一个元素并遍历集合list
4) 用ListIterator接口的boolean hasPrevious()方法逆向遍历集合
二、实验实现

package Example07;

import java.util.*;
public class Example07{
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        //定义ListIterator迭代器对象,while循环遍历输出每个元素
        // 遍历到abc4元素时,向集合中添加一个元素"abc5"
        System.out.println("while循环遍历输出每个元素");
        ListIterator lit1 = list.listIterator();
        while(lit1.hasNext()){
            Object obj = lit1.next();
            System.out.println(obj);
            if(obj.equals("abc4")){
                list.add("abc5");
                break;
            }
        }
        // hasPrevious()方法逆向遍历集合
        System.out.println("逆向遍历集合: ");
        ListIterator lit2 = list.listIterator(list.size());
        while(lit2.hasPrevious()){
            Object obj = lit2.previous();
            System.out.println(obj);
        }
    }
}

运行结果如图7-9所示。

图7-9 运行结果
三、实验总结
1、ListIterator迭代器的特有方法,如表7-3所示。
表7-3 ListIterator迭代器的特有方法
方法声明 功能描述
void add(Object o) 将指定的元素插入列表(可选操作)
boolean hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true
Object previous() 返回列表中的前一个元素
void remove() 从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)
2、在本实验中,使用hasPrevious()方法判断是否存在上一个元素,如果存在,则通过previous()方法将元素取出,否则,则表示到达了集合的末尾,没有要遍历的元素。
3、在遍历过程中,如果想增加元素同样不能调用集合对象的add()方法,此时需要使用ListIterator提供的add()方法,否则会出现并发修改异常ConcurrentModificationException。需要注意的是,ListIterator迭代器只能用于List集合。
实验7-8 用Enumeration迭代Vector集合
一、实验描述
1、 考核知识点
名称:Enumeration接口
2、 练习目标
 掌握如何使用Enumeration迭代器的特有方法遍历Vector集合中的元素
3、 需求分析
在JDK1.2以前还没有Iterator接口的时候,遍历集合需要使用Enumeration迭代器接口。由于很多程序中依然在使用Enumeration,因此了解该接口的用法是很有必要的。Vevtor集合是List接口的一个实现类。为了让初学者能熟悉Enumeration迭代器的用法,本实验将演示如何用Enumeration迭代器遍历Vector集合。
4、 设计思路(实现原理)
1) 编写一个类Example08,在该类中定义一个Vector集合v
2) 向集合v中添加四个元素
3) 用Enumeration迭代器遍历集合v,输出集合中的每一个元素
二、实验实现

package Example08;

import java.util.*;
public class Example08 {
    public static void main(String[] args) {
        Vector v = new Vector();      //创建Vector集合
        v.addElement("秦始皇");
        v.addElement("成吉思汗");
        v.addElement("朱元璋");
        v.addElement("李世民");
        //Enumeration迭代器遍历Vector集合
        Enumeration en = v.elements();
        while(en.hasMoreElements()){
            Object obj = en.nextElement();
            System.out.println(obj);
        }
    }
}

运行结果如图7-10所示。

图7-10 运行结果
三、实验总结
1、JDK中提供了一个Vevtor集合,该集合是List接口的一个实现类,用法与ArrayList完全相同,区别在于Vector集合是线程安全的,而ArrayList集合是线程不安全的。在Vector类中提供了一个elements()方法用于返回Enumeration对象,通过Enumeration对象就可以遍历该集合中的元素。
2、在本实验中,使用Enumeration迭代器时,使用一个while循环对集合中的元素进行迭代,其过程与Iterator迭代的过程类似,通过hasMoreElements()方法循环判断是否存在下一个元素,如果存在,则通过nextElement()方法逐一取出每个元素。
实验7-9 HashSet集合的存储
一、实验描述
1、 考核知识点
名称:HashSet集合
2、 练习目标
 了解HashSet集合的存储特点
 掌握HashSet集合的用法
3、 需求分析
HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的。为了让初学者熟悉HashSet集合的用法,本实验将针对HashSet集合中元素不可重复的特点,对HashSet集合的存储和遍历过程进行演示。
4、 设计思路(实现原理)
1) 编写一个类Example09,在该类中定义一个HashSet集合hs
2) 向集合hs中添加6个元素,其中有一些重复的元素
3) 用size()方法获取添加完元素后集合中元素的个数
4) 用Iterator迭代器遍历集合的每一个元素
5) 观察在输出结果中,是否存在重复的元素
二、实验实现

package Example09;

import java.util.*;
public class Example09 {
    public static void main(String[] args) {
        // 创建HashSet集合
        HashSet hs = new HashSet();
        //向HashSet集合中添加元素,其中包括重复元素
        hs.add("abc2");
        hs.add("abc2");
        hs.add("abc1");
        hs.add("abc4");
        hs.add("abc4");
        hs.add("abc3");
        // 输出集合中元素的个数
        System.out.println("集合中元素的个数: "+hs.size());
        // 输出集合中每一个元素
        System.out.println("遍历集合中的每一个元素: ");
        Iterator it = hs.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

运行结果如图7-11所示。

图7-11 运行结果
三、实验总结
1、HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的。当向HashSet集合中添加一个对象时,首先会调用该对象的hashCode()方法来确定元素的存储位置,然后再调用对象的equals()方法来确保该位置没有重复元素。
2、在本实验中,首先通过add()方法向HashSet集合依次添加了六个字符串,然后通过Iterator迭代器遍历所有的元素并输出打印。从打印结果可以看出取出元素的顺序与添加元素的顺序并不一致,并且重复存入的字符串对象"abc2"和"abc4"被去除了,只添加了一次。
实验7-10 将Object类存入HashSet
一、实验描述
1、 考核知识点
名称:HashSet集合
2、 练习目标
 掌握如何将对象存入HashSet集合并且去除重复对象
3、 需求分析
HashSet集合之所以能确保不出现重复的元素,是因为它在添加对象时,会先调用该对象的hashCode()方法来确定元素的存储位置,再调用对象的equals()方法来确保该位置没有重复元素。为了将Object类存入HashSet集合,本实验将针对如何重写Object类中的hashCode()和equals()方法去除重复的Object对象进行演示。
4、 设计思路(实现原理)
1) 设计一个Person类,在该类中定义两个变量name和age
2) 在Person类中重写hashCode()和equals()方法
3) 编写类Example10,在该类中定义一个HashSet集合
4) 将Person对象存入HashSet集合中,其中含有重复的Person对象
5) 遍历HashSet集合中的元素,观察结果是否含有重复的对象
二、实验实现
设计Person类,其代码如下:

class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 重写hashCode方法,返回name属性的哈希值
    public int hashCode() {
        return name.hashCode();
    }
    // 重写equals方法
    public boolean equals(Object obj) {
        if(this == obj) return false;
        else return false;
    }
    // 重写toString()方法
    public String toString() {
        return "Person  " + name + age;
    }
}

编写类Example10,其代码如下:

import java.util.*;
public class Example01 {
    public static void main(String[] args) {
        // 创建HashSet对象
        HashSet hs = new HashSet();
        // 将Person对象存入集合
        hs.add(new Person("lisa", 21));
        hs.add(new Person("lisi", 32));
        hs.add(new Person("lisi", 32));
        hs.add(new Person("leilei", 31));
        hs.add(new Person("lusi", 25));
        hs.add(new Person("lusi", 25));
        // 遍历集合中的元素
        Iterator it = hs.iterator();
        while (it.hasNext()) {
            Person p = (Person) it.next();
            System.out.println(p);
        }
    }
}

运行结果如图7-12所示。

图7-12 运行结果

三、实验总结
在本实验中,当HashSet集合的存入元素时,首先调用当前存入对象的hashCode()方法获得name属性的哈希值,然后根据对象的哈希值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入,如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次和该位置上的元素进行比较,如果返回的结果为false就将该元素存入集合,返回的结果为true则说明有重复元素,就将该元素舍弃。整个存储的流程如图7-13所示。

图7-13 HashSet对象存储过程
实验7-11 TreeSet集合的存储
一、实验描述
1、 考核知识点
名称:TreeSet集合
2、 练习目标
 了解TreeSet集合的存储特点
 掌握TreeSet集合的存储和迭代操作
3、 需求分析
TreeSet是Set接口的另一个实现类,它内部采用平衡二叉树来存储元素,这样的结构可以保证TreeSet集合中没有重复的元素,并且可以对元素进行排序。为了让初学者能熟悉TreeSet集合的使用,本实验通过向TreeSet集合添加元素并遍历集合元素来演示。
4、 设计思路(实现原理)
1) 编写一个类Example11,定义一个TreeSet集合
2) 向TreeSet集合中添加一系列元素,其中有重复元素
3) 遍历输出TreeSet集合中所有的元素
二、实验实现

package Example11;

import java.util.*;
public class Example11 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();    //创建TreeSet集合
        ts.add("abc3");             //向集合中添加一系列元素,其中包括重复元素
        ts.add("abc2");
        ts.add("abc4");
        ts.add("aabbcc");
        ts.add("aabbcc");
        ts.add("abc1");
        //使用Iterator迭代器遍历TreeSet集合元素
        Iterator it = ts.iterator();
        System.out.println("遍历TreeSet集合元素");
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

运行结果如图7-14所示。

图7-14 运行结果

三、实验总结
TreeSet内部采用平衡二叉树来存储元素,所谓二叉树就是说每个节点最多有两个子节点的有序树,每个节点及其子节点组成的树称为子树,通常左侧的子节点称为“左子树”,右侧的节点称为“右子树”,其中左子树上的元素应小于它的根结点,而右子树上的元素应大于它的根结点。二叉树中元素的存储结构如图7-15所示。

图7-15 二叉树的存储结构
实验7-12 自定义比较器
一、实验描述
1、 考核知识点
名称:Comparator比较器
2、 练习目标
 掌握如何通过自定义比较器的方式对TreeSet集合中的元素排序
3、 需求分析
如果定义的类没有实现Comparable接口或者对于实现了Comparable接口的类而不想按照定义的compareTo()方法进行排序,这时,可以通过自定义比较器的方式对TreeSet集合中的元素排序。为了让初学者能掌握自定义比较器的编写,本实验将通过自定义比较器对TreeSet集合中的元素排序。
4、 设计思路(实现原理)
1) 设计类Person,该类中有变量name和age,并实现它们的get()和set()方法。
2) 设计类MyComparator自定义比较器,该类实现了Comparator接口
3) 在类MyComparator中实现比较方法,以Person对象中age为主要比较条件,如果age相等再比较name
4) 编写类Example12,创建TreeSet集合,在创建TreeSet集合时传入自定义比较器MyComparator。并将Person对象存入集合中
5) 遍历集合中的元素,观察执行结果
二、实验实现
改写Person类,具体代码如下:

class Person {
    private String name;
    private int age;
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
    public String toString(){
        return "Person  "+ name + " " + 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;
    }
}

自定义比较器,具体代码如下:

class MyComparator implements Comparator {
    public int compare(Object o1, Object o2) {
        // 类型转换,比较的是Person对象
        Person p1 = (Person) o1;
        Person p2 = (Person) o2;
        // 以年龄为主要条件
        if(p1.getAge() < p2.getAge()){
            return -1;
        }
        else if(p1.getAge() > p2.getAge()){
            return 1;
        }
        else {
            return p1.getName().compareTo(p2.getName());
        }
    }
}

编写Example12类,具体代码如下:

import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
public class Example12 {
		public static void main(String[] args) {
			TreeSet ts = new TreeSet(new MyComparator());
			ts.add(new Person("lisa", 22));
			ts.add(new Person("lisi", 24));
			ts.add(new Person("lisi", 21));
			ts.add(new Person("wangwu", 20));
			ts.add(new Person("zhaoliu", 19));
			ts.add(new Person("zhaoliu", 26));
			Iterator it = ts.iterator();
			while (it.hasNext()) {
				System.out.println(it.next());
			}
		}
}

运行结果如图7-16所示。

图7-16 运行结果
三、实验总结
在本实验中,定义了一个MyComparator类实现了Comparator接口,在compare()方法中实现元素的比较,这就相当于定义了一个比较器。在创建TreeSet集合时,将MyComparator比较器对象传入,当向集合中添加元素时,比较器对象的compare()方法就会被自动调用,从而使存入TreeSet集合中的字符串按照长度进行排序。
实验7-13 操作HashMap集合的方法
一、实验描述
1、 考核知识点
名称:HashMap集合
2、 练习目标
 了解HashMap集合的存储特点
 掌握如何使用操作HashMap集合的方法
3、 需求分析
Map接口用于存储具有对应关系的数据。它的每个元素都包含一个键对象Key和值对象Value,键和值对象之间存在映射。HashMap集合是Map接口的一个实现类。为了让初学者能熟悉使用HashMap集合,本章将采用使用不同方法对HashMap集合进行操作,学习HashMap集合的使用方法。
4、 设计思路(实现原理)
1) 编写类Example13,创建一个HashMap集合,并向集合中添加元素
2) 使用一系列方法分别对定义的集合进行增加、移除、判断等操作
3) 运行程序,根据输出结果,分析这些方法对HashMap集合的操作
二、实验实现
编写Example13类,具体代码如下:

import java.util.*;
public class Example13 {
		public static void main(String[] args) {
			// 创建集合对象
			Map map = new HashMap();
			// 添加元素
			map.put("czbk001", "林青霞");
			map.put("czbk003", "林志玲");
			map.put("czbk002", "林志颖");
			// 添加元素,如果键存在,就替换,返回以前与key关联的值。
			System.out.println(map.put("czbk003", "林志炫"));
			// V remove(Object key):根据指定的键删除键值对。
			System.out.println("remove:" + map.remove("czbk003"));
			// 判断指定的键是否在集合中存在
			System.out.println("containsKey:" + map.containsKey("czbk002"));
			System.out.println("containsKey:" + map.containsKey("czbk007"));
			// 判断指定的值是否在集合中存在
			System.out.println("containsValue:" + map.containsValue("林志颖"));
			// 判断集合是否为空
			System.out.println("isEmpty:" + map.isEmpty());
			// 集合中元素的个数
			System.out.println("size:" + map.size());
			// 输出集合对象名称
			System.out.println("map:" + map);
		}
}

运行结果如图7-17所示。

图7-17 运行结果
三、实验总结
在本实验中,从运行结果可以看出:
1)集合中键为czbk003对应的值是"林志玲"。
2)由于集合中存在键czbk003,所以程序做map.put(“czbk003”, “林志炫”)操作时,值会替换为"林志炫"。所以删除键为czbk003的对象时,程序输出remove:“林志炫”。由此证实了Map中的键必须是唯一的,不能重复。如果存储了相同的键,后存储的值则会覆盖原有的值,简而言之就是,键相同,值覆盖。
3)"czbk002"在集合中存在,所以输出true。"czbk007"在集合中不存在,输出false.
4) 值"林志颖"在集合中存在,所以输出true。
5)因为集合不为空,所以map.isEmpty()返回false。
实验7-14 遍历Map中所有的键值
一、实验描述
1、 考核知识点
名称:HashMap集合
2、 练习目标
 掌握遍历Map中所有的键值两种方法
3、 需求分析
在程序开发中,经常需要取出Map中所有的键和值。为了让大家熟悉遍历Map中所有的键值,本实验将演示遍历Map中所有的键值对的两种遍历方式。
4、 设计思路(实现原理)
1) 编写类Example14,在该类中创建Map集合并向集合中添加元素
2) 使用第一种方式,遍历集合元素,先获取键的集合,再获取键所对应的值
3) 使用第二种方式,先获取集合中键值对映射关系,再从映射关系中获得键和值
二、实验实现

package Example14;

import java.util.*;
public class Example14 {
    public static void main(String[] args) {
        // 创建集合对象
        Map map = new HashMap();
        // 添加元素
        map.put("001", "李世民");
        map.put("002", "朱元璋");
        map.put("003", "武则天");
        System.out.println("方式一遍历:");
        // 遍历1:先获取键的集合,再获取键所对应的值
        Set keySet = map.keySet();
        Iterator it = keySet.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj +" " + map.get(obj));
        }
        System.out.println("方式二遍历:");
        // 遍历2:先获取集合中键值对映射关系,再从关系中获得键和值
        Set entrySet = map.entrySet();
        Iterator it1 = entrySet.iterator();
        while(it1.hasNext()){
            Map.Entry entry = (Map.Entry)(it1.next());
            Object key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + ":" + value);
        }
    }
}

运行结果如图7-18所示。

图7-18 运行结果

三、实验总结
1、在本实验中,第一种遍历Map的方式是首先调用Map对象的KeySet()方法,获得存储Map中所有键的Set集合,然后通过foreach循环遍历集合中的所有的键,最后通过调用get(key)方法,根据键获取对应的值。
2、本实验中的第二种遍历Map的方式,首先调用Map对象的entrySet()方法获得存储Map中所有映射的Set集合,这个集合中存放了Map.Entry类型的元素(Entry是Map接口内部类),每个Map.Entry对象代表Map中的一个键值对,然后迭代Set集合,获得每一个映射对象,并分别调用映射对象的getKey()和getValue()方法获取键和值。
3、在Map中,还提供了一个values()方法,通过这个方法可以直接获取Map中存储所有值的Collection集合。获取代码如下:
Collection values = map.values();
for (Object value : values ) {
System.out.println(value);
}
将此代码替换实验中的两种遍历方法的代码,运行结果如图7-19所示。

图7-19 运行结果

实验7-15 TreeMap集合的存取
一、实验描述
1、 考核知识点
名称:TreeMap集合
2、 练习目标
 了解TreeMap集合的存储特点
 掌握TreeMap集合存储和迭代方法
3、 需求分析
TreeMap集合用来存储键值映射关系,其中不允许出现重复的键。在TreeMap中是通过二叉树的原理来保证键的唯一性,因此TreeMap中所有的键是按照某种顺序排列的。为了熟悉TreeMap集合的使用,本实验将使用TreeMap集合获取一个字符串中每一个字母出现的次数,在实现这一功能的过程中掌握TreeMap集合存储和迭代方法。
4、 设计思路(实现原理)
1) 编写一个类Example15,要获取字符串"cbxzbvavdvgd"中,每一个字母出现次数,先将字符串转化成数组
2) 定义一个TreeMap集合,字符出现的次数作为值,每一个字符作为键
3) 遍历字符数组,获取到每一个字符
4) 拿到每一个字符,到TreeMap集合中找对应的值,判断返回值是否为NULL
5) 如果返回值是NULL,就将字符存储到TreeMap集合中,对应的键记为1
6) 如果返回值不为NULL,就将键值加1,并重新将值(字符)和键(出现的次数)存入集合
7) 把TreeMap的元素拼接成一个字符串,输出结果
二、实验实现

package Example15;

import java.util.*;

public class Example15{
    public static void main(String[] args) {
        String s = "cbxzbvavdvgd";
        // 把字符串变成字符数组。
        char[] chs = s.toCharArray();
        // 定义一个TreeMap集合
        TreeMap tm = new TreeMap();
        // 遍历字符数组,获取到每一个字符。
        // 拿到该字符,到TreeMap集合中找对应的值
        // 根据返回值是否为null。是:存储,把次数记录为1;否:把数据++,然后重写存储
        for(int i = 0; i < chs.length; i++){
            if(tm.get(chs[i]) == null){
//                tm.keySet(chs[i]) = 1;
                tm.put(chs[i], 1);
            } else {
                int last = (int) tm.get(chs[i]);
                tm.replace(chs[i], last + 1);
            }
        }
        // 把TreeMap的数据拼接成一个字符串。
        System.out.println("把TreeMap的数据拼接成一个字符串: ");
        StringBuilder sb = new StringBuilder();
        tm.forEach((key, value) -> {
            sb.append(key + ": " + value + "\n");
        });

        System.out.println(sb.toString());
    }
}

运行结果如图7-20所示。

图7-20 运行结果
三、实验总结
1、在本实验中,演示了TreeMap集合中元素的存储和迭代方法与HashMap相同。从输出结果可以看出,TreeMap集合中的元素是不重复的,并且按照值的自然顺序进行了排序。这是因为在TreeMap中是通过二叉树的原理来保证键的唯一性,这个TreeSet集合存储的原理一样,因此TreeMap中所有的键是按照某种顺序排列的。
2、本实验中,在定义TreeMap集合时使用了泛型,即<参数化类型>。它可以指定该类中方法操作的数据类型,避免在集合存取时会产生的数据类型转化的错误。
实验7-16 Properties集合的功能
一、实验描述
1、 考核知识点
名称:Proeprties集合
2、 练习目标
 掌握Proeprties集合的存储和遍历方法
3、 需求分析
Map接口中还有一个实现类Hashtable,它和HashMap的区别是Hashtable是线程安全的。Hashtable类有一个子类Properties在实际应用中非常重要,Properties主要用来存储字符串类型的键和值,为了掌握Properties集合的使用,本实验将演示Properties集合中元素的存储,修改和遍历。
4、 设计思路(实现原理)
1) 编写一个类Example16,创建Proeprties集合对象
2) 向Proeprties集合中添加元素
3) 遍历Proeprties集合中的元素
二、实验实现

import java.util.*;
public class Example16{
	    public static void main(String[] args) {
		     // 创建集合对象
		     Properties prop = new Properties();
          //添加元素
prop.setProperty("刘备", "双股剑");
		     prop.setProperty("关羽", "青龙偃月刀");
		     prop.setProperty("张飞", "丈八蛇矛");
			// 遍历Proeprties集合中的元素



     }
}

运行结果如图7-21所示。

图7-21 运行结果
三、实验总结
Properties类中,针对字符串的存取提供了两个专用的方法setProperty()和getProperty()。setProperty()方法用于将配置项的键和值添加到Properties集合当中。propertyNames()方法得到一个包含所有键的set对象,然后在遍历所有的键时,通过调用getProperty()方法获得键所对应的值。
实验7-17 泛型的使用
一、实验描述
1、 考核知识点
名称:泛型的使用
2、 练习目标
 了解为什么要使用泛型
 掌握泛型的使用方法
3、 需求分析
集合可以存储任何类型的对象,但是在程序中无法确定一个集合中的元素到底是什么类型的。那么在取出元素时,如果进行强制类型转换就很容易出错。为了解决这个问题,在Java中引入了“参数化类型(parameterized type)”这个概念,即泛型。本实验将使用泛型来限定集合元素的数据类型,从而方便初学者学习泛型的使用方法。
4、 设计思路(实现原理)
1) 编写一个类Example17,创建ArrayList集合对象,并指定集合只能存储String类型的元素
2) 向集合中添加元素,其中有一个Integer类型的元素
3) 遍历集合中的元素,观察结果是否报错
二、实验实现

import java.util.*;
public class Example17 {
		public static void main(String[] args) {
			// 用ArrayList存储字符串并遍历
			ArrayList<String> array = new ArrayList<String>();
			array.add("hello");
			array.add("world");
			array.add("java");
			array.add(new Integer(10));//添加一个Integer类型的数据,此处报编译异常
			Iterator<String> it = array.iterator();
			while (it.hasNext()) {
				String s = (String) it.next();
				System.out.println(s);
			}
		}
}

编译程序发现报错,如图7-22所示。

图7-22 编译报错
错误显示array中不能再存入除String类型之外的数据类型,将Integer类型数据删掉,重新编译运行程序,结果如图7-23所示。

图7-23 运行结果

三、实验总结
1、在定义集合类时,可以使用“<参数化类型>”的方式指定该类中方法操作的数据类型,具体格式如下:
ArrayList<参数化类型> list = new ArrayList<参数化类型>();
2、在本实验中,使用泛型规定了ArrayList集合只能存入String类型元素。需要注意的是,在使用泛型后每次遍历集合元素时,可以指定元素类型为String,而不是Object,这样就避免了在程序中进行强制类型转换。
3、在程序中也可以自定义泛型,自定义泛型的具体代码如下:

class cachePool<T> {             // 在创建类时,声明参数类型为T
	             T temp;
	      public void save(T temp) { // 在创建save()方法时,指定参数类型为T
		        this.temp = temp;
	      }
      public T get() {             // 在创建get()方法时,指定返回值类型为T 
		         return temp;
	      }
}

在定义CachePool类时,声明了参数类型为T,例如:在实例化对象时通过将参数T指定为Integer类型,同时在调用save()方法时传入的数据也是Integer类型,那么调用get()方法取出的数据自然就是Integer类型,这样做的好处是不需要进行类型转换。
实验7-18 Collections类对集合的操作
一、实验描述
1、 考核知识点
名称:Collections工具类
2、 练习目标
 掌握如何使用Collections类对集合进行操作
3、 需求分析
在程序中,针对集合的操作非常频繁,针对这些常见操作,JDK提供了一个工具类专门用来操作集合,这个类就是Collections。为了初学者能够熟悉Collections类中的方法,本实验将使用Collections类中的各种方法操作集合实现模拟斗地主发牌,来学习Collections类对集合操作的方法。
4、 设计思路(实现原理)
1) 编写类Example18,创建两个String类型数组,其中一个用于存储牌的花色,一个用于存储牌的数字
2) 创建一个ArrayList集合作为牌盒,将大小王和不同花色不同数字的牌循环添加到集合中
3) 用Collections工具类的shuffle()方法洗牌
4) 创建三个ArrayList集合作为三个人的牌的集合,并循环发牌,要留三张底牌
5) 打印出三个人的牌和集合中留的三张底牌
二、实验实现

import java.util.*;
public class Example18 {
		public static void main(String[] args) {
			// 表示花色的数组
			String[] colors = { "黑桃", "红桃", "梅花", "方块" };
			// 表示点数的数组
			String[] numbers = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10",
					"J", "Q", "K" };
			// 找一个牌盒
			ArrayList<String> array = new ArrayList<String>();
			array.add("大王");
			array.add("小王");
			// 循环装牌
			for (String c : colors) {
				for (String n : numbers) {
					array.add(c.concat(n));
				}
			}
			// 洗牌
			Collections.shuffle(array);
			// 发牌
			ArrayList<String> linString = new ArrayList<String>();
			ArrayList<String> zhouString = new ArrayList<String>();
			ArrayList<String> meString = new ArrayList<String>();
			// 用普通for
			for (int x = 0; x < array.size() - 3; x++) {
				if (x % 3 == 0) {
					linString.add(array.get(x));
				} else if (x % 3 == 1) {
					zhouString.add(array.get(x));
				} else if (x % 3 == 2) {
					meString.add(array.get(x));
				}
			}
			// 看牌
			System.out.println("linString:" + linString);
			System.out.println("zhouString:" + zhouString);
			System.out.println("meString:" + meString);
			// 看底牌
			System.out.print("三张底牌:");
			for (int x = array.size() - 3; x < array.size(); x++) {
				System.out.print(array.get(x) + "  ");
			}
		}
}

运行结果如图7-24所示。

图7-24 运行结果
三、实验总结
1、本实验中使用到了Collections工具类的shuffle()方法对List集合中的元素进行随机排序(模拟玩扑克中的“洗牌”)。
2、Collections工具类的其它方法,具体如表7-4所示。
表7-4 Collection类的相关方法
方法声明 功能描述
static boolean addAll(Collection<? super T> c, T… elements) 将所有指定元素添加到指定 collection 中
static void reverse(List list) 反转指定List集合中元素的顺序
static void shuffle(List list) 对List集合中的元素进行随机排序(模拟玩扑克中的“洗牌”)
static void sort(List list) 根据元素的自然顺序对List集合中的元素进行排序
static void swap(List list,int i,int j) 将指定List集合中i处元素和j处元素进行交换
static int binarySearch(List list,Object key) 使用二分法搜索指定对象在List集合中的索引,查找的List集合中的元素必须是有序的
static Object max(Collection col) 根据元素的自然顺序,返回给定集合中最大的元素
static Object min(Collection col) 根据元素的自然顺序,返回给定集合中最小的元素
static boolean replaceAll(List list,Object oldVal,Object newVal) 用一个新的newVal替换List集合中所有的旧值oldVal
实验7-19 Arrays类对数组的操作
一、实验描述
1、 考核知识点
名称:Arrays工具类
2、 练习目标
 掌握如何使用Arrays工具类对数组进行操作
3、 需求分析
Arrays是一个专门用于操作数组的工具类,其中提供了大量的静态方法。为了让初学者能熟悉Arrays类中方法的功能和使用,本实验将使用Arrays类中的各种方法对数据进行操作,来学习Arrays工具类对数组进行排序、转换等操作。
4、 设计思路(实现原理)
1) 编写一个类Example21,在该类中定义一个数组
2) 用Arrays类中的sort()方法对数组进行排序
3) 用toString()方法将数组转换成字符串,并输出
4) 用asList()方法将数组转换成集合
二、实验实现

import java.util.*;
public class Example19 {
		public static void main(String[] args) {
			Integer[] arr = { 3, 1, 6, 34, 78, 9 };
			// 对数组排序
			Arrays.sort(arr);
			// 将排序后的数组转换成字符串打印出来
			System.out.println("排序后的数组:"+Arrays.toString(arr));
			// 将数组转换成集合
			List<Integer> array = Arrays.asList(arr);
			System.out.println("数组转换成集合后:"+array);
		}
}

运行结果如图7-25所示。

图7-25 运行结果
三、实验总结
1、本实验中,使用Arrays的sort()方法时只需要将数组做为参数传递给sort()方法就可以,至于内部是怎么进行排序的我们无需关心。可见使用这个方法不仅可以大大减少代码的书写量,而且操作简单。使用Arrays工具类的方法toString(int[] arr)时。需要注意的是,该方法并不是对Object类toString()方法的重写,只是用于返回指定数组的字符串形式。
2、除了本实验中的三种方法,Arrays工具类中还有其他方法,如:
1)使用Arrays的binarySearch(Object[] a, Object key)方法查找元素
2)使用Arrays的copyOfRange(int[] original, int from, int to)方法拷贝元素
3)使用Arrays的fill(Object[] a, Object val)方法填充元素

  • 9
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet、TreeSet) 3)了解List接口及主要实现类(ArrayList、LinkedList、Vector) 4)了解Map接口及主要实现类(HashMap、TreeMap、HashTable) 二、实验内容及步骤 1、编写程序练习将以下5个Person类的对象放在一个HashSet中。 姓名:张三 身份证号:178880001 姓名:王五 身份证号:178880002 姓名:李四 身份证号:178880003 姓名:王五 身份证号:178880002 姓名:李四 身份证号:178880004 注意:因为Person类是自定义类,需要重写hashCode()方法和equals()方法,并规定只有姓名和身份证号都相等,则对象相等。 其中计算哈希码的算法:(31 + ((name == null) ? 0 : name.hashCode()))*31 + id (注:name:Person对象的姓名,id:Person对象的身份证号) 主方法中作如下测试: 1)创建一个可放置Person类对象的HashSet; 2)依次添加上述5个对象到HashSet中; 3)把集合中的元素打印出来(使用迭代器Iterator) 2、编写程序练习List集合的基本使用: 1) 创建一个只能容纳String对象名为names的ArrayList集合; 2)按顺序往集合中添加5个字符串对象:"张三"、"李四"、"王五"、"马六"、"赵七"; 3)对集合进行遍历,分别打印集合中的每个元素的位置与内容; 4)打印集合的大小,然后删除集合中的第3个元素,并显示删除元素的内容,然后再打印目前集合中第3个元素的内容,并再次打印集合的大小。 3、编写程序练习Map集合的基本使用: 1)创建一个只能容纳String对象的person的HashMap集合; 2)往集合中添加5个"键-值"对象: "id"-"1"; "name"-"张三"; "sex"-"男"; "age"-"25"; "hobby"-"爱学Java" 3)对集合进行遍历,分别打印集合中的每个元素的键与值; 4)打印集合的大小,然后删除集合中的键为age的元素,并显示删除元素的内容,并再次打印集合的大小。 四、思考题 1、集合中的List、Set、Map有哪些不同? 2、为什么使用集合框架,而尽可能少用数组作为存储结构? 3、如何使用TreeSet实现第一题?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值