- 集合的概念
- Collection接口
- Collection父接口
- List接口
- List实现类在这里插入代码片
- 泛型和工具类
- Set接口和实现类
- Map接口与实现类
- Collections工具类
对象的容器,定义了多个对象进行 *** 作的常用方法;可实现数组的功能
1.2集合和数组的区别- 1 数组的长度固定,集合长度不固定
- 2 数组可以存储基本类型和引用类型,集合只能存储引用类型
- 特点:代表一组应以类型的对象,无序、无下标、不能重复
- 方法
- boolean add (0bject obj) //添加一个对象。
- boolean addAl1 (Collection c) //将一个集合中的所有对象添加到此集合中。
- void clear() //清空此集合中的所有对象。
- boolean contains (Object o) //检查此集合中是否包含0对象
- boolean equals (object o) //比较此集合是否与指定对象相等。
- boolean isEmpty () //判断此集合是否为空
- boolean remove (0bject o) //在此集合中移除0对象
- int size() //返回此集合中的元素个数。
- Object[] toArray() //将此集合转换成数组。
public static void main(String[] args) { //创建集合 Collection collection = new ArrayList(); //1 添加元素 collection.add("西瓜"); collection.add("苹果"); collection.add("梨子"); System.out.println(collection.size());//打印集合长度 System.out.println(collection); //2 删除元素 // collection.remove("苹果"); //3 遍历元素 //3.1 增强for for (Object o : collection) { System.out.println(o); } System.out.println("---------------------"); //3.2 使用迭代器:专门用来遍历集合的方法(hasNext,next,remove) Iterator it = collection.iterator(); while (it.hasNext()){ String s = (String) it.next(); System.out.println(s); // collection.remove(s); //.ConcurrentModificationException 并发修改异常,迭代器中不能用Collection修改 // it.remove();//可以使用迭代器的方法删除 } //4 判断 System.out.println(collection.contains("西瓜"));//判断有没有元素西瓜 System.out.println(collection.isEmpty());//判断是否为空 }4、List子接口 特点:有序、有下标、元素可以重复
方法:
- 有序集合(也称为序列 )。 该界面的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。
- void add (int index, Object o) //在index位置插入对象0。
- boolean addAll (int index, Collection c) //将一个集合中的元素添加到此集合中的index位置。
- Object get (int index) //返回集合中指定位置的元素。
- List sublList (int fromIndex, int toIndex) //返回fromlndex和toIndex之间的集合元素。
public static void main(String[] args) { //创建集合对象 List list = new ArrayList(); //1 添加元素 list.add("小米"); list.add(0,"华为");//在第0处添加 list.add("水果"); System.out.println(list.toString());//[华为, 小米, 水果] //2 删除元素 list.remove(2); System.out.println(list.toString());//[华为, 小米] //3 遍历 //3.1 for for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i));//华为小米 } //3.2增强for for (Object o : list) { System.out.print(o);//华为小米 } System.out.println("_______________"); //3.3迭代器 Iterator it = list.iterator(); while (it.hasNext()){ System.out.print(it.next());//华为小米 } //3.4 listIterator列表迭代器,比Iterator强大,可以前后遍历,修改元素 ListIterator lt = list.listIterator(); while (lt.hasNext()){ System.out.println(lt.nextIndex()+":"+lt.next());//0:华为1:小米 } //从后往前 while (lt.hasPrevious()){ System.out.println(lt.previousIndex()+":"+lt.previous());//1:小米0:华为 } //4 判断 System.out.println(list.contains("华为"));//true System.out.println(list.isEmpty());//true //5 获取位置 System.out.println(list.indexOf("华为"));//0 }4.1、数字及subLIst
public static void main(String[] args) { List list = new ArrayList(); //1 添加数字(自动装箱)Integer包装类 list.add(20); list.add(30); list.add(40); list.add(50); list.add(60); System.out.println(list.toString()); //删除 // list.remove(0); // list.remove((Object) 20); // list.remove((Integer)20); // list.remove(new Integer(20));//数字 System.out.println(list.toString()); //subList 含头不含尾 List sublist = list.subList(1,3); System.out.println(sublist.toString());//[30, 40] }5、List实现类
- ArrayList(重点)
- 数组结构实现,查询快、增删慢
- jdk1.2版本,运行效率快、线程不安全
- Vector
- 数组结构实现,查询快、增删慢
- jdk1.0版本,运行慢,线程安全
- linkedList(常用)
- 链表结构实现,增删快,查询慢
- 链表首先有个head元素,添加元素,第一个就指向第二个元素以此类推
- 数组结构实现,查询快、增删慢
- 没有向集合中添加元素时,容量为0
- //数组容量超过10以后再添加元素,就扩容到原来的1,5倍,
- int newCapacity = oldCapacity + (oldCapacity >> 1);
public static void main(String[] args) { Student s1 = new Student("张三",22); Student s2 = new Student("李四",22); Student s3 = new Student("麻子",22); //创建集合 ArrayList arr = new ArrayList<>(); //1 添加 arr.add(s1); arr.add(s2); arr.add(s3); System.out.println(arr.toString()); System.out.println("_____________"); //2 删除 // arr.remove(s1); System.out.println(arr.toString()); System.out.println("_____________"); //3 遍历 //迭代器 Iterator it = arr.iterator(); while (it.hasNext()){ System.out.println(it.next()); } System.out.println("_____________"); //列表迭代器 ListIterator lit = arr.listIterator(); while (lit.hasNext()){ System.out.println(lit.next()); } System.out.println(lit.nextIndex()); System.out.println("_____________"); System.out.println(lit.previousIndex()); while (lit.hasPrevious()){ System.out.println(lit.previous()); } }ArrayList源码
//构造方法 public ArrayList() { //没有向集合中添加元素时,容量为0 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//空数组 } //添加元素 add public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } //add方法里的ensureCapacityInternal() //transient Object[] elementData; private void ensureCapacityInternal(int minCapacity) { // 10 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } //ensureCapacityInternal方法里的alculateCapacity private static int calculateCapacity(Object[] elementData, int minCapacity) { //elementData if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //Math.max()取最大值,(a >= b) ? a : b // 10 size+1 =1 return Math.max(DEFAULT_CAPACITY, minCapacity);//这里返回10 } return minCapacity; } //ensureCapacityInternal方法里的ensureExplicitCapacity private void ensureExplicitCapacity(int minCapacity) { //默认为0 modCount++;//1 // overflow-conscious code // 10 - 0 if (minCapacity - elementData.length > 0) // 10 grow(minCapacity); } //ensureExplicitCapacity方法里的grow,,核心 // 10 private void grow(int minCapacity) { // overflow-conscious code // 0 int oldCapacity = elementData.length; // 0 0 0 int newCapacity = oldCapacity + (oldCapacity >> 1); // 0 10 if (newCapacity - minCapacity < 0) // 10 newCapacity = minCapacity; // 10 ( Integer.MAX_VALUE - 8):很大 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: //空 空 10 elementData = Arrays.copyOf(elementData, newCapacity); //创建一个容量为10的数组 } //最后 0 传进来的元素 elementData[size++] = e; //添加元素到数组 //数组容量超过10以后再添加元素,就扩容到原来的1,5倍, int newCapacity = oldCapacity + (oldCapacity >> 1);5.2、Vector集合(不常用)
- Vector类实现了可扩展的对象数组。 像数组一样,它包含可以使用整数索引访问的组件。 但是, Vector的大小可以根据需要增长或缩小,以适应在创建Vector之后添加和删除项目。
public static void main(String[] args) { //创建集合 Vector vt = new Vector<>(); //1 添加元素 vt.add("苹果"); vt.add("草莓"); vt.add("西瓜"); System.out.println(vt.size());//3 //2 删除,remove //3 遍历 //for,增强for //jdk1.2之前,使用枚举器 Enumeration en = vt.elements(); while (en.hasMoreElements()){ System.out.println(en.nextElement()); } //4判断 System.out.println(vt.contains("西瓜")); System.out.println(vt.isEmpty()); //5 其他方法 vt.firstElement(); vt.lastElement(); vt.elements(); }5.3、linkedList
linkedList(常用)
- 链表结构实现,增删快,查询慢,双向链表
- 链表首先有个head元素,添加元素,第一个就指向第二个元素以此类推
public static void main(String[] args) { Student s1 = new Student("张三",22); Student s2 = new Student("李四",22); Student s3 = new Student("麻子",22); //创建元素 linkedList linkedList = new linkedList<>(); //1 添加元素 linkedList.add(s1); linkedList.add(s3); linkedList.add(s2); System.out.println(linkedList.toString()); //2 删除 // linkedList.remove(s1); //3 遍历 //for // for (int i = 0; i < linkedList.size(); i++) { // System.out.println(linkedList.get(i)); // } //增强for // for (Object o : linkedList) { // System.out.println(o); // } //迭代器 // Iterator it = linkedList.iterator(); // while (it.hasNext()){ // System.out.println(it.next()); // } //列表迭代器 ListIterator lt = linkedList.listIterator(); while (lt.hasNext()){ System.out.println(lt.next().toString()); } //4 判断 System.out.println(linkedList.contains(s1)); System.out.println(linkedList.isEmpty()); //5 获取 System.out.println(linkedList.indexOf(s1));//获取下标 }linkedList 源码
- size = 0
- first 头 last 尾
- 前一个指向后一个,后一个指向前一个
//构造方法空 public linkedList() { } //add方法 public boolean add(E e) { linkLast(e); return true; } //linkLast(e); void linkLast(E e) { // null final Node5.4 ArrayList和linkedList的区别l = last; // null 元素 final Node newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } //Node private static class Node { //item当前元素 E item; //下一个节点 Node next; //前一个节点 Node prev; Node(Node prev, E element, Node next) { this.item = element; this.next = next; this.prev = prev; } }
- linkedList
- 查询慢:需要从头或从尾一个个找
- 删除快:删除一个元素,只需要改变指向关系就可以了
- nextIndex()默认是0,previousIndex() : nextIndex()-1 = -1
- 直接逆遍历需要先把遍历一次,让nextIndex()到最后一位
ListIterator lit = arr.listIterator(); //正向遍历 while (lit.hasNext()){ System.out.println(lit.next()); } System.out.println(lit.nextIndex());//3 System.out.println(lit.previousIndex());//2 while (lit.hasPrevious()){ System.out.println(lit.previous()); } //注释掉正向遍历后 // while (lit.hasNext()){ // System.out.println(lit.next()); // } System.out.println(lit.nextIndex());//0 System.out.println("_____________"); System.out.println(lit.previousIndex());//-1 while (lit.hasPrevious()){//就不能遍历了 System.out.println(lit.previous()); } //可以在逆向遍历之前正向遍历一遍解决6、泛型
- Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
- 常见形式有泛型类、泛型接口、泛型方法。
- 语法:
- .
T称为类型占位符,表示一种引用类型。
- .
- 好处:
- (1)提高代码的重用性:比如传递时可以传递任意类型的参数
- (2)防止类型转换异常,提高代码的安全性
- 语法,类名
- T是类型占位符,表示一种引用类型,如果编写多个使用逗号隔开
- 泛型只能使用引用类型
- 不同泛型类型对象之间不能相互赋值
public class MyGeneric6.2、泛型接口{ //使用泛型T //1 创建变量 T t; //2 泛型作为方法的参数 public void show(T t){ System.out.println(t); } //3泛型的方法的返回值 public T getT() { return t; } } public static void main(String[] args) { //使用泛型类创建变量 //注意,1 泛型只能使用引用类型,2 不同泛型类型对象之间不能相互赋值 MyGeneric myGeneric = new MyGeneric (); myGeneric.t = "hello"; myGeneric.show("大家好");//大家好 String str = myGeneric.getT(); System.out.println(str);//hello MyGeneric myGeneric1 = new MyGeneric (); myGeneric1.t = 100; myGeneric1.show(200);//200 Integer integer = myGeneric1.getT(); System.out.println(integer);//100 }
- 定义泛型接口,接口名
- 注意:不能用泛型创建常量
- 实现类
- 1:可以在实现类上泛型直接指定类型,方法使用对应类型
- 2:实现类泛型不指定类型,使用的时候再指定
例子:
public interface MyInterface6.3、泛型方法{ String name = "张三"; T server(T t); } //实现类1 指定类型 public class MyInterfaceImpl implements MyInterface { @Override public String server(String t) { System.out.println(t); return t; } } //实现类2 不指定类型 public class MyInterfaceImpl2 implements MyInterface { @Override public T server(T t) { System.out.println(t); return t; } } //测试 public static void main(String[] args) { MyInterfaceImpl impl1 = new MyInterfaceImpl(); impl1.server("ttttttttttttt");//tttttttttt MyInterfaceImpl2 impl2 = new MyInterfaceImpl2<>(); impl2.server(2020);//2020 }
- 语法,方法返回值类型前加:public void show(){}、
- 传递的类型是由传递的值决定
//泛型方法 public6.4、泛型集合 概念:T show(T t){ System.out.println("泛型方法"+t); return t; } //调用 //泛型方法 MyGenericMethod mg = new MyGenericMethod(); //传递的类型是由传递的值决定 mg.show(222); mg.show("行啊");
- 参数化类型、类型安全的集合,强制集合元素的类型必须一致
- 编译时即可检查,而非运行时抛出异常
- 访问时,不需要类型转换(拆箱)
- 不同泛型之间引用不能相互赋值,泛型不存在多态
public static void main(String[] args) { ArrayList7、Set子接口 特点:arrayList = new ArrayList(); arrayList.add("aaa"); arrayList.add("bbb"); for (String s : arrayList) { String ss = s; System.out.println(ss); } Student s1 = new Student("aaa",11); Student s2 = new Student("bbb",22); ArrayList arrayList1 = new ArrayList<>(); arrayList1.add(s1); arrayList1.add(s2); Iterator it = arrayList1.iterator(); while (it.hasNext()){ //添加泛型指定Student类型后,获取的也是Student类型 Student st = it.next(); System.out.println(st); } }
- 无序、无下标、元素不可以重复
- 全部继承Collection的方法
public static void main(String[] args) { //创建集合 Set7.1、Set实现类(HashSet)set = new HashSet<>(); //1 添加数据 set.add("苹果"); set.add("西瓜"); set.add("香蕉"); System.out.println(set.toString());//[苹果, 香蕉, 西瓜] //2 删除 // set.remove("香蕉"); //3 遍历 //增强for for (String s : set) { System.out.println(s); } //迭代器 Iterator it = set.iterator(); while (it.hasNext()){ System.out.println(it.next()); } }
-
基于HashCode计算元素存放位置
-
当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,,则拒绝后者存入
-
存储过程
- 根据hashcode计算保存位置,如果位置为空,直接保存,如果不为空执行第二步
- 执行equals,如果equals为true,认为是重复,否则形成链表
public static void main(String[] args) { //创建集合 HashSet7.2、TreeSet 特点:hashSet = new HashSet<>(); //添加数据 Person s1 = new Person("张三",11); Person s2 = new Person("麻子",22); Person s3 = new Person("蓝色",33); hashSet.add(s1); hashSet.add(s2); hashSet.add(s3); hashSet.add(new Person("张三",11));//是不同对象可以添加 //重写hashcode,和equals后相同元素就不能添加了 System.out.println(hashSet); //删除 // hashSet.remove(s1); //重写hashcode,和equals后相同元素就不能删除了 hashSet.remove(new Person("张三",11)); }
- 基于排序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
@Override //Person类:实现Comparable接口,重新compareTo()方法 //先比姓名再比年龄 public int compareTo(Person o) { int n1 = this.getName().compareTo(o.getName()); int n2 = this.age-o.getAge(); return n1==0?n2:n1; } public class Demo2 { public static void main(String[] args) { TreeSet自定义比较规则person = new TreeSet<>(); //1 添加元素 Person p1 = new Person("xyz",18); Person p2 = new Person("aaa",33); Person p3 = new Person("ddd",22); Person p4 = new Person("ddd",20); person.add(p1); person.add(p2); person.add(p3); person.add(p4); System.out.println(person); //2 删除元素 person.remove(new Person("ddd",20)); //3 遍历 //增强for //迭代器 }
- 先比年龄,再比姓名
public static void main(String[] args) { //内部类 TreeSetts = new TreeSet<>(new Comparator () { @Override //先比年龄,再比姓名 public int compare(Person o1, Person o2) { int n1 = o1.getAge()-o2.getAge(); int n2 = o1.getName().compareTo(o2.getName()); return n1 == 0 ? n2:n1 ; } }); Person p1 = new Person("xyz",18); Person p2 = new Person("aaa",33); Person p3 = new Person("ddd",22); Person p4 = new Person("ddd",20); ts.add(p1); ts.add(p2); ts.add(p3); ts.add(p4); System.out.println(ts); }
- 字符串按长度进行排序
public static void main(String[] args) { TreeSet8、Map集合 8.1、Map父接口 特点:ts = new TreeSet<>(new Comparator () { @Override //长度从长往短排 public int compare(String o1, String o2) { int n1 = o2.length()-o1.length(); int n2 = o1.compareTo(o2); return n1==0 ? n2:n1; } }); ts.add("sidfhkajlsdhfj"); ts.add("aaas"); ts.add("bbb"); ts.add("cccds"); ts.add("caaas"); System.out.println(ts); //[sidfhkajlsdhfj, caaas, cccds, aaas, bbb] }
- 存储一对数据(Key-Value),无序、无下标,键不可重复,值可以重复
- V put (K key, V value) //将对象存入到集合中,关联键值。key重复则覆盖原值。
- Object get (object key) //根据键获取对应的值。
- KeySet //返回所有key。
- Collection values () //返回包含所有值的Collection集合。
- Set
> //键值匹配的Set集合。 - entrySet() 返回此映射中包含的映射关系的Set视图。
public static void main(String[] args) { Map8.1、HashMap*map = new HashMap<>(); //1 添加 map.put("pg","苹果"); map.put("xg","西瓜"); map.put("xj","香蕉"); System.out.println(map.size()+":"+map); //2 删除 // map.remove("xg"); // System.out.println(map.size()+":"+map); //3 遍历 // 1 keySet // Set s = map.keySet(); for (String s1 : map.keySet()) { System.out.println(s1+":"+map.get(s1)); } // 2 使用entrySet()遍历 // Set > entries = map.entrySet(); // for (Map.Entry entry : entries) { for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey()+":"+entry.getValue()); } //4 判断 System.out.println(map.containsValue("西瓜")); System.out.println(map.isEmpty()); }
-
JDK1.2支持,线程不安全,运行效率快;允许使用null作为key或Value
-
构造方法
-
HashMap() 构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。
-
HashMap(int initialCapacity) 构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。
-
HashMap(int initialCapacity, float loadFactor) 构造一个空的 HashMap具有指定的初始容量和负载因子。
-
HashMap(Map extends K,? extends V> m) 构造一个新的 HashMap与指定的相同的映射 Map
-
基于哈希表的实现的Map接口。 此实现提供了所有可选的地图 *** 作,并允许null的值和null键。 ( HashMap类大致相当于Hashtable ,除了它是不同步的,并允许null)。这个类不能保证地图的顺序; 特别是,它不能保证订单在一段时间内保持不变。
public static void main(String[] args) { HashMapHashMap小结:hm = new HashMap<>(); //添加元素 Student s1 = new Student("孙悟空",100); Student s2 = new Student("猪八盖",101); Student s3 = new Student("沙僧",102); hm.put(s1,"贵阳"); hm.put(s2,"金阳"); hm.put(s3,"火车站"); hm.put(new Student("沙僧",102),"北站");//hashcode不同可以添加,可以通过重新hashcode和equals System.out.println(hm.size()+":"+hm); //2 删除 remove //3 遍历 // KeySet for (Student student : hm.keySet()) { System.out.println(student+":"+hm.get(student)); } //entrySet for (Map.Entry studentStringEntry : hm.entrySet()) { System.out.println(studentStringEntry.getKey()+":"+studentStringEntry.getValue()); } }
- 刚创建集合时集合的长度为0,(节省空间)
- (put)添加数据时集合长度调整为16(0-15)
- 当数据个数达到阈值(16*0.75)12时,扩容为原来的两倍,32(16的二倍)
- jdk1.8当每个链表长度大于8,并且元素个数大于等于64时,会调整为红黑树,日的提高执行效率
- jdk1.8当链表长度小于6时,调整成链表
- jdk 1.8以前,链表时头插入, jdk1.8以后时是尾插入
- HashSet实际上使用的是HashMap的Key
- JDK1.0版本,线程安全,运行效率慢,键值不允许为null
- 子类:Properties
- 要求键值都是String,通常用于配置文件的读取
- 实现了sort
- 结构:红黑树
public static void main(String[] args) { TreeMapTreeSet 和TreeMaptm = new TreeMap<>(new Comparator () { @Override public int compare(Student o1, Student o2) { int n1 = o1.getStuNo()-o2.getStuNo(); return n1; } }); //1.添加对象 Student s1 = new Student("孙悟空",100); Student s2 = new Student("猪八盖",101); Student s3 = new Student("沙僧",102); tm.put(s1,"北京"); tm.put(s2,"上海"); tm.put(s3,"深圳"); System.out.println(tm.size()+":"+tm); tm.put(new Student("沙僧1",102),"南京");//替换了value System.out.println(tm.size()+":"+tm); //2 删除,remove //3 遍历 //keySet for (Student student : tm.keySet()) { System.out.println(student+":"+tm.get(student)); } //entrySet for (Map.Entry entry : tm.entrySet()) { System.out.println(entry.getKey()+":"+entry.getValue()); } //4 判断,containsKey,IsEntry }
- TreeSet使用的TreeMap的key
- 集合工具类,定义了除了存取以外的集合常用方法。
- 方法:
- public static void reverse(List> list) //反转集合中元素的顺序
- public static void shuffle(List> list) //随机重置集合元素的顺序
- public static void sort (List list) //升序排序(元素类型必须实现Comparable接口)
public static void main(String[] args) { List数组集合转换list = new ArrayList<>(); list.add(22); list.add(5); list.add(2); list.add(44); list.add(11); //sort 排序 默认升序 Collections.sort(list); System.out.println(list);//[2, 5, 11, 22, 44] //binarySearch 二分查找(先排序) ,有就返回下标,没有返回负数 int i = Collections.binarySearch(list,444);//-6 System.out.println(i); //copy复制 List list1 = new ArrayList<>(); //copy方法复制的对象没有长度会报异常IndexOutOfBoundsException for (int j = 0; j < list.size(); j++) { //先赋值0 list1.add(0); } Collections.copy(list1,list); System.out.println(list1);//[2, 5, 11, 22, 44] //reverse反转 Collections.reverse(list); System.out.println(list);//[44, 22, 11, 5, 2] //shuffle 打乱,每次都不一样 Collections.shuffle(list); System.out.println(list);//[22, 2, 5, 11, 44] }
//list转成数组,长度和list长度一样 Integer[] it = list.toArray(new Integer[0]); System.out.println(it.length+":"+ Arrays.toString(it));//5:[11, 44, 5, 2, 22] //把数组转成集合 ,创建的时候固定了长度,不能添加或删除,可以修改 String[] names = {"aaa","bbb","ddd","FFF"}; Listlist2 = Arrays.asList(names); //出现异常UnsupportedOperationException // list2.add("sss"); System.out.println(list2);//[aaa, bbb, ddd, FFF] //基本类型数组转集合时需要写包装类型 Integer[] nums = {111,222,33,44,55}; List integers = Arrays.asList(nums); System.out.println(integers);//[111, 222, 33, 44, 55]
小问题
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)