您的位置:首页 > 编程语言 > Java开发

Java基础<九>_集合(上)

2013-09-14 21:50 721 查看
集合(上)
一、Collection

1.1、集合的概述

根据面向对象的思想,数据多了就用对象来存储;对象多了,就用数组或者集合来存储。数组虽然可以存储对象,但长度不可变,类型固定,有很大的局限性;集合长度可变,类型不固定。正因为集合克服了数组的局限性,所以对象的存储大多数存在集合中。

因为底层的数据结构不同,所以集合可以分为很多种,但根据共性抽取的原则,可以把多种不同的集合不断地向上抽取。Collection接口就是不断抽取而成的,它可以分为List和Set两大接口。

List:元素有序,元素可以重复,有索引;

Set:元素无序(存入取出无序),元素不可重复。

Collection中有抽取了一些共性的方法,例如:add(Object obj):添加元素到集合中。

注意:集合中存储的都是对象的引用,也就是地址,并非对象本身。Java中的集合框架如下图所示:



迭代器:迭代器就是取出集合元素的方式。由于每个集合内部的数据结构不同,取出方式也就有所不同,但该怎么取出元素,只有集合本身最清楚,所以迭代器应该定义在集合的内部,成为内部类或者内部接口。但每种集合元素的取出方式都有一些共性,比如:内容判断、取出等,那么就将这些共性抽取形成一个接口:Iterator。
在java中,形成了Iterator接口后,取出不同集合的元素就在不同集合的内部实现;
那么该如何获取取出对象呢?通过对外提供的方法iterator()即可,这就是迭代器的基本原理。
二、List

List是Collection接口中的一个重要子接口,实现List接口的子类有很多,但比较重要的有Vector、ArrayList和LinkedList三个,下面主要介绍的也就是这三个。

ArrayList:底层的数据结构是数组,查询速度快,但增删操作稍慢,线程不同步。

LinkedList:底层的数据结构是链表,查询速度稍慢,但增删操作很快,线程不同步。

Vector:底层的数据结构是数组,线程同步,已经被ArrayList替代。

List接口中,有自己特有的方法,注意:凡是可以操作角标的方法都是该体系特有的方法

增:add(index,element); addAll(index,Collection);

删:remove(index);

改:set(index,element);

查:get(index);SubList(from,to);ListIterator()。

List集合特有的迭代器:ListIterator。ListIterator是Iterator的子接口。

在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生异常。所以在迭代时,只能用迭代的方式操作元素,可是Iterator中的方法是有限的,只能对元素进行判断、取出、删除等操作。

如果想进行其他的操作如添加、修改等,必须使用ListIterator,该接口只能通过List集合中的ListIterator()方法获取。

LinkList特有方法:

addFirst();addlast();添加元素;

getFirst();getLast(); 获取但不删除;

removeFirst();removeLast():获取但删除。

JDK1.6出现了替代方法:

offerFirst();offerLast();添加元素;

peekFirst();peekLast()获取但不删除;

pollFirst();pollLast()获取但删除。

在List集合中,判断元素是否相同,调用的是元素的equals()方法;remove(),contains()等方法的底层也是调用了equals()方法。

注意:List集合中开发多用ArrayList,因为集合中一般都是查询的多。

下面代码体现:

1、将自定义的对象作为元素存到ArrayList集合中,并去除重复的元素

package itheima.day14;

import java.util.ArrayList;
import java.util.Iterator;

//需求:
// 将自定义对象作为元素存到ArrayList集合中,并去除重复元素
//  比如:人对象,同姓名同年龄,视为同一个人
public class ArrayListTest2 {
public static void main(String[] args) {

ArrayList al = new ArrayList();
//		添加元素
al.add(new Person("zhangsan",15));
al.add(new Person("zhangsan1",16));
al.add(new Person("zhangsan2",17));
al.add(new Person("zhangsan1",16));

al = singleElement(al);
//		通过迭代器的方式取出集合中的元素
Iterator it = al.iterator();
while(it.hasNext()){
Object obj = it.next();
Person p = (Person)obj;
sop(p.getName()+"::::"+p.getAge());
}
}
private static ArrayList singleElement(ArrayList al) {

//		定义一个临时容器
ArrayList newAl = new ArrayList();
Iterator it = al.iterator();
while(it.hasNext()){
Object obj = it.next();
if(!newAl.contains(obj))//是否包含
newAl.add(obj);
}
return newAl;
}
public static void sop(Object obj){
System.out.println(obj);
}
}
//人
class Person{

private String name;
private int age;
Person(String name,int age){
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;
}

//	List集合判断元素是否相同,依据的是元素的equals方法。
//	remove(),contains()方法的底层也是调用了equals方法.
//	必须覆盖Object中的equals方法,根据自定义的方式判断两个元素是否相同
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name .equals(p.name) && this.age == p.age;
}
}


