java面向对象基础集合框架 Collection和Map

#1、集合可分为Collection和Map

    **Collection接口**
A、List接口:存储有序的,可以重复的元素
			ArrayList(主要的实现类,底层用数组实现没,线程不安全的)
			LinkedList(对于频繁的插入 、删除操作,链表实现的)
			Vector(古老的实现类、线程安全的)
B、Set接口:存储无序的不可重复的元素
		 	HashSet、LinkedHashSet、TreeSet

Map接口:存储“键-值”对的数据
HashMap、LinkedHaseMap、TreeMap、Hashtable(子类:Properties)
他们三个类大体方法和使用相同。ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector。对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高, 经常遍历时 ArrayList 效率较高。
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦.
LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引,但是缺点就是查找非常麻烦,要丛第一个索引开始。

#Collection接口

#Collection接口 – List接口

  1. 存储对象可以考虑 ①数组 ②集合

  2. 数组存储的特点:Student[] stu = new Student[20];
    -数组存储的弊端 ① 一旦创建,其长度不可变。②真实的数组存放的对象的个数是不可用

  3. Collection的方法
    ①int size()//获取长度
    ②boolean add(Object obj)//添加元素
    ③ addAll(Collection coll)//讲形参coll中包含的所有元素添加到当前集合中
    ④ 查看元素集合
    System.out.println(coll)//
    ⑤ isEmpty()//判断集合是否为空
    对象.isEmpty() //值是true false
    ⑥ clear()清空集合元素
    对象.clear();
    ⑦ contains(Object obj) 判断集合中是否包含指定的obj元素,如果包含 返回true,反之false。
    判断的依据,根据元素所在的类的equals()方法进行判断
    //明确:如果存入集合中的元素是自定义类的对象,要求:自定义类要重新equals()方法!
    对象.contains(“aa”);
    ⑧ containsAll(Contains coll) 判断当前集合中是否包含coll中所有的元素
    coll. containsAll(新集合);//返回 Boolean
    ⑨ retainAll(Contains coll)//求当前集合与coll的共有的元素,返回给当前集合 coll.retainAll(coll1);//返回两个集合中共有的元素,返回给 coll
    ⑩ remove(Object obj)//删除集合中的obj元素,若删除成功 返回 true 否则 返回false coll.remover(值)
    集合的遍历
    11)removeAll
    coll. removeAll(coll1);//删除两个集合共有的元素,返回coll剩余的元素
    12)equals//返回两个集合是否相等
    coll.equals(coll1);//返回Boolean
    13)hashCode() //求集合的hash值 set
    14)toArray();//将集合返回数组
    Objet[] obj = coll.toArray();

  1. iterator() 获取一个迭代器对象
    while(Iterator.hasNext){
    System.out.print(集合对象.next());
    }
    增强for循环
    for(Object x:coll){
    System.out.print(x);
    )
    #Collection举例

因为Collection接口无法被实例化;我们测试Collection 接口的所有例子使用ArrayList类帮忙实现
Collection a = new ArrayList();
// 打印长度
System.out.println(a.size());
// 添加元素
a.add(“张三”);

	// 添加一个集合的元素
	Collection<String> copyA = new ArrayList<String>();
	copyA.add("TONY");
	copyA.add("李四"); 
	a.addAll(copyA); // 将另一个集合元素添加到 a 集合中
		// 判断是否为空
	System.out.println("是否为空:" + a.isEmpty());
	// 清空集合元素
	// copyA.clear(); 为了测试 不真删..... 不然没得玩了...
	// 判断集合是否包含指定的obj元素
	System.out.println(a.contains("张三"));
	// 判断集合是否完全包含另一个集合
	System.out.println(a.containsAll(copyA));
	// 只留下和另一个集合重复的值
	System.out.println(a); 
	System.out.println(a.retainAll(copyA));
	System.out.println(a);
	// 删除匹配某一个数据
	System.out.println(a.remove("张三") ? "删除成功" : "没删除成功" );
	
	// 删除匹配一个集合的数据
	a.removeAll(copyA);
	// 返回成数组
	Object[] intArr = a.toArray();
	
	// 遍历
	System.out.println(copyA);
	copyA.add("王伟");
	copyA.add("钱学森");
	// 使用Iterator接口
	Iterator  i = copyA.iterator();
	while(i.hasNext()){ //是否有下一个
		System.out.print(i.next() + " (-) ");  // 进行查询
	}
	// 使用foreach遍历 
	System.out.println("\n符号纯粹只是为了区别...");
	for (Object object : copyA) {
		System.out.print(object + " (o) ");

}
}

##Collection接口 - list接口----------ArrayList类定义方法

