Java-集合框架(下)

Map集合

该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1.添加
put(K  key,V  value)
putAll( Map<? extends K,? extends V>  m )
2.删除
clear()
remove( Object  key )
3.判断
containsValue( Object  value )
containsKey( Object  key )
4.获取
get( Object  key )
size( )
value( )

entrySet( )
keySet( )

Map
|——HashTable:底层是哈希表数据结构,不可以存入null键和null值,该集合是线程同步的,效率低
|——HashMap:底层是哈希表数据结构,允许使用null键和null值,该集合是线程不同步的,将HashTable替代,效率高
|——TreeMap:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序

和Set很像,其实,Set底层就是使用了Map集合。
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

class MapDemo 
{
	public static void main(String[] args) 
	{
		Map<String,String> map = new HashMap<String,String>();

		//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键的对应值。
		//put方法会返回被覆盖的值。
		sop("put:"+map.put("01","zhangsan1"));
		sop("put:"+map.put("01","lisi1"));
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");

		sop("containsKey:"+map.containsKey("022"));
		sop("remove:"+map.remove("022"));
		
		//可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断。
		sop("get:"+map.get("02"));
		
		map.put("04",null);
		sop("get:"+map.get("04"));

		sop(map);

		//获取Map集合中所有的值
		Collection<String> coll = map.values();

		sop(coll);
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

Map集合的两种取出方式:
1.Set<k> keySet ,将Map中的所有键存入到Set集合,因为Set具备迭代器。
所以可以用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。
Map集合取出原理,将Map集合转成Set集合,再通过迭代器取出。

2.Set<Map.Entry<k,v>>  entrySet:将Map集合中的映射关系存入到Set集合中,
而这个关系的数据类型就是:Map.Entry。
Entry其实就是Map中的一个static内部接口,为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值对的映射关系。
关系属于Map集合中的一个内部事务,而且该事物在直接访问Map集合中的元素。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo2 {

	public static void main(String[] args) {
		Map<String,String> map = new HashMap<String,String>();
		
		map.put("02", "zhangsan");
		map.put("01", "zhaoliu");
		map.put("04", "lisi");
		map.put("03", "wangwu");
		
		//Map集合的第一种取出方式,keySet
		Set<String> keySet = map.keySet();
		
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()){
			String key = it.next();
			String value = map.get(key);
			
			System.out.println(key+"::"+value);
		}
		
		//Map集合的第二种取出方式,Map.Entry
		Set<Map.Entry<String,String>> entrySet = map.entrySet();
		
		Iterator<Map.Entry<String, String>> iter = entrySet.iterator();
		
		while(iter.hasNext()){
			Map.Entry<String, String> me = iter.next();
			
			String key = me.getKey();
			String value = me.getValue();
			System.out.println(key+"::"+value);
		}
	}
}

Map集合练习1:
每一个学生都有对应的归属地。
学生Student,地址String
学生属性:姓名,年龄
注意:姓名和年龄相同视为同一个学生。
保证学生的唯一性。

思路:
1.描述学生
2.定义map容器,将学生作为键,地址作为值,存入。
3.获取map集合中的元素。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo3 {

	public static void main(String[] args) {
		HashMap<Student,String> hm = new HashMap<Student,String>();
		
		hm.put(new Student("lisi1",21),"beijing");
		//hm.put(new Student("lisi1",21),"tianjin");
		hm.put(new Student("lisi2",22),"shanghai");
		hm.put(new Student("lisi3",23),"nanjing");
		hm.put(new Student("lisi4",24),"wuhan");
		
		//第一种方式 keySet
		Set<Student> keySet = hm.keySet();
		
		Iterator<Student> it = keySet.iterator();
		
		while(it.hasNext()){
			Student key = (Student)it.next();
			
			String value = hm.get(key);
			
			System.out.println(key.getName()+":::"+key.getAge()+":::"+value);
		}
		
		System.out.println("------------------------------------------");
		//第二种方式entrySet
		Set<Map.Entry<Student, String>> entrySet = hm.entrySet();
		
		Iterator<Map.Entry<Student, String>> iter = entrySet.iterator();
		
		while(iter.hasNext()){
			Map.Entry<Student, String> me = iter.next();
			
			Student key = me.getKey();
			String value = me.getValue();
			
			System.out.println(key.getName()+":::"+key.getAge()+":::"+value);
		}
	}
	
}

//描述学生类,复写hashCode、equals、compareTo
class Student implements Comparable<Student>{
	private String name;
	private int age;
	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	public int hashCode(){
		return this.name.hashCode()+this.age*37;
	}
	
	public boolean equals(Object obj){
		if(!(obj instanceof Student)){
			throw new RuntimeException("传入的对象有误!");
		}
		
		Student s = (Student)obj;
		return this.name.equals(s.name) && this.age==s.age;
	}
	
	public int compareTo(Student stu){
		int num = new Integer(this.age).compareTo(new Integer(stu.age));
		
		if(num==0){
			return this.name.compareTo(stu.name);
		}
		
		return num;
	}

	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;
	}
}

TreeMap练习2:
需求:
对学生对象的年龄进行升序排序。
对学生对象进行姓名排序。

思路:
因为数据是以键值对形式存在的,
所以要使用可以排序的Map集合。TreeMap

class MapTest2 
{
	public static void main(String[] args) 
	{
		TreeMap<Student,String> tm = new TreeMap<Student,String>(new stuNameComparator());

		tm.put(new Student("blisi3",23),"nanjing");
		tm.put(new Student("lisi1",21),"beijing");
		tm.put(new Student("alisi4",24),"wuhan");
		tm.put(new Student("lisi1",21),"tianjin");
		tm.put(new Student("lisi2",22),"shanghai");

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

		Iterator<Map.Entry<Student,String>> it = entrySet.iterator();

		while(it.hasNext()){
			Map.Entry<Student,String> me = it.next();

			Student s = me.getKey();
			String addr = me.getValue();

			System.out.println(s+".."+addr);
		}
	}
}

class stuNameComparator implements Comparator<Student>
{
	public int compare(Student s1,Student s2){
		int num = s1.getName().compareTo(s2.getName());

		if(num==0){
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}

		return num;
	}
}

TreeMap练习3:
"dhsafkjdhasfjk"获取该字符串中的字幕出现的次数
希望打印结果:a(1)b(2)c(4)...

通过结果发现:每一个字母都有对应的次数,
说明字母和次数之间都有映射关系。

注意了,当发现有映射关系时,可以考虑Map集合。
因为Map集合中存放的就是映射关系。

什么时候使用Map集合呢?
当数据之间存在者映射关系时,就要先想Map集合。

思路:
1.将字符串转成字符数组,因为要对每一个字母进行操作
2.定义一个Map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。
3.遍历字符数组。
将每一个字母作为键去查Map集合,
如果返回null,将该字母和1存入到Map集合中。
如果返回不是null,说明该字母在Map集合中已经存在并有对应次数。
那么就获取该次数并进行自增,然后将该字母和自增后的次数存进Map集合中,覆盖掉原有值。
4.将Map集合中的数据变成指定的字符串形式返回。

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class MapDemo4 {

	public static void main(String[] args) {
		String s = printChar("dacssdabac");
		System.out.println(s);
	}
	
	public static String printChar(String str){
		//转成字符数组
		char[] ch = str.toCharArray();
		
		//定义一个TreeMap集合,方便排序
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		
		//到Map集合中查找,如果ch[x]存在,那么存入ch[x]、1;如果不存在,那么存入ch[x]、value
		for(int x=0;x<ch.length;x++){
			Integer value = tm.get(ch[x]);
			
			if(value==null){
				tm.put(ch[x], 1);
			}else{
				value = value + 1;
				tm.put(ch[x], value);
			}
		}
		
		//取出Map中的元素,并按指定的格式存入到StringBuilder中
		StringBuilder sb = new StringBuilder();
		
		Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
		
		while(it.hasNext()){
			Map.Entry<Character, Integer> me = it.next();
			
			Character key = me.getKey();
			Integer value = me.getValue();
			
			sb.append(key+"("+value+")");
		}
		
		return sb.toString();
	}
}

集合框架工具类

Collections:集合框架的工具类,里面定义的都是静态方法。
Collections和Collection有什么区别?

Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口:
List:存放在List集合中的元素都有定义索引,有序,可以重复。
Set:元素不可以重复,无序。

Collections是集合框架的一个工具类,该类中的方法都是静态的,
提供的方法中有可以对List集合进行排序的,二分查找等方法。
通常常用的集合都是线程不安全的,因为要提高效率,
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
import java.util.*;

