Java集合框架超详细笔记

while(lit.hasNext()) {

String s = (String)(lit.next()) ;

System.out.println(s);

}

System.out.println(“--------------------”);

//逆向遍历

while(lit.hasPrevious()) {

String s = (String)(lit.previous()) ;

System.out.println(s);

}

}

4.3.1 使用迭代器遍历的问题

如果使用迭代器遍历元素,就不能使用集合添加元素;

java.util.ConcurrentModificationException:并发修改异常 ;

4.3.1.1 使用迭代器遍历,迭代器添加元素

public static void main(String[] args) {

//创建一个List集合对象

List list = new ArrayList();

//集合存储三个元素

list.add(“hello”) ;

list.add(“world”) ;

list.add(“java”) ;

//由于Collection的Iterator迭代器没有添加功能的,所以列表迭代器

ListIterator lit = list.listIterator() ;

while(lit.hasNext()) {

String s = (String)(lit.next()) ;

//判断

if(“world”.equals(s)) {

//迭代器添加元素

lit.add(“javaee”);

}

}

System.out.println(“list:”+list);

4.3.1.2 使用集合遍历,集合添加元素

public static void main(String[] args) {

//创建一个List集合对象

List list = new ArrayList();

//集合存储三个元素

list.add(“hello”) ;

list.add(“world”) ;

list.add(“java”) ;

//普通for循环:get(int index) 和 size()方法先结合

for(int i = 0 ;i < list.size() ; i ++) {

//获取元素

String s = (String)(list.get(i)) ;

//判断

if(“world”.equals(s)) {

//使用集合添加

list.add(“javaee”) ;

}

}

System.out.println(“list:”+list);

}

4.4 集合的四种遍历方式案例


public static void main(String[] args) {

//创建ArrayList集合对象

ArrayList array = new ArrayList() ;

//给集合中添加元素

array.add(“kaka”) ;

array.add(“hello”) ;

array.add(“world”) ;

array.add(“world”) ;

array.add(“java”) ;

array.add(“java”) ;

//1:Object[] toArray遍历

Object[] objs = array.toArray() ;

for(int x = 0 ; x < objs.length ; x ++) {

String s = (String)(objs[x]) ;

System.out.println(s+“—”+s.length());

}

System.out.println(“-----------------------”);

//2:Collection的迭代器

Iterator it = array.iterator() ;

while(it.hasNext()) {

String s = (String)(it.next()) ;

System.out.println(s+“—”+s.length());

}

System.out.println(“-----------------------”);

//3:使用List集合的列表迭代器

ListIterator lit = array.listIterator() ;

while(lit.hasNext()) {

String s = (String)(lit.next()) ;

System.out.println(s+“—”+s.length());

}

System.out.println(“-----------------------”);

//4:Object get(int index) 和int size()方法相集合

for (int i = 0; i < array.size(); i++) {

String s = (String)(array.get(i)) ;

System.out.println(s+“—”+s.length());

}

}

4.5 List集合的三个子实现类的特点


  • ArrayList:

底层数据结构:数组----->查询快,增删慢

从线程角度考虑:此实现不是同步的---->线程不安全---->执行效率高!

  • LinkedList:

底层数据结构:链接列表(链表)---->查询慢,增删快

从线程角度考虑:此实现不是同步的----->线程不安全---->执行效率高!

  • Vector:

底层数据库结构:可增长的数组实现---->查询快.增删慢

线程方面: 线程安全—>同步----->执行效率低!

除多线程环境外,在需求中没有指定具体的集合---->都使用ArrayList ()

4.6 ArrayList集合


见4.4,4.5;

4.6.1 存储自定义对象并遍历

需求:有5个学生,都有姓名和年龄,现需要将5个学生存储到集合中,并遍历5个学生信息

1)定义一个学生类

2)创建集合对象 ArrayList

3)创建5个学生

5)将5个学生添加到集合中

6)创建迭代器

7)利用迭代器遍历集合

//学生类

public class Student {

private String name;

private int age;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

}

public static void main(String[] args) {

//创建ArrayList集合对象

ArrayList array = new ArrayList();

//创建5个学生对象

Student s1 = new Student(“卡卡”,23);

Student s2 = new Student(“张三”,23);

Student s3 = new Student(“李四”,23);

Student s4 = new Student(“王五”,23);

Student s5 = new Student(“赵六”,23);

//集合中添加元素

array.add(s1);

array.add(s2);

array.add(s3);

array.add(s4);

array.add(s5);

//迭代器

Iterator it = array.iterator();

//遍历

while(it.hasNext()){

Student s = (Student)(it.next());

System.out.println(s.getName() + “—” + s.getAge());

}

}

4.6.2 案例:获取10个1-20之间的随机数,要求不能重复,使用ArrayList集合

public static void main(String[] args) {

ArrayLists();

}

private static void ArrayLists() {

ArrayList arr = new ArrayList<>();

Random r = new Random();

while(arr.size() != 10){

int number = r.nextInt(20)+1 ;

if(!arr.contains(number)){

arr.add(number) ;

}

}

System.out.println(“ArrayList版本:”);

//遍历

Iterator it = arr.iterator();

while(it.hasNext()){

Integer i = (Integer)(it.next());

System.out.print(i + “\t”);

}

}

4.7 Vector集合


见4.5

通过整数索引访问组件;

线程安全的类:StringBuffer 和 Vector