ArrayList
add(int index,Object ele);在指定的索引位置 index添加元素ele 添加的索引位置不能超过现有集合长度
Object get(int index)//获取指定索引的元素值
Object remove(int index)//删除指定索引的元素 并返回该元素
Object set(int index,Object ele)//设置指定索引位置的元素为ele 返回该位置的原有元素
boolean addAll(int index,Collection eles) //将eles 集合中的所有元素添加到集合中
Int indexOf(Object obj)
Int lastindexOf(Objext obj)
List subList(int fromindex,int toindex)
List常用的方法:增 add(Object obj),删remove
改set(),查get,插 add 长度 size()
语法:List list = new ArrayList
1)添加值list.add(值);
list.add(0,43);//在第一个位置添加
2)获取位置元素的值
Object obj = list.get(下标);
3)删除指定位置的元素
list.remove(0);
4)修改指定位置的元素
list.set(0,432);
5) indexOf返回obj在集合中首次出现的位置,没有返回-1
6)lastindexOf返回obj在集合中最后出现的位置,没有返回-1
list.indexOf(值)//会调用equals方法
list.lastindexOf(值)
7) subList(int fromindex,int toindex)//返回从fromindex到toindex的lsit
list.subList(0,4)//包含左边 不包含右边的新集合

#=ArraysList方法综合举例==================

public static void main(String[] args) {
	   // 使用List接口 创建一个ArrayList 
	   List<String> student = new ArrayList<String>();
		student.add("小明");
		student.add("小红");
		student.add("小刚");
		System.out.println(student);
		
		student.add(2, "林丹"); //将林丹插入第二个位置之前
		System.out.println(student);
		
		student.remove(2);// 删除下标为2的
		System.out.println(student);
		
		student.set(0, "马龙"); //将下标为0的改为马龙
		System.out.println(student);
		
		//创建一个集合
		List<String> footballPlayer = new ArrayList<String>();
		footballPlayer.add("C罗");
		footballPlayer.add("梅西");
		footballPlayer.add("贝尔");

		student.addAll(footballPlayer); //添加一个集合(足球队)
		System.out.println(student);
		
		System.out.println("获取C罗下标: "+ student.indexOf("C罗"));
		System.out.println("获取C罗下标: "+ student.lastIndexOf("C罗"));
		System.out.println("求字串下标 1-2 " +student.subList(1, 3)); 
		
		System.out.println("获取梅西: " + student.get(4)); 
}

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

Collection接口 – List接口 -LinkedList

  1. void addFirst(Object obj)

  2. void addLast(Object obj)

  3. Object getFirst()

  4. Object getLast()

  5. Object removeFirst()

  6. Object removeLast()
    =LinkedList综合举例================
    public static void main(String[] args) {
    // 使用List接口 创建一个LinkedList
    LinkedList persons = new LinkedList();
    persons.add(“大明”);
    persons.add(“大红”);
    persons.add(“大刚”);
    System.out.println(persons);

     // 添加到集合首位
     persons.addFirst("葫芦娃大娃");
     // 添加到集合末尾
     persons.addLast("葫芦娃七娃");
     System.out.println(persons);
    
     System.out.println("抓第一个: " + persons.getFirst());
     System.out.println("抓最后一个: " + persons.getLast());
    
     System.out.println("带走第一个: " + persons.removeFirst());
     System.out.println("带最后一个: " + persons.removeLast());
     System.out.println(persons);
    

}

List常用子类还包括 Vector

他们三个类大体方法和使用相同。**ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector**。**对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高, 经常遍历时 ArrayList 效率较高。**
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦.
   LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引,但是缺点就是查找非常麻烦,要丛第一个索引开始。

泛型:
1.解决元素存储的安全性问题
2.解决获取数据元素时,需要类型强转的问题
语法:List list =new ArrayList;//E表示数据类型

Collection接口 – Set接口
Set接口是Collection的子接口,Set接口没有提供额外的方法
Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法

##Collection接口 – Set接口 - HashSet 类**

   HashSet类实现了Set接口,由哈希表支持.它不保证Set的迭代顺序,特别是它不保证该顺序恒久不变.

HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
HashSet 具有以下特点:
不能保证元素的排列顺序
元素不能重复(equals方法判断重复)
HashSet 不是线程安全的
集合元素可以是 null
因为无法保证顺序HashSet无法获取到某一项的值 只能遍历

  1. add
  2. clear
  3. contains
  4. remove
  5. size

public static void main(String[] args) {
Set s = new HashSet();
s.add(“A”);
s.add(“B”);
s.add(“C”);
s.add(“D”);
s.add(“E”);
s.add(“E”);
System.out.println(s);

	s.remove("E");// 删除值为E的集合项
	System.out.println(s);

	System.out.println("是否包含C: " + s.contains("C"));
	System.out.println("SET长度 " + s.size());
 }