2、使用LinkedList模拟一个堆栈或者队列数据结构

package itheima.day14;

import java.util.LinkedList;

//使用LinkedList模拟一个堆栈或者队列数据结构*/
//堆栈:先进后出,如同杯子
// 队列:先进先出:如同水管
public class LinkedListTest {

public static void main(String[] args) {

DuiLie dl = new DuiLie();
dl.myAdd("java01");
dl.myAdd("java02");
dl.myAdd("java03");
dl.myAdd("java04");

while(!dl.isNull()){
sop(dl.myGet());
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
//封装一个队列的类
class DuiLie{
//	底层封装一个链表,改造
private LinkedList link;
DuiLie(){
link = new LinkedList();
}
public void myAdd(Object obj){
link.addFirst(obj);
}
public Object myGet(){
return  link.removeLast();//队列:先进先出
//		return link.removeFirst();//如果是堆栈的话,就后进先出
}
public boolean isNull(){
return link.isEmpty();
}
}


三、Set

Set中的元素无序(存入和取出无序),元素不可以重复;Set是Collection接口中一个重要的子接口;实现Set接口的子类有很多,但比较重要的有HashSet、TreeSet两个。

HashSet:底层数据结构是哈希表。HashSet通过调用元素自身的hashCode()、equals()方法来保证元素的唯一性

如果元素的hashCode()返回的值不同,则直接认为两个元素不是同一个元素;否则,继续判断元素的equals()方法,如果返回值是false,则认为两个元素不是同一个元素;返回值为true,则认为两个元素是同一个元素,注意:若哈希值不一样,不会继续判断equals()方法。

所以:如果自定义的对象要存储到HashSet集合中,必须覆盖对象自身的hashCode()方法和equals()方法。

TreeSet:HashSet集合可以保证元素的唯一性,但不能保证元素的有序性;而TreeSet集合既可以保证元素的唯一性,也可以保证元素在集合中存储的有序性。

TreeSet保证元素有序性有两种方式:让元素自身基本具备比较性、让TreeSet集合本身具备比较性。

1、让元素自身具备比较性:Copareable接口可以让元素具备比较性,实现该接口的类必须实现CompareTo()方法;所以,要想让元素自身具备比较性,需要实现Comparable接口,复写compareTo方法,即可。

2、让TreeSet集合自身具备比较性:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让TreeSet具备比较性。可以定义一个类,实现Comparator接口,并且覆盖compare()方法,称之为比较器;然后将比较器对象作为参数传递给TreeSet集合的构造函数,即可。

TreeSet集合底层数据结构是二叉树,当元素进入二叉树时,可以减少比较次数,提高效率。

下面代码体现:

1、往HashSet集合中存入自定义对象

package itheima.day14;

import java.util.HashSet;
import java.util.Iterator;
//往HashSet集合中存入自定义对象
//  人:姓名和年龄相同,那么视为同一个对象
public class HashSetTest {

public static void main(String[] args) {

HashSet hs = new HashSet();
//		添加元素
hs.add(new Person1("a1",12));
hs.add(new Person1("a2",13));
hs.add(new Person1("a3",14));
hs.add(new Person1("a1",12));
hs.add(new Person1("a4",15));

boolean yes =hs.contains(new Person1("a1",12));
System.out.println(yes);
//		迭代器的=方式取出元素
Iterator it = hs.iterator();
while(it.hasNext()){
Person1  p = (Person1)it.next();
System.out.println(p.getName()+"::::"+p.getAge());
}
}
}
//人
class Person1{
private String name;
private int age;
Person1(String name,int age){
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;
}
//	为了让能够存入HashSet集合中,元素自身必须覆盖hashCode()函数
public int hashCode(){
return name.hashCode()+age*23;//哈希值按照本类的属性进行计算,更合理
}
//	为了让能够存入HashSet集合中,元素自身必须覆盖equals()函数
public boolean equals(Object obj){
if(!(obj instanceof Person1))
throw new RuntimeException("哥们,类型错误啦");
Person1 p = (Person1)obj;
//		如果姓名、年龄相同,视为同一个人
return this.name .equals(p.name) && this.age == p.age;
}
}


2、往TreeSet集合中存储自定义对象学生,按照学生的年龄进行排序

package itheima.day15;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

//需求:
//  往TreeSet集合中存储自定义对象学生,按照学生的年龄进行排序
public class TreeSetDemo {

public static void main(String[] args) {

//		new一个比较器对象作为参数传给构造函数,让集合自身具备比较性
//		TreeSet ts = new TreeSet(new MyCompare());
//		根据元素自身的排序方式进行排序
TreeSet ts = new TreeSet();
//		添加元素
ts.add(new Student("zhangsan1",23));
ts.add(new Student("zhangsan611",23));
ts.add(new Student("zhangsan2",24));
ts.add(new Student("zhangsan4",25));
ts.add(new Student("zhangsan0",23));
//		通过迭代器方式取出元素
Iterator it = ts.iterator();
while(it.hasNext()){
Student stu = (Student)(it.next());
System.out.println(stu.getName()+":::::"+stu.getAge());
}
}
}
//学生的类
class Student implements Comparable//该接口强制学生对象具有比较性
{
private String name;
private int age;
Student(String name,int age){
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;
}

//	为了存入TreeSet集合中,可以让元素自身具备比较性
public int compareTo(Object obj){
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象!!!");
Student s = (Student)obj;
//		按照年龄排序,年龄相同时,按照姓名的自然顺序比较
if(this.age>s.age)
return 1;
if(this.age <s.age)
return -1;
return this.name.compareTo(s.name);
}

}
//让TreeSet集合具备比较性,定义一个比较器
class MyCompare implements Comparator
{
public int compare(Object o1,Object o2){
if(!(o1 instanceof Student)|| !(o2 instanceof Student))
throw new RuntimeException("不是学生类!!!");
Student s1 =(Student)o1;
Student s2 = (Student)o2;
//		按姓名的自然顺序排序,当姓名相同时,按年龄排序
int num = s1.getName().compareTo(s2.getName());
if(num==0)
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
return num;
}
}


3、按照字符串长度进行排序

package itheima.day15;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

//练习:按照字符串长度进行排序
//字符串自身具备的比较性时按照自然顺序比较的,不是我们想要的,
// 所以,必须要让TreeSet集合自身具备比较性
public class TreeSetTest {
public static void main(String[] args) {

//		让TreeSet集合自身具备比较性,传比较器给构造函数
TreeSet ts = new TreeSet(new StrLenComparator());
//		添加元素
ts.add("abcdef");
ts.add("abcde");
ts.add("abcd");
ts.add("a");
ts.add("abc");
ts.add("abd");

//		取出元素
Iterator it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
//定义一个比较器
class StrLenComparator implements Comparator
{
//	覆盖该方法,具有比较性
public int compare(Object o1,Object o2){
String s1 = (String)o1;
String s2 = (String)o2;
//		按照自然顺序进行排序,若长度相同,则按照字符串的自然比较顺序排序
if(s1.length()>s2.length())
return 1;
if(s1.length()<s2.length())
return -1;
return s1.compareTo(s2);
}
}


四、泛型

泛型:泛型是JDK1.5版本以后出现的新特性,是一种类型安全机制,专门用于解决安全问题;泛型常常出现在集合框架中

好处1:集合中可以存储任意类型的元素,也就是说一个集合中可以存储两个或者以上不同类型的元素,但操作类型的方法底层在调用不同类型元素的方法时,往往会出现问题;所以:程序员必须主观控制存入集合中的类型,往往编译能通过,但运行时会出现ClassCastException异常。泛型的出现,可以将运行时期出现的ClassCastException转移到了编译时期,方便于程序员解决问题,让运行时问题减少,安全。

好处2:避免了强制类型转换带来的麻烦

泛型格式:通过<>来定义要操作的引用类型,当使用集合时,将集合中要存储的类型写到<>中即可。

泛型的定义:当集合中要操作的引用数据类型不确定时,早期定义Object来完成扩展,现在定义泛型来完成扩展

定义在类上的泛型,在整个类中有效,称之为:带泛型的类。

定义在方法上的泛型,在整个方法体中有效,称之为:带泛型的方法。

注意:静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。

泛型的限定:

?:通配符,也可以理解为占位符;

?extends E:可以接收E类型或者E的子类型,上限;

?super E:可以接收E类型或者E的父类型,下限。

下面代码体现:

1、演示泛型类、泛型方法、静态泛型方法

package itheima.day15;

//泛型类,泛型方法,静态泛型方法的演示
public class GenericDemo4 {

public static void main(String[] args) {
Demo<String> d = new Demo<String>();
d.show("haha");
d.print_1(new Integer(4));
d.method(new Double(153.652));
}
}
//类型不确定,定义带泛型的类
class Demo<T>{
//	类的泛型在类中的成员方法上有效
public void show(T t){
System.out.println("Class Generic show::"+t);
}
//	方法上要操作的类型不确定,定义带泛型的方法
public <Q> void print_1(Q q){
System.out.println("Method Generic show:::"+q);
}
//	静态方法不可以使用类上的泛型,带泛型的静态方法
public  static <W> void method(W w){
System.out.println("Generic static method show:::"+w);
}
}


2、上限的使用,举例说明

package itheima.day15;

import java.util.ArrayList;
import java.util.Iterator;

//泛型的上限,举例说明
public class GenericDemo6 {

public static void main(String[] args) {

ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("abc1"));
al.add(new Person("abc2"));
al.add(new Person("abc3"));
al.add(new Person("abc4"));
//		printColl(al);

ArrayList<Student2> al1 = new ArrayList<Student2>();
al1.add(new Student2("abc---1"));
al1.add(new Student2("abc---2"));
al1.add(new Student2("abc---3"));
al1.add(new Student2("abc---4"));
//		printColl(ArrayList<? extends Person> al),Student2继承Person,上限
printColl(al1);
}
//	? extends E:可以接收E类型或者E的子类型,上限
public static void printColl(ArrayList<? extends Person> al){
Iterator<? extends Person> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}

class Person{
private String name;
Person(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "name:::" + name ;
}
}
//学生
class Student2 extends Person implements  Comparable<Person>//<? extends E>
{
public Student2(String name) {
super(name);
}
public int compareTo(Person s){
return this.getName().compareTo(s.getName());
}
}


3、下限的使用,举例说明

package itheima.day15;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

//泛型的下限,举例说明
public class GenericDemo8 {

public static void main(String[] args) {

//		TreeSet(Comparator<? super E> comparator)
//		E:泛型;Student3:参数化的泛型;Comparator<? super E>:意思是说:可以使用Student3父类的比较器
TreeSet<Student3> ts = new TreeSet<Student3>(new Comp());
//		添加元素
ts.add(new Student3("abc01"));
ts.add(new Student3("abc05"));
ts.add(new Student3("abc03"));
ts.add(new Student3("abc04"));

Iterator<Student3> it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}

TreeSet<Worker1> ts1 = new TreeSet<Worker1>(new Comp());
//		添加元素
ts1.add(new Worker1("abc----01"));
ts1.add(new Worker1("abc----05"));
ts1.add(new Worker1("abc----03"));
ts1.add(new Worker1("abc----04"));

Iterator<Worker1> it1 = ts1.iterator();
while(it1.hasNext()){
System.out.println(it1.next().getName());
}
}
}
//比较器
class Comp implements Comparator<Person2>{
public int compare(Person2 s1,Person2 s2){
return s1.getName().compareTo(s2.getName());
}
}
//人
class Person2{
private String name;
Person2(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//学生类,并继承于人
class Student3 extends Person2{
Student3(String name){
super(name);
}
}
//工人类,并继承于人
class Worker1 extends Person2{
Worker1(String name){
super(name);
}
}


五、Map

Map集合:Map不同于Collection,Collection中存储的是单个元素,而Map中存储的是键值对,一对一对往里存储,并要保证唯一性

Map集合中的共性方法:

1、添加:put(K key, V value);putAll(Map<? extendsK, <? extends K> m);

2、删除:clear();remove(Object key);

3、判断:containsValue(Object value);containsKey(Objectkey);isEmpty();

4、获取:get(Object key);size();value();entrySet();keySet()。

实现Map接口的子类有很多,但重要的有Hashtable、HashMap、TreeMap三个。下面主要介绍这三个。

Hashtable:底层是哈希表数据结构,不可以存入null键null值,线程同步,效率低;

HashMap:底层是哈希表数据结构,允许使用null值和null键,线程不同步,效率高;

TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。

Map集合的两种取出方式:

1、keySet:将map中所有的键存入到Set集合,因为Set具备迭代器,所以可以迭代方式取出所有的键,再通过get()方法获取每一个键对应的值。

2、Set<Map.Entry<K,V>>:将map集合中的映射关系存入到set集合 中,而这个关系就是Map.Entey。Map.Entry:其实Entry也是 一个接口,它是Map接口中的一个内部接口。

总之:Set底层就是使用了Map集合;Map集合的取出原理:将map集合转成set集合,再通过迭代器取出

下面代码体现:

1、存储:学生Student对应一个地址String,姓名和年龄相同视为同一个学生

package itheima.day16;

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

//每个学生都有对应的归属地,学生Student,地址String,
// 		学生属性:姓名,年龄。注意:姓名和年龄相同视为同一个学生。
// 		要保证学生的唯一性
//思路:1描述学生
// 		2、定义map容器,学生作为键,地址作为值,存入
// 		3、获取map集合中的元素
public class MapTest {

public static void main(String[] args) {

HashMap<Student,String> hm = new HashMap<Student,String>();
hm.put(new Student("zhangsan01",21), "北京");
hm.put(new Student("zhangsan05",25), "上海");
hm.put(new Student("zhangsan03",23), "广州");
hm.put(new Student("zhangsan02",22), "南京");
hm.put(new Student("zhangsan06",26), "西安");
hm.put(new Student("zhangsan04",24), "桂林");
Set<Student> keySet = hm.keySet();

Iterator<Student> it = keySet.iterator();
while(it.hasNext()){
Student stu = it.next();
String addr = hm.get(stu);
System.out.println(stu+"::::"+addr);
}

}
}
class Student implements Comparable<Student>
{
private String name;
private int age;
Student(String name,int age){
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;
}
public String toString(){
return name+"::::"+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;
}

@Override
public int compareTo(Student o) {
int num = new Integer(this.age).compareTo(new Integer(o.age));
if(num ==0)
return this.getName().compareTo(o.getName());
return num;
}
}


2、对学生对象的姓名进行升序排序

package itheima.day16;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import itheima.day16.Student;

//需求:对学生对象的姓名进行升序排序,。
//  	因为数据是以键值对形式存在,所以要使用可以排序的Map集合,TreeMap
public class MapTest2 {

public static void main(String[] args) {

TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());
tm.put(new Student("zhangsan01",21), "北京");
tm.put(new Student("zhangsan005",25), "上海");
tm.put(new Student("zhangsan03",23), "广州");
tm.put(new Student("zhangsan002",22), "南京");
tm.put(new Student("zhangsan06",26), "西安");
tm.put(new Student("zhangsan004",24), "桂林");

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  stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+":::"+addr);
}
}
}

class StuNameComparator implements Comparator<Student>{
@Override
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;
}
}


3、获取一个字符串中字母出现的次数,希望打印结果为:a(1)b(2)...

package itheima.day16;

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

//练习:获取一个字符串中字母出现的次数,希望打印结果为:a(1)b(2)...
//思路:1、将字符串转换成字符数组,因为要对每一个字母进行操作;
//  	2、定义一个map集合,因为打印结果的字母有顺序,TreeMap;
// 		3、遍历字符数组,将每一个字母作为键去查map集合,如果返回null,
// 			存入;如果不是null,则对应的值加1。
// 		4、将map集合中的数据变成指定的字符串形式返回。
public class MapTest3 {

public static void main(String[] args) {

String str ="54653gfghfhvfagfgafsdg";
System.out.println(charCount(str));
}

public static String charCount(String str){
char[] chs = str.toCharArray();
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
int count =0;
for(int x=0;x<chs.length;x++){
if(!(chs[x]>='a'&& chs[x]<='z' || chs[x]>='A'&&chs[x]<='Z'))//非字母,不存
continue;
Integer value = tm.get(chs[x]);
if(value!=null)
count = value;
count++;
tm.put(chs[x], count);
count=0;
}
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 ch = me.getKey();
Integer value = me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: