java基础---集合

集合类的由来:
    对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。就使用集合容器进行存储。

集合特点:
1,用于存储对象的容器。
2,集合的长度是可变的。
3,集合中不可以存储基本数据类型值。

集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。

框架的顶层Collection接口:

Collection的常见方法: 

1,添加。
    boolean add(Object obj):
    boolean addAll(Collection coll):    

2,删除。
    boolean remove(object obj):
    boolean removeAll(Collection coll);
    void clear();
    
3,判断:
    boolean contains(object obj):
    boolean containsAll(Colllection coll);
    boolean isEmpty():判断集合中是否有元素。 

4,获取:
    int size():
    Iterator iterator():取出元素的方式:迭代器。
    该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。
    所以该迭代器对象是在容器中进行内部实现的。
    对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,
    也就是iterator方法。
        Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
        
5,其他:
    boolean retainAll(Collection coll);取交集。
    Object[] toArray():将集合转成数组。

demo1:

public class CollectionDemo {

	public static void main(String[] args) {
		Collection coll = new ArrayList();
		
//		show(coll);
		
		Collection c1 = new ArrayList();
		Collection c2 = new ArrayList();
		show(c1,c2);	
	}
	
	public static void show(Collection c1,Collection c2){
		
		//给c1添加元素。
		c1.add("abc1");
		c1.add("abc2");
		c1.add("abc3");
		c1.add("abc4");
		
		//给c2添加元素。
		c2.add("abc1");
		c2.add("abc2");
		c2.add("abc3");
		c2.add("abc4");
		c2.add("abc5");
		
		System.out.println("c1:"+c1);
		System.out.println("c2:"+c2);
		
		//演示addAll
		
//		c1.addAll(c2);//将c2中的元素添加到c1中。	
		
		//演示removeAll
//		boolean b = c1.removeAll(c2);//将两个集合中的相同元素从调用removeAll的集合中删除。
//		System.out.println("removeAll:"+b);
		
		//演示containsAll
//		boolean b = c1.containsAll(c2);
//		System.out.println("containsAll:"+b);
		
		//演示retainAll
		boolean b = c1.retainAll(c2);//取交集,保留和指定的集合相同的元素,而删除不同的元素。
								//和removeAll功能相反 。
		System.out.println("retainAll:"+b);
		System.out.println("c1:"+c1);			
	}
	
	public static void show(Collection coll){
		
		//1,添加元素。add.
		coll.add("abc1");
		coll.add("abc2");
		coll.add("abc3");
		System.out.println(coll);
		
		//2,删除元素。remove
//		coll.remove("abc2");//会改变集合的长度 
		
		//清空集合.
//		coll.clear();
		
		System.out.println(coll.contains("abc3"))			
		System.out.println(coll);		
	}
}

demo2:

public class IteratorDemo {

	public static void main(String[] args) {

		Collection coll = new ArrayList();
		coll.add("abc1");
		coll.add("abc2");
		coll.add("abc3");
		coll.add("abc4");
		
//		System.out.println(coll);
		
		//使用了Collection中的iterator()方法。 调用集合中的迭代器方法,是为了获取集合中的迭代器对象。
//		Iterator it = coll.iterator();		
//		while(it.hasNext()){
//			System.out.println(it.next());
//		}
		
		for(Iterator it = coll.iterator(); it.hasNext(); ){
			System.out.println(it.next());
		}
		
//		System.out.println(it.next());
//		System.out.println(it.next());
//		System.out.println(it.next());
//		System.out.println(it.next());
//		System.out.println(it.next());//java.util.NoSuchElementException
		
	}
}

Collection
    |--List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
    |--Set:元素不能重复,无序。

List:特有的常见方法:有一个共性特点就是都可以操作角标。

List:特有的常见方法:有一个共性特点就是都可以操作角标。
    
1,添加
    void add(index,element);
    void add(index,collection);

2,删除;
    Object remove(index):

3,修改:
    Object set(index,element);    

4,获取:
    Object get(index);
    int indexOf(object);
    int lastIndexOf(object);
    List subList(from,to);
        
list集合是可以完成对元素的增删改查。

List:
    |--Vector:内部是数组数据结构,是同步的。增删,查询都很慢!
    |--ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。
    |--LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。

demo1:

public class ListDemo {

	public static void main(String[] args) {
		List list = new ArrayList();
		show(list);
	}

	public static void show(List list) {
		
		//添加元素
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		System.out.println(list);
		
		//插入元素。		
//		list.add(1,"abc9");
		
		//删除元素。
//		System.out.println("remove:"+list.remove(2));
		
		//修改元素。
//		System.out.println("set:"+list.set(1, "abc8"));
		
		//获取元素。
//		System.out.println("get:"+list.get(0));
		
		//获取子列表。
//		System.out.println("sublist:"+list.subList(1, 2));
			
		System.out.println(list);				
	}
}

demo2:

public class ListDemo2 {

	public static void main(String[] args) {

		List list = new ArrayList();
//		show(list);
			
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		
		System.out.println("list:"+list);
		ListIterator it = list.listIterator();//获取列表迭代器对象
		//它可以实现在迭代过程中完成对元素的增删改查。
		//注意:只有list集合具备该迭代功能.
				
		while(it.hasNext()){
			
			Object obj = it.next();
			
			if(obj.equals("abc2")){
				it.set("abc9");
			}
		}
//		System.out.println("hasNext:"+it.hasNext());
//		System.out.println("hasPrevious:"+it.hasPrevious());
		
		
		while(it.hasPrevious()){
			System.out.println("previous:"+it.previous());
		}
		System.out.println("list:"+list);			
		
		/*Iterator it = list.iterator();
		while(it.hasNext()){
			
			Object obj = it.next();//java.util.ConcurrentModificationException
							//在迭代器过程中,不要使用集合操作元素,容易出现异常。
						//可以使用Iterator接口的子接口ListIterator来完成在迭代中对元素进行更多的操作。 
			
			if(obj.equals("abc2")){
				list.add("abc9");
			}
			else
				System.out.println("next:"+obj);
		}
		System.out.println(list);
		*/
		
	}

	public static void show(List list) {
		
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		list.add("abc4");
		
		Iterator it = list.iterator();
		while(it.hasNext()){
			System.out.println("next:"+it.next());
		}
		
		//list特有的取出元素的方式之一。
		
		for(int x=0; x<list.size(); x++){
			System.out.println("get:"+list.get(x));
		}
	}
}

LinkedList:

    addFirst();
    addLast():
    jdk1.6
    offerFirst();
    offetLast();  
    
    getFirst();.//获取但不移除,如果链表为空,抛出NoSuchElementException.
    getLast();
    jdk1.6
    peekFirst();//获取但不移除,如果链表为空,返回null.
    peekLast():
    
    removeFirst();//获取并移除,如果链表为空,抛出NoSuchElementException.
    removeLast();
    jdk1.6
    pollFirst();//获取并移除,如果链表为空,返回null.
    pollLast();

 

Set:元素不可以重复,是无序。
    Set接口中的方法和Collection一致。
    |--HashSet: 内部数据结构是哈希表 ,是不同步的。
        如何保证该集合的元素唯一性呢?
        是通过对象的hashCode和equals方法来完成对象唯一性的。
        如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。 
        如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
        如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
        
        记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
        一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。
        建立对象判断是否相同的依据。
                
        
    |--TreeSet:可以对Set集合中的元素进行排序。是不同步的。 
                判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。 
                
   TreeSet对元素进行排序的方式一:
         使用元素的自然顺序排序,既元素的类实现Comperable接口(此接口强行对实现它的每个类的对象进行整体排序。这                   种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法),并覆盖compareTo()方法,在此方法中定             义比较方法。
                
  如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
  可以使用TreeSet集合第二种排序方式二:
  让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
  将该类对象作为参数传递给TreeSet集合的构造函数。
               

哈希表确定元素是否相同
1,判断的是两个元素的哈希值是否相同。
    如果相同,在判断两个对象的内容是否相同。

2,判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。

注意:如果哈希值不同,是不需要判断equals。

 

泛型:jdk1.5出现的安全机制。

好处:
    1,将运行时期的问题ClassCastException转到了编译时期。
    2,避免了强制转换的麻烦。

<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
   其实<>就是一个用于接收具体引用数据类型的参数范围。

在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。
泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。

在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。

public class Tool<QQ>{
	private QQ q;

	public QQ getObject() {
		return q;
	}

	public void setObject(QQ object) {
		this.q = object;
	}
		
	/**
	 * 将泛型定义在方法上。
	 */
	public <W> void show(W str){
		System.out.println("show : "+str.toString());
	}
	public void print(QQ str){
		System.out.println("print : "+str);
	}
	
	/**
	 * 当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,
	 * 只能将泛型定义在方法上。 
	 */
	public static <Y> void method(Y obj){
		System.out.println("method:"+obj);
	}
}

泛型接口:

public class GenericDefineDemo5 {

	public static void main(String[] args) {

		InterImpl in = new InterImpl();
		in.show("abc");
		
		InterImpl2<Integer> in2 = new InterImpl2<Integer>();
		in2.show(5);
	}
}
//泛型接口,将泛型定义在接口上。 
interface Inter<T>{
	public void show(T t);
}

//使用接口时不声明具体类型,创建子类对象时明确具体类型
class InterImpl2<Q> implements Inter<Q>{
	public void show(Q q){
		System.out.println("show :"+q);
	}
}
//使用接口时声明就具体类型
class InterImpl implements Inter<String>{
	public void show(String str){
		System.out.println("show :"+str);
	}
}

泛型的通配符:? 未知类型。

	public static void printCollection(Collection<?> al) {	
	
		Iterator<?> it = al.iterator();		
		while(it.hasNext()){
//			T str = it.next();
//			System.out.println(str);
			System.out.println(it.next().toString());
		}	
	}

泛型的限定:
? extends E: 接收E类型或者E的子类型对象。上限
一般存储对象的时候用。比如 添加元素 addAll.

? super E: 接收E类型或者E的父类型对象。 下限。
一般取出对象的时候用。比如比较器。

	public static void printCollection(Collection<? extends Person> al) {
		
		Iterator<? extends Person> it = al.iterator();		
		while(it.hasNext()){
//			T str = it.next();
//			System.out.println(str);
//			System.out.println(it.next().toString());
			Person p = it.next();
			
			System.out.println(p.getName()+":"+p.getAge());
		}		
	}
	
	public static void printCollection(Collection<? super Student> al){
		Iterator<? super Student> it = al.iterator();		
		while(it.hasNext()){			
			System.out.println(it.next());
		}
	}

集合的一些技巧:

需要唯一吗?
需要:Set
    需要制定顺序: 
            需要: TreeSet
            不需要:HashSet
            但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
    需要频繁增删吗?
        需要:LinkedList
        不需要:ArrayList

如何记录每一个容器的结构和所属体系呢?看名字!

List
    |--ArrayList
    |--LinkedList

Set
    |--HashSet
    |--TreeSet

后缀名就是该集合所属的体系。

前缀名就是该集合的数据结构。

看到array:就要想到数组,就要想到查询快,有角标.    
看到link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法 
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。 
看到tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。

而且通常这些常用的集合容器都是不同步的。

 

                                        MAP

Map:一次添加一对元素。Collection 一次添加一个元素。
    Map也称为双列集合,Collection集合称为单列集合。
    其实map集合中存储的就是键值对。 
    map集合中必须保证键的唯一性。 
        
常用方法:
1,添加。
    value put(key,value):返回前一个和key关联的值,如果没有返回null.

2,删除。
    void  clear():清空map集合。
    value remove(key):根据指定的key翻出这个键值对。 

3,判断。
    boolean containsKey(key):
    boolean containsValue(value):
    boolean isEmpty();

4,获取。 
    value get(key):通过键获取值,如果没有该键返回null。                    当然可以通过返回null,来判断是否包含指定键。 
    int size(): 获取键值对的个数。 
                                
Map常用的子类:
    |--Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。
        |--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。         
    |--HashMap : 内部结构是哈希表,不是同步的。允许null作为键,null作为值。
    |--TreeMap : 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。

demo1:

public class MapDemo {

	public static void main(String[] args) {
		
		Map<Integer,String> map = new HashMap<Integer,String>();
		method_2(map);
	}
	