##LinkedHashSet 是Hashset的子类
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

PS:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

**Collection接口 – Set接口 -  TreeSet类**

TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
Comparator comparator()
Object first()
Object last()
Object lower(Object e)
Object higher(Object e)
SortedSet subSet(fromElement, toElement)
SortedSet headSet(toElement)
SortedSet tailSet(fromElement)

TreeSet s = new TreeSet();
s.add(“z”);
s.add(“a”);
s.add(“c”);
s.add(“g”);

	System.out.println(s);

	System.out.println("第一个元素: " + s.first());
	System.out.println("最后一个元素: " + s.last());

	System.out.println("低一点 " + s.lower("g"));
	System.out.println("高一点 " + s.higher("g"));

	SortedSet ss = s.subSet("a", "g");
	System.out.println("求子集 " + ss);
	
	System.out.println("求子集 " + s.headSet("g"));
	System.out.println("求子集 " + s.tailSet("g"));

大家都知道treeset是可以排序的, 字母和数字等内容还好, 排序跟着字典顺序走就是了, 那么问题来了, 如果存入的是一个学生对象… 那如何排序??
TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列. 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。

class Student implements Comparable {
public String name;
public int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
if (!(o instanceof Student)) {
return 0;
}
if (o == this) {
return 1;
}
Student s = (Student) o;
if (this.age < s.age) {
return 1;
}else{
return -1;
}
}
}

public class Test {
public static void main(String[] args) {
Student xiaohong = new Student(“小红”, 10);
Student xiaoming = new Student(“小明”, 12);
Student xiaogang = new Student(“小刚”, 13);
TreeSet s = new TreeSet();
s.add(xiaohong);
s.add(xiaoming);
s.add(xiaogang);
Iterator i = s.iterator();
while(i.hasNext()){
System.out.println(i.next().name);
}
}
}

通过Comparator接口的帮助。需要重写compare(T o1,T o2)方法。
利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return this.name;
}
}

class MyComparator implements Comparator {
@Override
public int compare(Student s1, Student s2) {
return s1.age - s2.age == 0 ? 0 : (s1.age - s2.age > 0) ? -1 : 1;
}
}
public class Test {
public static void main(String[] args) {
TreeSet tree = new TreeSet(new MyComparator());
tree.add(new Student(“小明”, 10));
tree.add(new Student(“小红”, 15));
tree.add(new Student(“小刚”, 9));
tree.add(new Student(“小光”, 93));
System.out.println(tree);
}
}

当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0

//手写 判断两个对象相等方法.

public boolean equals(Object o) {
	Student s = (Student) o;
	return (s.age == age && s.name.equals(name));
}

public int hashCode(){
	return age * name.hashCode();

}
// eclipse同时也提供快捷键 ALT + SHIFT + F + H 生成 equals和hashCode方法重写.

#Map接口

Map效果图
Map:保存多个映射关系的对象
Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(键值对)
Map 中的 key 和 value 都可以是任何引用类型的数据
Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。
常用String类作为Map的“键”。
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value。

常用方法
添加、删除操作:
Object put(Object key,Object value)
Object remove(Object key)
void putAll(Map t)
void clear()

元视图操作的方法:
Set keySet()
Collection values()
Set<Map.Entry<K, V>> entrySet();–返回键值对象的集合

元素查询的操作:
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
boolean equals(Object obj)

=Map 综合举例====================
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put(“s01”, “小王”);
map.put(“s02”, “小李”);// 没有小李
map.put(“s02”, “小虎”);
map.put(“s03”, “小杰”);
map.put(“s04”, “小王”);

	System.out.println("获取 s02 的值: " + map.get("s02"));
	map.put("s05", "小强"); //
	map.remove("s05"); // 删除

	Set<String> set = map.keySet(); // 将所有Map的key传递给Set
	Iterator<String> it = set.iterator();
	System.out.println("===Key集合的集合===");
	while (it.hasNext()) {
		System.out.println(it.next());
	}

	Collection<String> coll = map.values();
	it = coll.iterator();
	System.out.println("===Value集合===");
	while (it.hasNext()) {
		System.out.println(it.next());
	}
	System.out.println("是不是空的? " + map.isEmpty());
	System.out.println("清空集合");
	map.clear();
	System.out.println("是不是空的? " + map.isEmpty());

	System.out.println("有没有 s04 的key ? " + map.containsKey("s04"));
	System.out.println("有没有 小王 的key ? " + map.containsValue("小杰"));

}

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

##HashMap

*Map接口的常用实现类:HashMap、TreeMap和Hashtable、Properties。
*
HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

###LinkedHashMap
LinkedHashMap 是 HashMap 的子类
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

	Map<String, String> map = new LinkedHashMap<String, String>();
	map.put("s01", "小王");
	map.put("s02", "小李");// 没有小李