Vector类特有功能:

  • public void addElement(Object obj):给Vector集合中添加元素 ------->类似于add(Object obj)
  • public Object elementAt(int index):通过整数索引值获取指定元素内容---->类似于Object get(int index)
  • public Enumeration elements() :就是Vector集合的专有遍历方式:返回Enumeration接口(枚举元素)----->类似于:Iterator iterator()
Enumeration接口:
*   boolean hasMoreElements():判断枚举中是否存在元素
*   Object nextElement():获取下一个枚举元素

public static void main(String[] args) {

//创建Vector集合对象

Vector v = new Vector();

//给Vector集合中添加元素

v.add(“kaka”);

v.add(“hello”);

v.add(“world”);

v.add(“java”);

//通过整数索引值获取指定元素内容 + size()遍历Vector集合

for(int i = 0; i < v.size(); i++){

String s = (String)(v.elementAt(i));

System.out.println(s + “—” + s.length());

}

System.out.println(“------------”);

//特有遍历

Enumeration em = v.elements();

while(em.hasMoreElements()){

String s = (String)(em.nextElement());

System.out.println(s + “—” + s.length());

}

}

4.8 ListedList集合


见4.5

ListedList集合特有功能:

  • 添加
public void addFirst(Object e):将指定元素始终在链表开头添加
public void addLast(Object e):将指定的元素在链表的末尾添加
  • 获取
public Object getFirst() :获取链表的第一个元素
public Object getLast() :获取链表的最后一个元素
  • 删除
public Object removeFirst():删除链表第一个元素
public Object removeLast() :删除链表最后一个元素

public static void main(String[] args) {

//创建一个LinkeList集合对象

LinkedList link = new LinkedList() ;

link.add(“hello”) ;

link.add(“world”) ;

link.add(“java”) ;

//将指定元素始终在链表开头添加

link.addFirst(“javaee”);

link.addFirst(“android”);

//将指定的元素在链表的末尾添加

link.addLast(“go”);

link.addLast(“R”);

//获取链表的第一个元素,返回被获取的元素

System.out.println(“getFirst():”+link.getFirst());//android

//获取链表的最后一个元素

System.out.println(“getLast():”+link.getLast());//R

//删除链表第一个元素

System.out.println(“removeFirst():”+link.removeFirst());//android

//删除链表最后一个元素

System.out.println(“removeLast():”+link.removeLast());//R

System.out.println(“link:”+link);//[javaee, hello, world, java, go]

}

4.8.1 利用ListedList 集合模拟栈结构特点_01

栈的特点:先进后出;

利用ListedList 中的 public void addFirst(Object e)方法,将指定元素始终在链表开头添加,实现模拟栈的结构特点;

public static void main(String[] args) {

//创建一个LinkedList集合

LinkedList link = new LinkedList() ;

//addFirst()添加

link.addFirst(“kaka”);

link.addFirst(“hello”);

link.addFirst(“java”);

//遍历

//使用迭代器

Iterator it = link.iterator();

while(it.hasNext()) {

String s = (String)(it.next()) ;

System.out.println(s);

}

}

4.8.2 利用ListedList 集合模拟栈结构特点_02

利用ListedList 中的 public void addFirst(Object e)方法,将指定元素始终在链表开头添加,在利用public Object removeFirst()方法,删除链表第一个元素;一加一删来实现模拟栈结构特点;

import java.util.LinkedList;

/**

  • 自定义的栈集合类

  • @author 卡卡

*/

public class MyStack {

private LinkedList link;

//定义无参构造

public MyStack(){

link = new LinkedList();

}

/**

  • 添加

*/

public void add(Object obj){

link.addFirst(obj);

}

/**

  • 获取

*/

public Object get(){

return link.removeFirst();

}

/**

  • 判断

*/

public boolean isEmpy(){

return link.isEmpty();

}

}

/*

  • 测试类

*/

public class MyStackTest {

public static void main(String[] args) {

//创建MyStack对象

MyStack my = new MyStack();

//添加元素

my.add(“kaka”);

my.add(“hello”);

my.add(“world”);

while(!my.isEmpy()){

//获取元素

System.out.println(my.get());

}

}

}

4.9 List 案例_01


需求:在ArrayList存储了一些重复元素,去重ArrayList重复的元素!(字符串元素)

创建一个新集合的思想

  1. 创建一个ArrayList集合对象 array
  1. 给集合中添加很多重复元素
  1. 创建一个新的集合newArray
  1. 遍历以前的集合
  1. 判断新集合如果不包含这个元素,就将这个元素添加到新集合中
  1. 遍历新集合

public static void main(String[] args) {

//创建一个ArrayList集合

ArrayList arr = new ArrayList<>();

//给集合中添加重复元素

arr.add(“kaka”);

arr.add(“hello”);

arr.add(“world”);

arr.add(“java”);

arr.add(“kaka”);

arr.add(“hello”);

arr.add(“kaka”);

arr.add(“java”);

//创建一个新集合

ArrayList newArr = new ArrayList<>();

//遍历以前的元素

Iterator it = arr.iterator();

while(it.hasNext()){

//获取元素

String s = (String)(it.next());

//判断新集合如果不包含这个元素,添加到新集合中;

if(! newArr.contains(s)){

newArr.add(s);

}

}

//遍历新集合

Iterator itN = newArr.iterator();

while(itN.hasNext()){

String s = (String)(itN.next());

System.out.println(s);

}

}

4.10 List案例_02


需求:在ArrayList存储了一些重复元素,去重ArrayList重复的元素!(字符串元素)

不创建新集合,利用选择排序的思想

  • 使用0索引对应的元素和后面索引的元素进行比较,如果后面的元素和前面元素一致,就将后面重复元素从集合删除掉----->remove(int index)
  1. 创建ArrayList集合对象
  1. 添加重复元素
  1. 利用选择排序的思想,删除重复的元素
  1. 遍历集合

public static void main(String[] args) {

//创建一个ArrayList集合

ArrayList arr = new ArrayList<>();

//给集合中添加重复元素

arr.add(“kaka”);

arr.add(“hello”);

arr.add(“world”);

arr.add(“java”);

arr.add(“kaka”);

arr.add(“hello”);

arr.add(“kaka”);

arr.add(“java”);

//利用选择排序的思想,将后面重复元素从集合删除掉

for(int i = 0 ;i < arr.size()-1 ;i ++) {

for(int j = i+1 ; j < arr.size(); j++) {

//如果后面元素和前面的元素重复了,删除后面元素,里面索引–

//通过角标获取集合元素内容get(int index)

if(arr.get(i).equals(arr.get(j))) {

//删除

arr.remove(j) ;

j – ;

}

}

}

//遍历集合

Iterator it = arr.iterator() ;

while(it.hasNext()) {

String s = (String)(it.next()) ;

System.out.println(s);

}

}

4.11 List案例_03


需求:使用ArrayList集合存储自定义对象Student并去重

1)定义一个学生类

2)创建集合对象 ArrayList

3)创建5个学生

5)将5个学生添加到集合中

6)创建迭代器

7)利用迭代器遍历集合

重点:重写equals方法

//学生类

public class Student {

private String name ;

private int age ;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

@Override

public boolean equals(Object obj) { //Student s ;

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())//获取字节码文件对象: this.getClass

return false;

Student other = (Student) obj;

if (age != other.age) //比较当前学生类中成员信息

return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name)) //String name

return false;

return true;

}

}

public static void main(String[] args) {

//创建ArrayList集合对象

ArrayList arr = new ArrayList<>();

//创建学生对象

//创建对象

Student s1 = new Student(“卡卡”,23);

Student s2 = new Student(“张三”,23);

Student s3 = new Student(“李四”,23);

Student s4 = new Student(“卡卡”,23);

Student s5 = new Student(“王五”,23);

Student s6 = new Student(“赵六”,23);

//添加到集合中

arr.add(s1);

arr.add(s2);

arr.add(s3);

arr.add(s4);

arr.add(s5);

arr.add(s6);

//创建一个新集合

ArrayList newArr = new ArrayList<>();

//遍历以前的集合

Iterator it = arr.iterator();

while(it.hasNext()){

Student s = (Student)(it.next());

if(!newArr.contains(s)){

newArr.add(s);

}

}

//遍历新的集合

Iterator it2 = newArr.iterator();

for(int i = 0; i < newArr.size();i++){

Student s = (Student)(newArr.get(i));

System.out.println(s.getName() + “—” +s.getAge());

}

}

5. Set集合与实现类

================================================================================


5.1 Set 概述


Set接口就是一个不包含重复元素的collection;全部继承自Collection中的方法;

特点:

无序、无下标、元素不可以重复

Set集合和List集合的区别:

  • List集合:有序的集合,存储和取出是一致的,它允许元素重复
  • Set集合:无序的集合,存储和取出不一致(不能保证该顺序恒久不变),它元素唯一的

public static void main(String[] args) {

//创建一个Set集合对象

Set set = new HashSet();

//添加元素

set.add(“hello”);

set.add(“hello”);

set.add(“java”);

set.add(“java”);

set.add(“world”);

set.add(“world”);

//增强for遍历

for(String s :set){

System.out.println(s);//java world hello

}

}

  • 元素不能重复

5.2 Set集合中的子实现类


Set中的子实类包括HashSet、LinkedHashSet、TreeSet

5.2.1 HashSet类概述

HashSet集合的add方法跟HashMap集合的put有关系,将所有需要存入HashSet的值,直接保存在HashMap中,底层依赖于hashCode()、equals()方法。需要在自定义的类中重写hashCode()和equals方法();

需求:使用HashSet集合存储自定义对象Student,保证元素唯一

//学生类

public class Student {

private String name;

private int age;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + ((name == null) ? 0 : name.hashCode());

//result = 31 * 29 + name的哈希值

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Student other = (Student) obj;

if (age != other.age)

return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

return true;

}

@Override

public String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

}

public static void main(String[] args) {

//创建一个HashSet集合对象

Set set = new HashSet();

//创建学生对象

Student s1 = new Student(“卡卡”,23);

Student s2 = new Student(“张三”,26);

Student s3 = new Student(“卡卡”,24);

Student s4 = new Student(“张三”,26);

Student s5 = new Student(“卡卡”,34);

//添加集合中

set.add(s1);

set.add(s2);

set.add(s3);

set.add(s4);

set.add(s5);

//增强for遍历

for(Student s : set){

System.out.println(s.getName()+“—”+s.getAge());

}

}

以上代码输出:

卡卡—23

卡卡—24

卡卡—34

张三—26

5.2.2 LinkedHashSet类概述

元素有序唯一,底层数据结构是链接列表和哈希表

  • 链接列表: 来保证元素有序(存储和取出一致的)

  • 哈希表: 来保证元素唯一性

节点形式单独存储数据,并可以指向下一个节点,通过顺序访问节点,可保留元素插入顺序;