	public static void method_2(Map<Integer,String> map){
		map.put(8,"zhaoliu");
		map.put(2,"zhaoliu");
		map.put(7,"xiaoqiang");
		map.put(6,"wangcai");
				
		Collection<String> values = map.values();		
		Iterator<String> it2 = values.iterator();
		while(it2.hasNext()){
			System.out.println(it2.next());
		}		
		/*
		 * 通过Map转成set就可以迭代。
		 * 找到了另一个方法。entrySet。
		 * 该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型(结婚证)		 		 * 
		 */
		Set<Map.Entry<Integer, String>> entrySet = map.entrySet();		
		Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();	
		while(it.hasNext()){
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key+"::::"+value);			
		}
		//取出map中的所有元素。
		//原理,通过keySet方法获取map中所有的键所在的Set集合,在通过Set的迭代器获取到每一个键,
		//在对每一个键通过map集合的get方法获取其对应的值即可。
		/*
		Set<Integer> keySet = map.keySet();
		Iterator<Integer> it = keySet.iterator();		
		while(it.hasNext()){
			Integer key = it.next();
			String value = map.get(key);
			System.out.println(key+":"+value);			
		}
		*/		
	}	
	public static void method(Map<Integer,String> map){//学号和姓名		
		// 添加元素。
		System.out.println(map.put(8, "wangcai"));//null
		System.out.println(map.put(8, "xiaoqiang"));//wangcai 存相同键,值会覆盖。
		map.put(2,"zhangsan");
		map.put(7,"zhaoliu");		
		//删除。
//		System.out.println("remove:"+map.remove(2));		
		//判断。
//		System.out.println("containskey:"+map.containsKey(7));	
		//获取。 
		System.out.println("get:"+map.get(6));		
		System.out.println(map);		
		Outer.Inner.show();
	}	
}
interface MyMap{
	public static interface MyEntry{//内部接口
		void get();
	}
}
class MyDemo implements MyMap.MyEntry{
	public void get(){}
}
class Outer{
	static class Inner{
		static void show(){}
	}
}

demo2:

public class HashMapDemo {

	public static void main(String[] args) {		
		/*
		 * 将学生对象和学生的归属地通过键与值存储到map集合中。 
		 */
		
		HashMap<Student,String> hm = new HashMap<Student,String>();		
		hm.put(new Student("lisi",38),"北京");
		hm.put(new Student("zhaoliu",24),"上海");
		hm.put(new Student("xiaoqiang",31),"沈阳");
		hm.put(new Student("wangcai",28),"大连");
		hm.put(new Student("zhaoliu",24),"铁岭");
		
//		Set<Student> keySet = hm.keySet();		
//		Iterator<Student> it = keySet.iterator();
		
		Iterator<Student> it = hm.keySet().iterator();		
		while(it.hasNext()){
			Student key = it.next();
			String value = hm.get(key);
			System.out.println(key.getName()+":"+key.getAge()+"---"+value);
		}		
	}
}

demo3:

public class TreeMapDemo {

	public static void main(String[] args) {

		TreeMap<Student,String> tm = new TreeMap<Student,String>(new ComparatorByName());	
		tm.put(new Student("lisi",38),"北京");
		tm.put(new Student("zhaoliu",24),"上海");
		tm.put(new Student("xiaoqiang",31),"沈阳");
		tm.put(new Student("wangcai",28),"大连");
		tm.put(new Student("zhaoliu",24),"铁岭");	
		Iterator<Map.Entry<Student, String>> it = tm.entrySet().iterator();
		
		while(it.hasNext()){
			Map.Entry<Student,String> me = it.next();
			Student key = me.getKey();
			String value = me.getValue();			
			System.out.println(key.getName()+":"+key.getAge()+"---"+value);
		}	
	}
}

LinkedHashMap

public class LinkedHashMapDemo {
	public static void main(String[] args) {
		
		File f= null;
		HashMap<Integer,String> hm = new LinkedHashMap<Integer,String>();		
		hm.put(7, "zhouqi");
		hm.put(3, "zhangsan");
		hm.put(1, "qianyi");
		hm.put(5, "wangwu");		
		Iterator<Map.Entry<Integer,String>> it = hm.entrySet().iterator();		
		while(it.hasNext()){
			Map.Entry<Integer,String> me = it.next();			
			Integer key = me.getKey();
			String value = me.getValue();			
			System.out.println(key+":"+value);
		}
	}
}

练习:
 "fdgavcbsacdfs" 获取该字符串中,每一个字母出现的次数。
  要求打印结果是:a(2)b(1)...;