System.out.println(map);
HashTable
Hashtable与HashMap的用法基本一致,但是也存在一些区别:
1)HashMap可以允许存在一个为null的key和任意个为null的value,但是HashTable中的key和value都不允许为null。
2)Hashtable是线程安全的,而HashMap是线程不安全的。

Properties
Properties(Java.util.Properties),主要用于读取Java的配置文件,在Java中,其配置文件常为.properties文件,格式为文本文件,文件的内容的格式是“键=值”的格式,文本注释信息可以用"#"来注释。

它提供了几个主要的方法:
1. load ( InputStream inStream),从输入流中读取属性列表(键和元素对)。通过对指定的文件(比如说上面的 test.properties 文件)进行装载来获取该文件中的所有键 - 值对。以供 getProperty ( String key) 来搜索。

2. getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。

3. setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置 键 - 值对。

4. store ( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。

5. clear (),清除所有装载的 键 - 值对。该方法在基类中提供。

##TreeMap
TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
TreeMap 的 Key 的排序:
自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
若使用自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。
内部比较器:在需要比较排序的类中 实现comparable接口,并且实现compareTo方法
外部比较器:单独定义一个类,实现comparator接口,并实现compare方法,在创建TreeMap实例对象时,作为构造器参数传入,从而制定TreeMap的排序规则

		**//Tree 可以排序 但是不能以值排序 只能以key进行排序 这点比较特殊**

class Student {
public int age;

public String name;

public Student(int age, String name) {
	super();
	this.age = age;
	this.name = name;
}

@Override
public String toString() {
	return "Student [age=" + age + ", name=" + name + "]";
}

}

class StuAgeComparator implements Comparator {
public int compare(Student s1, Student s2) {
if (s1.age > s2.age) {
return -1;
} else {
if (s1.age == s2.age) {
return 0;
}
return 1;
}
}
}

public class Test {
public static void main(String[] args) {
Map<Student, String> map = new TreeMap<Student, String>(
new StuAgeComparator());
map.put(new Student(25, “宇智波鼬”), “s001”);
map.put(new Student(18, “佐助”), “s002”);
map.put(new Student(20, “李洛克”), “s003”);
map.put(new Student(19, “鸣人”), “s004”);
map.put(new Student(40, “四代火影”), “s005”);
map.put(new Student(65, “三代火影”), “s006”);

	System.out.println("遍历Map集合");
	Set<Student> set = map.keySet();
	Iterator<Student> it = set.iterator();
	while (it.hasNext()) {
		Student key = it.next();
		String value = map.get(key);
		System.out.println(key + " : " + value.toString());
	}
}

}

操作集合的工具类:Collections
Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

排序操作:(均为static方法)
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

查找、替换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

public static void main(String[] args) {
LinkedList persons = new LinkedList();
persons.add(“tony”);
persons.add(“andy”);
persons.add(“mark”);
persons.add(“mark”);
persons.add(“zero”);

	System.out.println("原本" + persons);
	Collections.reverse(persons);
	System.out.println("翻转后" + persons);
	Collections.shuffle(persons);
	System.out.println("随机后" + persons);
	Collections.sort(persons);
	System.out.println("升序" + persons);
	Collections.swap(persons, 0, 3);
	System.out.println("0 和 3交换后" + persons);

	System.out.println("求最大" + Collections.max(persons));
	System.out.println("求最小" + Collections.min(persons));
	System.out.println("求最小" + Collections.min(persons));

	System.out.println("计算mark出现次数"
			+ Collections.frequency(persons, "mark"));
	LinkedList<String> personsCopy = new LinkedList<String>();
	
	Collections.replaceAll(persons, "mark", "happy new year"); //替换所有mark
	System.out.println("当前" + persons);
}

##* 什么是hash表

HASH表主要就是提供更快的查找速度,由hash值和数值组成,简单来说就是分桶。

比如说你们学校的一个年级有很多班是吧?

那么现在要查找一位同学。如果不看班级直接找,就需要每个班级一个一个的查找是不?那现在因为分了班级,我们有一个函数可以通过名字产生它的班级号。比如说何磊,二班。
那么现在我们直接hash(何磊) = 2;
然后我们就直接从2班开始找。

如果2班有50个学生,那么我们最多查找50次对吗?

好。假设你们年级一共有100个班,如果没有这个hash函数,那么直接找,最坏可能要查找50*100=5000次。!!

这个班级其实就是每个桶!!
这就是分桶。。。通过哈希函数产生哈希值,然后相同哈希值的元素放在相同的桶里边。。。!

这样可以通过hash这个间接作用减少查找的时间和次数!!这就是它的意义!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值