public static void main(String[] args) {

//创建LinkedHashSet集合对象

LinkedHashSet link = new LinkedHashSet();

//添加元素

link.add(“hello”);

link.add(“hello”);

link.add(“kaka”);

link.add(“kaka”);

link.add(“javaEE”);

link.add(“javaEE”);

link.add(“android”);

//遍历

for(String s : link){

System.out.println(s);

}

}

以上代码输出:

hello

kaka

javaEE

android

6 TreeSet 类概述(重)

===================================================================================


底层数据结构是红黑树一种自平衡的二叉树;

1). 实现了SortedSet接口,要求必须可以对元素排序,使用元素的自然顺序对元素进行排序。

2). 所有插入元素,必须实现Comparable接口,覆盖compareTo方法。

3). 根据compareTo方法返回0作为去重的依据

6.1 Red - Black - Tree 红黑树结构简述


红黑树一种自平衡的二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。

public static void main(String[] args) {

//创建TreeSet集合对象

TreeSet ts = new TreeSet();

//add()添加

ts.add(20) ;

ts.add(18) ;

ts.add(23) ;

ts.add(22) ;

ts.add(17) ;

ts.add(24) ;

ts.add(19) ;

ts.add(18) ;

ts.add(24) ;

//遍历集合

for(Integer i : ts) {

System.out.print(i+" ");//17 18 19 20 22 23 24

}

}

遍历原理:拿上面的数字20,18,23,22,17,24,19,18,24来说:

存储元素:

  1. 添加元素时,第一个元素20作为根节点---->root

  2. 后面添加的元素都需要和根节点进行比较

  3. 如果比根节点小,作为根节点的左孩子(根节点左边的子节点)

  4. 如果比根节点打,作为根节点的右孩子(根节点右边的子节点)

  5. 如果元素相等,不会进入到红黑树的结构中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfUZvbcY-1592762980994)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200621231132497.png)]

遍历元素:

使用中序遍历(左根右)

  1. 首先访问根节点的左孩子,如果这个左孩子仍然有左孩子继续访问,一直到没有左孩子的节点,输出该节点17;

  2. 依据中序遍历次序,输出17的父节点18,;

  3. 在输出18的右孩子19;

  4. 以节点18为大的左孩子输出完毕,在输出整个二叉树的根节点20;

  5. 依据中序遍历次序左根右,找到根节点20的右孩子23,因为23有左孩子所以输出23的左孩子22;

  6. 输出22的根节点23;

  7. 在输出23的右孩子24;

  8. 最终得到序列17,18,19,20,22,23,24

6.2 TreeSet 集合案例_按照学生的年龄从小到大排序


TreeSet集合存储自定义对象,并且主要条件按照学生年龄的长度(从小到大比较)

  • 主要条件:年龄从小到大排序
  • 次要条件:
长度如果一样,还需要比较姓名的内容
需要比较人的年龄是否一样

/*

  • 如果要使用自然排序,针对自定义,该自定义类必须实现Comparable接口

  • 重写 compareTo(T s)方法对元素进行比较

*/

public class Student implements Comparable{

private String name;

private int age;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

@Override

public int compareTo(Student s) {

// TODO Auto-generated method stub

int num = this.age - s.age;

int num2 = (num == 0?(this.name.compareTo(s.name)):num);

return num2;

}

}

public static void main(String[] args) {

TreeSet ts = new TreeSet();

Student s1 = new Student(“kaka”,23);

Student s2 = new Student(“kaka”,21);

Student s3 = new Student(“kaaka”,28);

Student s4 = new Student(“kkkkaka”,26);

Student s5 = new Student(“ka11ka”,24);

Student s6 = new Student(“kakaaa”,23);

Student s7 = new Student(“kaka”,23);

//添加元素

ts.add(s1);

ts.add(s2);

ts.add(s3);

ts.add(s4);

ts.add(s5);

ts.add(s6);

ts.add(s7);

//遍历

for(Student s : ts){

System.out.println(s.getName()+“—”+s.getAge());

}

}

以上代码输出:

kaka—21

kaka—23

kakaaa—23

ka11ka—24

kkkkaka—26

kaaka—28

6.3 TreeSet 集合案例_按照学生的


姓名长度从小到大排序


/*

  • 学生类

*/

public class Student implements Comparable {

private String name ;

private int age ;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

//重写Comparable接口的方法

@Override

public int compareTo(Student s) {

//主要条件按照学生姓名的长度(从小到大)

int num = this.name.length() - s.name.length() ;

//1)次要条件:姓名的长度一样,姓名的内容不一定一样

int num2 = num == 0 ? (this.name.compareTo(s.name)) : num;

//2)次要条件:姓名的长度一样,内容一样,年龄不一定一样

int num3 = num2 == 0 ? (this.age-s.age) : num2 ;

return num3 ;

}

}

public static void main(String[] args) {

//创建一个TreeSet集合 对象

TreeSet ts = new TreeSet() ; //实现自然排序

//创建学生对象

Student s1 = new Student(“kaka”,23);

Student s2 = new Student(“kaka”,21);

Student s3 = new Student(“kaaka”,28);

Student s4 = new Student(“kkkkaka”,26);

Student s5 = new Student(“ka11ka”,24);

Student s6 = new Student(“kakaaa”,23);

Student s7 = new Student(“kaka”,23);

ts.add(s1) ;

ts.add(s2) ;

ts.add(s3) ;

ts.add(s4) ;

ts.add(s5) ;

ts.add(s6) ;

ts.add(s7) ;

//增强for

for(Student s :ts) {

System.out.println(s.getName()+“—”+s.getAge());

}

}

以上代码输出:

kaka—21

kaka—23