class CollectionsDemo 
{
	public static void main(String[] args) 
	{	
		binarySearchDemo();
		//maxDemo();
		//sortDemo();
	}

	//二分查找法
	public static void binarySearchDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		
		/*自然排序,并获取角标值
		Collections.sort(list);
		sop(list);
		int index = Collections.binarySearch(list,"aaa");
		sop(index);
		*/

		/*自然排序,演示二分查找原理
		Collections.sort(list);
		sop(list);
		int index = halfSearch(list,"aaaa");
		sop(index);
		*/

		//自定义比较器,演示二分查找原理
		Collections.sort(list,new StrLenComparator());
		sop(list);
		int index = halfSearch2(list,"kkkkk",new StrLenComparator());
		sop(index);

	}
	
	//二分查找原理方法
	public static int halfSearch(List<String> list,String key){
		int max,min,mid;
		min = 0;
		max = list.size()-1;

		while(min<=max){
			mid = (min+max)/2;

			String str = list.get(mid);
			int num = str.compareTo(key);

			if(num>0){
				max = mid - 1;
			}else if(num<0){
				min = mid + 1;
			}else{
				return mid;
			}
		}
		return -min-1;
	}
	
	//二分查找原理方法(加入比较器)
	public static int halfSearch2(List<String> list,String key,Comparator<String> comp){
		int max,min,mid;

		min = 0;
		max = list.size();

		while(min<=max){
			mid = (min+max)/2;
			String str = list.get(mid);

			int num = comp.compare(str,key);

			if(num>0){
				max = mid - 1;
			}else if(num<0){
				min = mid + 1;
			}else{
				return mid;
			}
		}
		return -min-1;
	}

	//获取集合的最大元素
	public static void maxDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		
		sop(list);

		//按照元素的自然顺序获取最大值。--zz
		//Collections.sort(list);
		//sop(list);
		//String max = Collections.max(list);

		//按照自定义比较器的比较顺序进行排序。--kkkkk
		Collections.sort(list,new StrLenComparator());
		sop(list);
		String max = Collections.max(list,new StrLenComparator());

		sop(max);
	}

	//排序方法
	public static void sortDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");

		sop(list);
		//按照元素的自然顺序排序。
		//Collections.sort(list);
		//sop(list);

		//按照自定义比较器进行排序。
		Collections.sort(list,new StrLenComparator());
		//Collections.swap(list,1,2);
		sop(list);
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

class StrLenComparator implements Comparator<String>
{
	public int compare(String s1,String s2){
		int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));

		if(num==0){
			return s1.compareTo(s2);
		}

		return num;
	}
}

Collections练习2:
import java.util.*;

class CollectionsDemo2 
{
	public static void main(String[] args) 
	{
		//shuffleDemo();
		//orderDemo();
		//replaceAllDemo();
		fillDemo();
	}

	//随机排列
	public static void shuffleDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");

		sop(list);