* 思路:
 * 对于结果的分析发现,字母和次数之间存在着映射的关系。而且这种关系很多。
 * 很多就需要存储,能存储映射关系的容器有数组和Map集合。
 * 关系一方式有序编号吗?没有!
 * 那就是使用Map集合。 又发现可以保证唯一性的一方具备着顺序如 a b c ...
 * 所以可以使用TreeMap集合。
 * 
 * 这个集合最终应该存储的是字母和次数的对应关系。 
 * 
 * 1,因为操作的是字符串中的字母,所以先将字符串变成字符数组。
 * 2,遍历字符数组,用每一个字母作为键去查Map集合这个表。
 * 如果该字母键不存在,就将该字母作为键 1作为值存储到map集合中。
 * 如果该字母键存在,就将该字母键对应值取出并+1,在将该字母和+1后的值存储到map集合中,
 * 键相同值会覆盖。这样就记录住了该字母的次数.
 * 3,遍历结束,map集合就记录所有字母的出现的次数。

 

public class MapTest {

	public static void main(String[] args) {
		
		String str = "fdg+avAdc  bs5dDa9c-dfs";		
		String s = getCharCount(str);		
		System.out.println(s);		
	}

	public static String getCharCount(String str) {
				
		//将字符串变成字符数组 
		char[] chs = str.toCharArray();		
		//定义map集合表。
		Map<Character,Integer> map = new TreeMap<Character,Integer>();
		
		for (int i = 0; i < chs.length; i++) {
			
			if(!(chs[i]>='a' && chs[i]<='z' || chs[i]>='A' && chs[i]<='Z'))
//			if(!(Character.toLowerCase(chs[i])>='a' && Character.toLowerCase(chs[i])<='z'))
				continue;			
			//将数组中的字母作为键去查map表。			
			Integer value = map.get(chs[i]);
			
			int count = 1;
			
			//判断值是否为null.
			if(value!=null){
				count = value+1;
			}
//			count++;
			map.put(chs[i], count);
			/*
			if(value==null){
				map.put(chs[i], 1);
			}else{
				map.put(chs[i], value+1);
			}
			*/
		}					
		return mapToString(map);
	}

	private static String mapToString(Map<Character, Integer> map) {
		
		StringBuilder sb = new StringBuilder();		
		Iterator<Character> it = map.keySet().iterator();		
		while(it.hasNext()){
			Character key = it.next();
			Integer value = map.get(key);			
			sb.append(key+"("+value+")");
		}		
		return sb.toString();
	}
}

foreach:

public class ForEachDemo {
	public static void main(String[] args) {
		/*
		 * foreach语句:
		 * 格式:
		 * for(类型  变量   :Collection集合|数组)
		 * {
		 * 		
		 * }
		 * 
		 * 传统for和高级for的区别?
		 * 传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。
		 * 
		 * 高级for是一种简化形式。
		 * 它必须有被遍历的目标。该目标要是数组,要么是Collection单列集合。
		 * 
		 * 对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。
		 * 如果要对数组的角标进行操作建议使用传统for。 
		 *  
		 */
		
		List<String> list =new ArrayList<String>();
		
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		
		for(String s : list){	//简化书写。		
			System.out.println(s);			
		}
				
		int[] arr = {3,1,5,7,4};
		
		for(int i : arr){
			System.out.println(i);
		}				
		//可以使用高级for遍历map集合吗?不能直接用,但是可以将map转成单列的set,就可以用了。
		Map<Integer,String> map = new HashMap<Integer,String>();
		
		map.put(3,"zhagsan");
		map.put(1,"wangyi");
		map.put(7,"wagnwu");
		map.put(4,"zhagsansan");	
		
		for(Integer key : map.keySet()){
			String value = map.get(key);
			System.out.println(key+"::"+value);
		}
		
		for(Map.Entry<Integer,String> me : map.entrySet()){
			Integer key = me.getKey();
			String value = me.getValue();			
			System.out.println(key+":"+value);
		}		
		
		Iterator<String> it = list.iterator();	
		while(it.hasNext()){
			System.out.println(it.next());
		}		
	}
}

可变参数:

public class ParamterDemo {

	public static void main(String[] args) {	
		int sum = newAdd(5,1,4,7,3);
		System.out.println("sum="+sum);
		int sum1 = newAdd(5,1,2,7,3,9,8,7,6);
		System.out.println("sum1="+sum1);
		
	}
	/*
	 * 函数的可变参数。
	 * 其实就是一个数组,但是接收的是数组的元素。
	 * 自动将这些元素封装成数组。简化了调用者的书写。
	 * 
	 * 注意:可变参数类型,必须定义在参数列表的结尾。 
	 */
	public static int newAdd(int a,int...  arr){
		
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum+=arr[i];
		}
		return sum;
	}
	
	public static int add(int[] arr){
		
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum+=arr[i];
		}
		return sum;		
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值