kaaka—28

ka11ka—24

kakaaa—23

kkkkaka—26

6.4 TreeSet集合两种比较器排序


构造方法:

  • TreeSet():创建TreeSet集合对象使用自然排序
  • TreeSet(Comparator comparatpr):比较器排序
*   构造方法的形式参数是一个接口类型:
    1.  自定义类实现Comarator接口,重写compare(T o1 ,T o2)方法
    2.  接口的匿名内部类
        new 接口名(){
               重写接口中的方法;
        };

注:6.4.1和6.4.2学生类都是以下

/*

  • 学生类

*/

public class Student {

private String name;

private int age;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

}

6.4.1 自定义类实现Comparator接口

/*

  • Comparator接口

*/

public class MyComparator implements Comparator{

public MyComparator() {

}

@Override

public int compare(Student s1, Student s2) {

//s1----->this

//s2---->传进来被比较的对象

//主要条件:按照学生年龄从小到大

int num = s1.getAge() - s2.getAge() ;

//次要条件:如果年龄一样,比较姓名的内容是否一样

int num2 = num == 0 ? (s1.getName().compareTo(s2.getName())) : num ;

return num2;

}

}

public static void main(String[] args) {

//创建一个TreeSet集合对象

//TreeSet(Comparator comparatpr):比较器排序

TreeSet ts = new TreeSet(new MyComparator()) ;

//创建几个学生对象

Student s1 = new Student(“kaka”,23);

Student s2 = new Student(“kaka”,21);

Student s3 = new Student(“kaaka”,28);

Student s4 = new Student(“kkkkaka”,26);

Student s5 = new Student(“ka11ka”,24);

Student s6 = new Student(“kakaaa”,23);

Student s7 = new Student(“kaka”,23);

//添加元素

ts.add(s1) ;

ts.add(s2) ;

ts.add(s3) ;

ts.add(s4) ;

ts.add(s5) ;

ts.add(s6) ;

ts.add(s7) ;

//遍历

for(Student s: ts) {

System.out.println(s.getName()+“—”+s.getAge());

}

}

以上代码输出:

kaka—21

kaka—23

kakaaa—23

ka11ka—24

kkkkaka—26

kaaka—28

6.4.2 直接接口的匿名内部类

public static void main(String[] args) {

//直接接口的匿名内部类

TreeSet ts = new TreeSet(new Comparator() {

@Override

public int compare(Student s1, Student s2) {

//s1----->this

//s2---->传进来被比较的对象

//主要条件:按照学生年龄从小到大

int num = s1.getAge() - s2.getAge() ;

//次要条件:如果年龄一样,比较姓名的内容是否一样

int num2 = num == 0 ? (s1.getName().compareTo(s2.getName())) : num ;

return num2;

}

});

//创建几个学生对象

Student s1 = new Student(“kaka”,23);

Student s2 = new Student(“kaka”,21);

Student s3 = new Student(“kaaka”,28);

Student s4 = new Student(“kkkkaka”,26);

Student s5 = new Student(“ka11ka”,24);

Student s6 = new Student(“kakaaa”,23);

Student s7 = new Student(“kaka”,23);

//添加元素

ts.add(s1) ;

ts.add(s2) ;

ts.add(s3) ;

ts.add(s4) ;

ts.add(s5) ;

ts.add(s6) ;

ts.add(s7) ;

//遍历

for(Student s: ts) {

System.out.println(s.getName()+“—”+s.getAge());

}

}

}

以上代码输出:

kaka—21

kaka—23

kakaaa—23

ka11ka—24

kkkkaka—26

kaaka—28

7. Map接口与实现类

================================================================================


7.1 Map接口的概述


Map集合数据结构<K,V> 键值对存储一对数据;

Map接口的特点:

  • 用于存储任意类型的键值对(Key-value)

  • 键:无序、无下标、不允许重复(唯一)

  • 值:无序、无下标、允许重复

  • 针对键有效,跟值无关

Map接口和Collection接口的不同:

  • Map是双列的,存储一堆键值对元素,特点针对键有效,键是唯一的可理解为(夫妻对),数据结构值针对键有效跟值无关;
  • Collection是单列的 ,只能存储一种引用数据类型,子体系Set是唯一的,理解为光棍,数据结构是针对元素有效;

7.2 Map集合的基本功能


  • V put(K key,V value) :添加一个键值对元素(后面的值会将前面的值覆盖,存储到集合,返回第一次存储的键对应的值)
  • V remove(Object key) :删除键,返回键对应的值
  • void clear() :暴力删除(删除全部键值对元素)
  • boolean containsKey(Object key):判断是否包含指定的键
  • boolean containsValue(Object value):判断是否包含指定的值
  • boolean isEmpty() :判断Map集合是否为空
  • int size() :获取集合的元素数

public static void main(String[] args) {

//创建Map集合对象

Map<String,String> map = new HashMap<String,String>();

//添加一个键值对元素

//后面的值会将前面的值覆盖,存储到集合,返回第一次存储的键对应的值

//第一次添加返回null

System.out.println(map.put(“卡卡”, “涛涛”));//null

System.out.println(map.put(“卡卡”, “牛牛”));//涛涛

System.out.println(map);//{卡卡=牛牛}

//删除键,返回键对应的值

System.out.println(“remove():”+map.remove(“杨过”));

//暴力清除

map.clear();

//判断是否包含指定的键

System.out.println(“containsKey():”+map.containsKey(“卡卡”));//true

System.out.println(“containsKey():”+map.containsKey(“唐唐”));//false

//判断是否包含指定的值

System.out.println(“containsValue():”+map.containsValue(“牛牛”));//true

//判断Map集合是否为空

System.out.println(“isEmpty():”+map.isEmpty());//false

//获取集合的元素数

System.out.println(map.size());//1

System.out.println(map);//{卡卡=牛牛}

}