		//对list随机排序
		Collections.shuffle(list);
		sop(list);
	}

	//对集合进行自定义比较顺序的逆反转。
	public static void orderDemo(){
		TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator()));

		ts.add("abcde");
		ts.add("aaa");
		ts.add("k");
		ts.add("cc");

		Iterator it = ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	
	//使用另一个值替换列表中出现的所有某一指定值
	//反转List集合
	public static void replaceAllDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");

		sop(list);
		Collections.replaceAll(list,"aaa","pp");

		sop(list);
		Collections.reverse(list);

		sop(list);
	}

	/*
	练习:fill方法可以将list集合中所有元素替换成指定元素。
		将list集合中部分元素替换成指定元素。
	*/

	public static void fillDemo(){
		List<String> list = new ArrayList<String>();
	
		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");

		sop(list);
		Collections.fill(list,"pp");
		sop(list);
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

class StrLenComparator implements Comparator<String>
{
	public int compare(String s1,String s2){
		if(s1.length()>s2.length()){
			return 1;
		}else if(s1.length()<s2.length()){
			return -1;
		}else{
			return s1.compareTo(s2);
		}
	}
}

Arrays工具类练习:
Arrays:用于操作数组的工具类。
里面都是静态方法。

asList:将数组变成list集合。
*/
import java.util.*;

class ArraysDemo 
{
	public static void main(String[] args) 
	{
		/*数组变字符串
		int[] arr = {2,3,5};
		System.out.println(Arrays.toString(arr));
		*/

		String[] arr = {"abc","ee","ggg"};

		/*
		把数组变成list集合有什么好处?
		可以使用集合的思想和方法来操作数组中的元素。

		注意:将数组变成集合,不可以使用集合的增删方法。
			  因为数组的长度是固定的。
		eg:
		   contains()
		   get()
		   indexOf()
		   subList();

		   如果你增删,那么会发生UnsupportedOperationException。
		*/

		List<String> list = Arrays.asList(arr);
		//sop("contains:"+list.contains("ee"));

		//list.add("qq");不能增加,报UnsupportedOperationException。
		
		/*看现象---li打印出来的是哈希值,为什么?
		sop(list);
		int[] arr1 = {2,4,5};
		List li = Arrays.asList(arr1);
		sop(li);
		*/
		
		//这里打印的则是[2,4,5]
		/*
		原因:如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成了集合中的元素。
			  如果数组中的元素是基本数据类型,那么会将该数组作为集合中的元素存在。
		*/
		sop(list);
		Integer[] arr1 = {2,4,5};
		List<Integer> li = Arrays.asList(arr1);
		sop(li);

	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}

集合变成数组
1.指定类型的数组到底要定义多长呢?
当指定类型的数组长度大于了集合的长度,那么该方法内部会创建一个新的数组,长度为集合的size。
当指定类型的数组长度小于了集合的size,就不会新创建数组,而是使用传递进来的数组。

2.为什么要将集合变数组?
为了限定对元素的操作,不需要进行增删。

/*
集合变数组。
Collection接口中的toArray方法
*/
import java.util.*;

class CollectionToArray 
{
	public static void main(String[] args) 
	{
		ArrayList<String> al = new ArrayList<String>();

		al.add("abc1");
		al.add("abc2");
		al.add("abc3");

		String[] arr = al.toArray(new String[al.size()]);

		System.out.println(Arrays.toString(arr));
	}
}

高级for循环

格式:
for( 数据类型  变量名:被遍历的集合(Collection)或者数组){  }

局限性:对集合进行遍历,只能获取集合元素,但是不能对集合进行操作

迭代器除了遍历,还可以进行remove集合中的元素的动作,
如果使用了ListIterator,还可以在遍历过程中对集合进行增删改查的动作。

高级for与传统for有什么区别呢?
高级for有一个局限性,必须有被遍历的目标,
建议在遍历数组时,还是希望使用传统for,因为传统for可以定义角标。

import java.util.*;

class ForEachDemo 
{
	public static void main(String[] args) 
	{
		/*遍历集合
		ArrayList<String> al = new ArrayList<String>();

		al.add("abc1");
		al.add("abc2");
		al.add("abc3");

		for(String s:al){
			System.out.println(s);
		}*/
		//System.out.println(al);
		

		/*遍历数组
		int[] arr = {3,5,1};

		for(int x=0;x<arr.length;x++){
			System.out.print(arr[x]+",");
		}

		System.out.println();

		for(int i:arr){
			System.out.print(i+",");
		}*/

		//遍历Map集合

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

		hm.put(1,"a");
		hm.put(2,"b");
		hm.put(3,"c");

		Set<Integer> keySet = hm.keySet();

		for(Integer i:keySet){
			System.out.println(i+":"+hm.get(i));
		}

		for(Map.Entry<Integer,String> me:hm.entrySet()){
			System.out.println(me.getKey()+"----"+me.getValue());
		}
	}
}

JDK1.5新特性:可变参数

在使用时注意:
可变参数一定要定义在参数列表的最后面。
class ParamMethodDemo 
{
	public static void main(String[] args) 
	{	
		/*方法一:
		show(3,4);
		show(3,4,5);
		*/
		/*方法二:
		虽然少定义了多个方法,但是每次都要定义数组,作为实际参数。
		int[] arr = {3,4};
		show(arr);

		int[] arr1 = {3,4,5};
		show(arr1);
		*/
	
		/*
		方法三:可变参数
		其实就是上一种数组参数的简写形式,不用每一次都手动的建立数组对象。
		只要将要操作的元素作为参数传递即可,隐式的将这些参数封装成了数组。
		*/

		show("haha",2,3,4);
		//show(2,3,4,"hehe");  错误,可变参数必须放在最后面。
	}

	//方法三:
	public static void show(String str,int... arr){
		System.out.println(arr.length);
	}

	/*
	想调用含不同参数的方法,但是又想简化代码,尝试二:
	//虽然不用重复写方法,但是每次调用都要定义数组,也很繁琐。
	public static void show(int[] arr){
	}
	*/

	/*
	想调用含不同参数的方法,但是又想简化代码,尝试一:
	//代码太繁琐,每次都要重复写方法。
	public static void show(int a,int b){
		System.out.println(a+","+b);
	}

	public static void show(int a,int b,int c){
		System.out.println(a+","+b+","+c);
	}
	*/
}

JDK1.5新特性:静态导入

StaticImport 静态导入。

当类名重名时,需要指定具体的包名。
当方法重名时,需要指定具备所属的对象或者类。

eg:
import java.util.*;
import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。
import static java.util.Collections.*;

packa/Demo.class
packb/Demo.class

import packa.*;
import packb.*;

import static java.lang.System.*;//导入了System类中所有静态成员。

class StaticImport 
{
	public static void main(String[] args) 
	{
		out.println("haha");

		int[] arr = {3,1,5};

		sort(arr);
		int index = binarySearch(arr,1);
		out.println(Arrays.toString(arr));
		System.out.println("Index="+index);

		ArrayList al = new ArrayList();
		al.add(1);
		al.add(3);
		al.add(2);

		out.println(al);

		sort(al);
		out.println(al);
	}
}

System类

System:类中的方法和属性都是静态的。
out:标准输出,默认是控制台
in:标准输入,默认是键盘

描述系统一些信息。

获取系统属性信息:Properties   getProperties( );

import java.util.*;

class SystemDemo 
{
	public static void main(String[] args) 
	{
		Properties prop = System.getProperties();

		/*
		因为Properties是Hashtable的子类,也就是Map集合的一个子类对象。
		那么可以通过Map的方法取出该集合中的元素。
		该集合中存储的都是字符串,没有泛型定义。
		*/

		//如何在系统中自定义一些特有信息呢?
		System.setProperty("myKey","myValue");

		//获取指定属性信息。
		String value = System.getProperty("os.name");
		System.out.println(value);

		//可不可以在jvm启动时,动态加载一些属性信息呢?
		//java -Dhaha=qqqqqq SystemDemo.java
		String v = System.getProperty("haha");

		System.out.println("v="+v);
		
		/*获取所有属性信息
		for(Object obj:prop.keySet()){
			String value = (String)prop.get(obj);
			System.out.println(obj+"::"+value);
		}*/
	}
}

Runtime对象

该类中并没有提供构造函数。
说明不可以new对象,那么会直接想到该类中的方法都是静态的,
但是发现该类中还有非静态方法,说明该类肯定提供了方法获取本类对象,
而且该方法是静态的,并且返回值类型是本类对象。
由这个特点可以看出,该类使用了单例设计模式完成。


Date对象
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo {

	public static void main(String[] args) {
		Date d = new Date();
		System.out.println(d);
		
		//将模式封装到SimpleDateFormat对象中
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日  hh:mm:ss");
		
		//调用format方法让模式格式化指定Date对象
		String time = sdf.format(d);
		System.out.println(time);
		
		long l = System.currentTimeMillis();
		Date d1 = new Date(l);
		System.out.print(d1);
	}

}

Calendar对象
import java.util.*;
import java.text.*;

class CalendarDemo
{
	public static void main(String[] args) 
	{
		Calendar c = Calendar.getInstance();

		String[] mons = {"一月","二月","三月","四月"
					,"五月","六月","七月","八月"
					,"九月","十月","十一月","十二月"};

		String[] weeks = {"","星期日","星期一","星期二","星期三",
							"星期四","星期五","星期六"};

		int index = c.get(Calendar.MONTH);
		int index1 = c.get(Calendar.DAY_OF_WEEK);

		sop(c.get(Calendar.YEAR)+"年");

		//sop(c.get(Calendar.MONTH)+"月");
		sop(mons[index]);

		sop(c.get(Calendar.DAY_OF_MONTH)+"日");

		//sop("星期"+c.get(Calendar.DAY_OF_WEEK));
		sop(weeks[index1]);

		/*
		Date d = new Date();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年");
		String time = sdf.format(d);

		System.out.println(time);*/
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值