7.3 Map接口中的其他功能


  • V get(Object key):通过键获取值
  • Set < K> keySet() :获取所有的键的集合
  • Collection< V> values():获取所有的值的集合
  • Set<Map.Entry<K,V>> entrySet() :获取的是键值对对象(用于遍历详见7.4.2)

public static void main(String[] args) {

//创建Map集合

Map<String,String> map = new HashMap<String,String>() ;

//添加元素

map.put(“卡卡”, “小卡”) ;

map.put(“牛牛”, “小牛”) ;

map.put(“堂堂”, “小堂”) ;

map.put(“涛涛”, “小涛”) ;

// 获取所有的键的集合

Set set = map.keySet() ;

//增强for

for(String key : set) {

//通过键获取值

String value = map.get(key) ;

System.out.println(key+“=”+value);

}

System.out.println(“-----------------------”);

//获取所有的值的集合

Collection c = map.values() ;

for(String value : c) {

System.out.println(value);

}

}

上述代码输出:

卡卡=小卡

堂堂=小堂

涛涛=小涛

牛牛=小牛

小卡

小堂

小涛

小牛

7.4 Map集合的遍历


7.4.1 通过键找值

set< K > keySet() {}

  • 获取所有键的集合
  • 遍历键的集合,获取到每一个键
  • 根据键找值

public static void main(String[] args) {

Map<String,String> map = new HashMap<String,String>();

//添加元素

map.put(“卡卡”, “小卡”) ;

map.put(“牛牛”, “小牛”) ;

map.put(“堂堂”, “小堂”) ;

map.put(“涛涛”, “小涛”) ;

//获取所有的键的集合

Set set = map.keySet() ;

for(String key :set) {

//通过键获取值 V get(Object key)

String value = map.get(key) ;

System.out.println(key+“=”+value);

}

}

7.4.2 根据键值对对象找键和值

public Set<Map.Entry<K,V>> entrySet()

  • Map.Entry<K,V>接口中

  • K getKey():获取键

  • V getValue():获取值

  • 获取所有键值对对象的集合
  • 遍历键值对对象的集合,获取到每一个键值对对象
  • 根据键值对对象找键和值

public static void main(String[] args) {

Map<String,String> map = new HashMap<String,String>() ; //HashMap:哈希表(元素唯一,无序!)

//添加元素

map.put(“卡卡”, “小卡”) ;

map.put(“牛牛”, “小牛”) ;

map.put(“堂堂”, “小堂”) ;

map.put(“涛涛”, “小涛”) ;

//通过map集合获取所有的键值对对象

Set<Map.Entry<String, String>> entrySet = map.entrySet() ;

for(Map.Entry<String, String> entry:entrySet ) {

//通过entry所有的键值对对象

String key = entry.getKey() ;

String value = entry.getValue() ;

System.out.println(key+“=”+value);

}

}

7.5 HashMap 集合类


键是哈希表结构,可以保证键的唯一性;可以用null作为key或者value;

HashMap<K,V>:可以存储任意的引用类型数据;

  • HashMap< String ,String>
  • HashMap < String ,Integer>
  • HashMap < String ,Student>

7.5.1 相同类型

public static void main(String[] args) {

//创建一个HashMap集合

HashMap<String, String> map = new HashMap<String,String>() ;

//添加元素

map.put(“卡卡”, “小卡”) ;

map.put(“牛牛”, “小牛”) ;

map.put(“堂堂”, “小堂”) ;

map.put(“涛涛”, “小涛”) ;

//直接遍历

Set set = map.keySet() ;

for(String key :set) {

String value = map.get(key) ;

System.out.println(key+“—”+value);

}

}

7.5.2 不同类型

public static void main(String[] args) {

//创建HashMap集合

HashMap<String, Student> hm = new HashMap<String,Student>() ;

hm.put(“1001”, new Student(“卡卡”,27)) ;

hm.put(“1002”, new Student(“牛牛”,25)) ;

hm.put(“1003”, new Student(“堂堂”,22)) ;

hm.put(“1004”, new Student(“涛涛”,20)) ;

hm.put(“1005”, new Student(“丫丫”,18)) ;

//遍历集合

Set set = hm.keySet() ;

for(String key :set ) {

//通过键获取值

Student s = hm.get(key) ;

System.out.println(key+“—”+s.getName()+“—”+s.getAge());

}

}

7.5.3 自定义类型

如果HashMap键的类型是自定义的,必须重写hashCode()和equals方法()保证元素唯一;

  • String:学号
  • Key:Student类型:学生信息

/*

  • 自定义学生类

*/

public class Student {

private String name ;

private int age ;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

this.name = name;

this.age = age;

}

@Override

public String toString() {

return “Student [name=” + name + “, 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 int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + ((name == null) ? 0 : name.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Student other = (Student) obj;

if (age != other.age)

return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

return true;

}

}

public static void main(String[] args) {

//创建一个HashMap集合

HashMap<Student, String> hm = new HashMap<Student,String>() ;

Student s1 = new Student(“卡卡”, 29) ;

Student s2 = new Student(“卡卡”, 25) ;

Student s3 = new Student(“卡卡”, 29) ;

Student s4 = new Student(“涛涛”, 30) ;

Student s5 = new Student(“涛涛”, 31) ;

Student s6 = new Student(“帆帆”, 22) ;

//添加元素

hm.put(s1, “1001”) ;

hm.put(s2, “1002”) ;

hm.put(s3, “1003”) ;

hm.put(s4, “1004”) ;

hm.put(s5, “1005”) ;

hm.put(s6, “1006”) ;

Set set = hm.keySet() ;

for(Student key :set) {

String value = hm.get(key) ;

System.out.println(key.getName()+“—”+key.getAge()+“—”+value);

}

}

7.6 Map案例


需求:键盘录入,获取字符串中每一个字母出现的次数

步骤:

  1. 创建键盘录入对象,录入字符串内容
  1. 创建Map集合,TreeMap<Character,Integer>
  1. 将字符串转换成字符数组
  1. 遍历字符数组,获取到每一个字符
  1. 利用Map集合对象通过键获取值 ,判断当前获取的值是否null
*   如果为null,第一次添加,给值默认值1,map集合对象将键和值添加到集合
*   如果不为null,说明键不是第一次添加,值自增,重写map集合键和值添加到集合中
  1. 创建字符串缓冲区对象StringBuilder
  1. 遍历TreeMap<Character,Integer>
  1. 使用字符串缓冲区对象将键和值拼接起来,转换成字符串

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

System.out.println(“输入内容:”);

String line = sc.next();

//创建Map集合

TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();

//字符串转化为数组

char[] chs = line.toCharArray();

//遍历数组

for(char ch :chs){

//通过键获取值

Integer i = tm.get(ch);

//判断是否为null

if(i == null){

tm.put(ch, 1);

}else{

i++;

tm.put(ch, i);

}

}

//创建字符串缓冲区对象

StringBuilder sb = new StringBuilder();

Set set = tm.keySet();//Map存到Set

for(Character key :set){

//获取值

Integer value = tm.get(key);

//拼接

sb.append(key).append(“(”).append(value).append(“)”);

}

String result = sb.toString();

System.out.println(result);

}

}

7.7 集合的嵌套遍历 _01


ArrayList集合嵌套HashMap集合 ArrayList<HashMap<String,String>>

public static void main(String[] args) {

//创建一个大集合

ArrayList<HashMap<String,String>> array = new ArrayList<HashMap<String,String>>();

//第一个子集合HashMap<String,String>

HashMap<String,String> hm1 = new HashMap<String,String>();

//添加元素

hm1.put(“卡卡”, “小卡”);

hm1.put(“牛牛”, “小牛”);

//将第一个集合添加到大集合中

array.add(hm1);

//第二个子集合

HashMap<String,String> hm2 = new HashMap<String,String>();

//添加元素

hm2.put(“欧欧”, “小欧”);

hm2.put(“QQ”, “小Q”);

array.add(hm2);

//第三个子集合

HashMap<String,String> hm3 = new HashMap<String,String>();

//添加元素

hm3.put(“发发”, “小发”);

hm3.put(“安安”, “小安”);

array.add(hm3);

for(HashMap<String,String> map : array){

//获取所有键的集合

Set set = map.keySet();

for(String key : set){

//键找值

String value = map.get(key);

System.out.println(“\t” + key +“—” +value);

}

}

}

7.8 集合的嵌套遍历 _02


HashMap集合嵌套ArrayList集合HashMap<String,ArrayList< String >>

  • 键:String
  • 值:HashMap<String,String>

public static void main(String[] args) {

//创建一个大集合

HashMap<String,ArrayList> hm = new HashMap<String,ArrayList>();

//Key:String类型

//value:ArrayList集合

ArrayList firstArray = new ArrayList();

firstArray.add(“刘备”);

firstArray.add(“曹操”);

//将子集合添加到大集合中

hm.put(“三国演义”, firstArray);

ArrayList secArray = new ArrayList();

secArray.add(“令狐冲”);

secArray.add(“林平之”);

//将子集合添加到大集合中

hm.put(“笑傲江湖”, secArray);

ArrayList thirArray = new ArrayList();

thirArray.add(“宋江”);

thirArray.add(“吴用”);

//将子集合添加到大集合中

hm.put(“水浒传”, thirArray);

//遍历

//获取所有集合

Set set = hm.keySet();

//遍历键

for(String key : set){

System.out.println(key);

//通过键获取值

ArrayList list = hm.get(key);

//遍历ArrayList

for(String value : list){

System.out.println(“\t” + value);

}

}

}

8. Collections工具类

=====================================================================================


集合工具类,针对集合操作的工具类,定义了除了存取以外的集合常用方法。

8.1 Collection 的成员方法


  • public static void sort(List list):针对集合进行默认的自然排序
  • public static < T > void sort(List< T > list, Comparator<? super T> c):针对List集合的比较器排序
  • public static int binarySearch(List<?> list,T key):集合中查询指定的元素出现的索引值(二分搜索法)
  • public static T max(Collection<?> coll):获取集合中的最大值
  • public static void reverse(List<?> list):直接集合的数据进行反转
  • public static void shuffle(List<?> list):针对集合中元素随机置换

注:折半查找(二分搜索法)---->数组中的元素必须有序的 ,数组的元素是无序的,就不能够直接使用二分搜索法

public static void main(String[] args) {

//创建List集合对象

List list = new ArrayList();

//添加元素

list.add(50);

list.add(30);

list.add(79);

list.add(10);

list.add(49);

System.out.println(list);//[50, 30, 79, 10, 49]

//针对集合进行默认的自然排序

Collections.sort(list);

System.out.println(list);//[10, 30, 49, 50, 79]

//集合中查询指定的元素出现的索引值(二分搜索法)

System.out.println(“index:” + Collections.binarySearch(list, 30));//index:1

//获取集合中的最大值

System.out.println(“max:” + Collections.max(list));//max:79

//集合的数据进行反转

Collections.reverse(list);

System.out.println(list);//[79, 50, 49, 30, 10]

//针对集合中元素随机置换

Collections.shuffle(list);

System.out.println(list);//[30, 50, 79, 10, 49]每次不定是随机生成的

}

8.2 针对List集合的比较器排序


public static < T > void sort(List< T > list, Comparator<? super T> c):针对List集合的比较器排序

需求:List集合中存储的是Student类型,按照学生的年龄从小到大排序,,排序的过程还能够保证集合元素唯一

/*

  • 学生类

*/

public class Student {

private String name;

private int age;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

}

public static void main(String[] args) {

//创建一个List集合

List list = new ArrayList();

//创建学生对象

Student s1 = new Student(“kaka”, 25) ;

Student s2 = new Student(“kaka”, 25) ;

Student s3 = new Student(“zhangsan”, 20) ;

Student s4 = new Student(“lisi”, 20) ;

Student s5 = new Student(“wangwu”, 22) ;

Student s6 = new Student(“zhaoliu”, 30) ;

//添加到list集合中

list.add(s1);

list.add(s2);

list.add(s3);

list.add(s4);

list.add(s5);

list.add(s6);

//对当前学生排序,针对List集合的比较器排序

//list集合是可以重复的

Collections.sort(list, new Comparator() {

@Override

public int compare(Student s1, Student s2) {

//年龄从小到大排:主要条件

int num = s1.getAge() - s2.getAge() ;

//年龄如果一样,不一定是同一个人,比较姓名的内容是否相同

int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) :num ;

return num2 ;

}

});

//遍历集合

for(Student s :list){

System.out.println(s.getName() + “—”+ s.getAge());

}

}

9. 模拟斗地主的洗牌和发牌_ 无序

=======================================================================================


最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • public static void sort(List list):针对集合进行默认的自然排序
  • public static < T > void sort(List< T > list, Comparator<? super T> c):针对List集合的比较器排序
  • public static int binarySearch(List<?> list,T key):集合中查询指定的元素出现的索引值(二分搜索法)
  • public static T max(Collection<?> coll):获取集合中的最大值
  • public static void reverse(List<?> list):直接集合的数据进行反转
  • public static void shuffle(List<?> list):针对集合中元素随机置换

注:折半查找(二分搜索法)---->数组中的元素必须有序的 ,数组的元素是无序的,就不能够直接使用二分搜索法

public static void main(String[] args) {

//创建List集合对象

List list = new ArrayList();

//添加元素

list.add(50);

list.add(30);

list.add(79);

list.add(10);

list.add(49);

System.out.println(list);//[50, 30, 79, 10, 49]

//针对集合进行默认的自然排序

Collections.sort(list);

System.out.println(list);//[10, 30, 49, 50, 79]

//集合中查询指定的元素出现的索引值(二分搜索法)

System.out.println(“index:” + Collections.binarySearch(list, 30));//index:1

//获取集合中的最大值

System.out.println(“max:” + Collections.max(list));//max:79

//集合的数据进行反转

Collections.reverse(list);

System.out.println(list);//[79, 50, 49, 30, 10]

//针对集合中元素随机置换

Collections.shuffle(list);

System.out.println(list);//[30, 50, 79, 10, 49]每次不定是随机生成的

}

8.2 针对List集合的比较器排序


public static < T > void sort(List< T > list, Comparator<? super T> c):针对List集合的比较器排序

需求:List集合中存储的是Student类型,按照学生的年龄从小到大排序,,排序的过程还能够保证集合元素唯一

/*

  • 学生类

*/

public class Student {

private String name;

private int age;

public Student() {

super();

// TODO Auto-generated constructor stub

}

public Student(String name, int age) {

super();

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 String toString() {

return “Student [name=” + name + “, age=” + age + “]”;

}

}

public static void main(String[] args) {

//创建一个List集合

List list = new ArrayList();

//创建学生对象

Student s1 = new Student(“kaka”, 25) ;

Student s2 = new Student(“kaka”, 25) ;

Student s3 = new Student(“zhangsan”, 20) ;

Student s4 = new Student(“lisi”, 20) ;

Student s5 = new Student(“wangwu”, 22) ;

Student s6 = new Student(“zhaoliu”, 30) ;

//添加到list集合中

list.add(s1);

list.add(s2);

list.add(s3);

list.add(s4);

list.add(s5);

list.add(s6);

//对当前学生排序,针对List集合的比较器排序

//list集合是可以重复的

Collections.sort(list, new Comparator() {

@Override

public int compare(Student s1, Student s2) {

//年龄从小到大排:主要条件

int num = s1.getAge() - s2.getAge() ;

//年龄如果一样,不一定是同一个人,比较姓名的内容是否相同

int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) :num ;

return num2 ;

}

});

//遍历集合

for(Student s :list){

System.out.println(s.getName() + “—”+ s.getAge());

}

}

9. 模拟斗地主的洗牌和发牌_ 无序

=======================================================================================


最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-qvIiHh8P-1714853546407)]

[外链图片转存中…(img-JfSJ41Pc-1714853546407)]

[外链图片转存中…(img-ogev22X6-1714853546407)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值