首页 技术 正文
技术 2022年11月10日
0 收藏 769 点赞 3,296 浏览 17626 个字

一、概述

JAVA集合框架中有两个很重要的工具类,一个是Collections,另一个是Arrays。分别封装了对集合的操作方法和对数组的操作方法,这些操作方法使得程序员的开发更加高效。

public class Collections extends Object      全类名:java.util.Collections 
public class Arrays extends Object           全类名:java.util.Arrays 

二.Collections类。

1.Collections.sort方法。

public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> void sort(List<T> list, Comparator<? super T> c)

(1)示例。

现在有一些字符串,可能有重复元素,想要将它们存入一个容器中并按照一定的规则进行排序,该怎么做?

思路:使用ArrayList集合进行存储并使用Collections.sort方法进行排序。

 package p01.ColletionsDemo.p01.SortDemo; import java.util.ArrayList;
import java.util.Collections; public class SortDemo { public static void main(String[] args) {
Demo1(); }
private static void Demo1() {
ArrayList<String>al=new ArrayList<String>();
al.add("abc");
al.add("bca");
al.add("aab");
al.add("bac");
al.add("cba");
System.out.println("排序前:"+al);
Collections.sort(al);
System.out.println("排序后:"+al);
} }

这是按照字符串的自然排序方式排序的代码,即输出结果的字符串是按照字典序排序的。

现在有了新的需求,即按照字符串长度排序,如果字符串长度相同按照字典序排序,这时候需要使用比较器。

 package p01.ColletionsDemo.p01.SortDemo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; public class SortDemo {
public static void main(String[] args) {
//Demo1();
Demo2();
}
/*
* Demo2:该方法采用带比较器的Collections.sort方法
*/
private static void Demo2() {
ArrayList<String>al=new ArrayList<String>();
al.add("abcd");
al.add("abc");
al.add("bc");
al.add("aabadsf");
al.add("b");
al.add("cbae");
al.add("bade");
System.out.println("排序前:"+al);
Collections.sort(al,new ComparatorByLength());
System.out.println("排序后:"+al);
}
/*
* Demo1:该方法使用的是不带比较器的Collections.sort方法。
*/
private static void Demo1() {
ArrayList<String>al=new ArrayList<String>();
al.add("abc");
al.add("abc");
al.add("bca");
al.add("aab");
al.add("bac");
al.add("cba");
System.out.println("排序前:"+al);
Collections.sort(al);
System.out.println("排序后:"+al);
} }
class ComparatorByLength implements Comparator<String>
{ @Override
public int compare(String o1, String o2) {
int temp=o1.length()-o2.length();
return temp==0?o1.compareTo(o2):temp;
} }

两个重载方法使用起来非常方便,但是其实现原理是什么也需要了解。

(2)模拟不使用比较器的sort方法。

 package p01.ColletionsDemo.p02.SortDemo; import java.util.ArrayList;
import java.util.List; class Person implements Comparable<Person>
{ private String name;
private int age;
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]\n";
}
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 Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public int compareTo(Person o) {
int temp=this.age-o.getAge();
return temp==0?this.name.compareTo(o.getName()):temp;
}
}
class Student extends Person
{ public Student() {
super();
} public Student(String name, int age) {
super(name, age);
} }
class Worker extends Person
{ public Worker() {
super();
} public Worker(String name, int age) {
super(name, age);
} } public class SortDemo {
/**
* 该类模拟带不带比较器的Collections.sort方法。
* @param args
*/
public static void main(String[] args) { Demo1();
} private static void Demo1() {
ArrayList<Person>al=new ArrayList<Person>();
al.add(new Person("lisi",24));
al.add(new Person("wangwu",25));
al.add(new Person("zhangsan",23));
al.add(new Person("chenqi",27));
al.add(new Person("zhaoliu",26)); System.out.println("排序前:"+al);
MyCollections.sort(al);
System.out.println("排序后:"+al);
} }
/*
* 使用自定义Collections类
*/
class MyCollections
{
public static <T extends Comparable<? super T>> void sort(List <T>list)
{
for(int i=0;i<=list.size()-2;i++)
{
for(int j=i+1;j<=list.size()-1;j++)
{
if( list.get(i).compareTo(list.get(j))>0)
{
T t=list.get(i);
list.set(i, list.get(j));
list.set(j, t);
}
}
}
}
}

改程序的核心就是MyColletions类了:

 class  MyCollections
{
public static <T extends Comparable<? super T>> void sort(List <T>list)
{
for(int i=0;i<=list.size()-2;i++)
{
for(int j=i+1;j<=list.size()-1;j++)
{
if( list.get(i).compareTo(list.get(j))>0)
{
T t=list.get(i);
list.set(i, list.get(j));
list.set(j, t);
}
}
}
}
}

(3)模拟使用比较器的sort方法。

 package p01.ColletionsDemo.p03.SortDemo; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator; class Person implements Comparable<Person>
{ private String name;
private int age;
@Override
public String toString() {
return "name="+name + ", age=" + age +"\n";
}
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 Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public int compareTo(Person o) {
int temp=this.age-o.getAge();
return temp==0?this.name.compareTo(o.getName()):temp;
}
}
class Student extends Person
{ @Override
public String toString() {
return super.toString() ;
} public Student() {
super();
} public Student(String name, int age) {
super(name, age);
} }
class Worker extends Person
{ @Override
public String toString() {
return super.toString();
} public Worker() {
super();
} public Worker(String name, int age) {
super(name, age);
} } public class SortDemo {
/**
* 该类模拟带不带比较器的Collections.sort方法。
* @param args
*/
public static void main(String[] args) { // Demo1();
// Demo2();
Demo3();
} private static void Demo3() {
ArrayList<Student>al=new ArrayList<Student>();
al.add(new Student("lisi",24));
al.add(new Student("wangwu",25));
al.add(new Student("zhangsan",23));
al.add(new Student("chenqi",27));
al.add(new Student("zhaoliu",26)); System.out.println("排序前:"+al);
MyCollections_1.sort(al,new ComparatorByLength());
//Collections.sort(al, new ComparatorByLength());
System.out.println("排序后:"+al);
} private static void Demo1()
{
ArrayList<Person>al=new ArrayList<Person>();
al.add(new Student("lisi",24));
al.add(new Person("wangwu",25));
al.add(new Worker("zhangsan",23));
al.add(new Person("chenqi",27));
al.add(new Person("zhaoliu",26)); System.out.println("排序前:"+al); System.out.println("排序后:"+al);
} }
class MyCollections_1
{
public static <T> void sort(List <T>list,Comparator<? super T> c)
{
Object [] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++)
{
i.next();
i.set(a[j]);
}
}
}
class ComparatorByLength implements Comparator<Person>
{
@Override
public int compare(Person o1, Person o2) {
int temp=o1.getName().length()-o2.getName().length();
return temp==0?o1.getName().compareTo(o2.getName()):temp;
}
}

改造程序的核心是:

 class  MyCollections_1
{
public static <T> void sort(List <T>list,Comparator<? super T> c)
{
Object [] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++)
{
i.next();
i.set(a[j]);
}
}
}
class ComparatorByLength implements Comparator<Person>
{
@Override
public int compare(Person o1, Person o2) {
int temp=o1.getName().length()-o2.getName().length();
return temp==0?o1.getName().compareTo(o2.getName()):temp;
}
}

其实,Collectios.sort方法的实质就是将集合转换成数组,然后使用Arrays工具类的sort方法进行排序,最后根据排序结果修改原集合。

2.Collections.binarySearch方法。

public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key)
public static <T> int binarySearch(List<? extends T> list,T key,Comparator<? super T> c)

这两个方法中,前者是不带比较器的二分查找方法,后者是带着比较器的二分查找方法。

既然是二分查找法,那么集合中的元素必然是有序的;如果元素不带有比自然比较的属性,则必须使用比较器,否则元素必须具备自然比较的属性,即实现了Comparable接口。

(1)简单的使用方法(不带比较器)演示

 package p02.ColletionsDemo.p01.BinarySearchDemo; import java.util.ArrayList;
import java.util.Collections; public class BinarySearchDemo { public static void main(String[] args) {
Demo01();
Demo02();
}
/**
* 没经过排序的集合使用二分查找法
*/
private static void Demo02() {
ArrayList<String>al=new ArrayList<String>();
al.add("abc");
al.add("dabdc");
al.add("cd");
al.add("bac");
al.add("ba");
System.out.println(al);
int index=Collections.binarySearch(al, "ba");
System.out.println(index);
}
/**
* 经过排序的集合使用二分查找法
*/
private static void Demo01() {
ArrayList<String>al=new ArrayList<String>();
al.add("abc");
al.add("dabdc");
al.add("cd");
al.add("bac");
al.add("ba");
Collections.sort(al);
System.out.println(al);
int index=Collections.binarySearch(al, "ba");
System.out.println(index);
} }

如果没有找到关键字,则会返回一个负数,该负数是如果将该数插入集合应当插入的位置*-1-1。减一的目的是为了防止应当插入的位置是0。

(2)复杂的使用方法演示(存放自定义对象,并使用了自定义比较器)

 package p02.ColletionsDemo.p02.BinarySearchDemo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; class Person implements Comparable<Person>
{
public String name;
public int age; @Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]\n";
} public Person(String name, int age) {
super();
this.name = name;
this.age = age;
} public Person() {
super();
} @Override
public int compareTo(Person o) {
int temp=this.age-o.age;
return temp==0?this.name.compareTo(o.name):temp;
}
}
public class BinarySearchDemo {
public static void main(String[] args) {
Demo01(); /*
* 按照名字的字典序排序,并查找,如果名字相同,则按照年龄排序
*/
Demo02();
} /*
* 使用带比较器的二分查找方法
*/
private static void Demo02() {
ArrayList<Person>al=new ArrayList<Person>();
al.add(new Person("zhaoliu",26));
al.add(new Person("lisi",24));
al.add(new Person("zhangsan",23));
al.add(new Person("wangwu",25));
al.add(new Person("wangwu",23));
al.add(new Person("wangwu",22));
al.add(new Person("wangwu",21));
Collections.sort(al,new ComparatorByName());
System.out.println(al);
int index=Collections.binarySearch(al,new Person("wangwu",25),new ComparatorByName());
System.out.println(index);
} /*
* 不使用带比较器的二分查找方法。
*/
private static void Demo01() {
ArrayList<Person>al=new ArrayList<Person>();
al.add(new Person("zhaoliu",26));
al.add(new Person("lisi",24));
al.add(new Person("zhangsan",23));
al.add(new Person("wangwu",25));
al.add(new Person("wangwu",23));
al.add(new Person("wangwu",22));
al.add(new Person("wangwu",21));
Collections.sort(al);
System.out.println(al);
int index=Collections.binarySearch(al,new Person("wangwu",25));
System.out.println(index);
} }
class ComparatorByName implements Comparator<Person>
{
@Override
public int compare(Person o1, Person o2) {
int temp=o1.name.compareTo(o2.name);
return temp==0?o1.age-o2.age:temp;
} }

 3.最大值最小值方法。

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp)
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
public static <T> T min(Collection<? extends T> coll,Comparator<? super T> comp)
 package p03.ColletionsDemo.p01.MaxMainDemo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; public class MaxMinDemo { public static void main(String[] args) {
Demo01(); } private static void Demo01() {
ArrayList<String>al=new ArrayList<String>();
al.add("bcade");
al.add("abc");
al.add("baefgh");
al.add("b");
/*
* 按照默认比较方式进行比较
*/
String max=Collections.max(al);
String min=Collections.min(al);
System.out.println("max="+max);
System.out.println("min="+min); System.out.println();
/*
* 更改比较方式,按照长度进行比较
*/
ComparatorByStringLength cbsl=new ComparatorByStringLength();
String max_1=Collections.max(al,cbsl);
String min_1=Collections.min(al,cbsl);
System.out.println("max="+max_1);
System.out.println("min="+min_1);
} }
/*
* 按照长度进行比较
*/
class ComparatorByStringLength implements Comparator<String>
{
@Override
public int compare(String o1, String o2) {
int temp=o1.length()-o2.length();
return temp==0?o1.compareTo(o2):temp;
}
}

4.反转和逆序。

public static void reverse(List<?> list)
public static <T> Comparator<T> reverseOrder()
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
 package p04.ColletionsDemo.p01.ReverseOrderDemo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; public class ReverseOrderDemo { public static void main(String[] args) {
//直接得到逆序的比较器从而将结果逆序。
Demo01();
//将比较器逆序从而将结果逆序。
Demo02();
} /*
* 按照长度进行排序(自定义比较器)并逆序
*/
private static void Demo02() {
ArrayList<String>al=new ArrayList<String>();
al.add("defefe");
al.add("edfef");
al.add("abce");
al.add("ba");
al.add("ab");
ComparatorByStringLength cbsl=new ComparatorByStringLength();
Collections.sort(al,cbsl);
System.out.println(al);
Collections.sort(al,Collections.reverseOrder(cbsl));//实现比较器的逆序。
System.out.println(al);
} private static void Demo01() {
ArrayList<String>al=new ArrayList<String>();
al.add("defefe");
al.add("edfef");
al.add("abce");
al.add("ba");
al.add("ab");
Collections.sort(al);
System.out.println(al);
Collections.sort(al,Collections.reverseOrder());//实现逆序
System.out.println(al);
}
}
/*
* 按照长度进行比较
*/
class ComparatorByStringLength implements Comparator<String>
{
@Override
public int compare(String o1, String o2) {
int temp=o1.length()-o2.length();
return temp==0?o1.compareTo(o2):temp;
}
}

5.替换。

public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal)

使用这个方法的时候如果List中存放的是自定义对象,则应当复写equals方法。

 package p05.ColletionsDemo.p01.ReplaceAllDemo; import java.util.ArrayList;
import java.util.Collections; class Person
{
public String name;
public int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public String toString() {
return "name=" + name + ", age=" + age + "\n";
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
* 如果想要使用Collections.repalceAll方法,则必须复写自定义对象的equals方法。
*/
@Override
public boolean equals(Object obj) {
Person p=(Person)obj;
return this.age==p.age&&this.name==p.name?true:false;
}
} public class ReplaceAllDemo { public static void main(String[] args) {
Demo01();
} private static void Demo01() {
ArrayList<Person>al=new ArrayList<Person>();
al.add(new Person("zhangsan",23));
al.add(new Person("lisi",24));
al.add(new Person("wangwu",25));
al.add(new Person("zhaoliu",26)); System.out.println(al);
Collections.replaceAll(al, new Person("zhangsan",23),new Person("chenqi",27));
System.out.println(al);
} }

6.最重要的问题:同步集合的问题。

Colletions类中提供了几种方法可以将非同步的集合转变成同步集合,这是为了满足在多线程环境下编程的需求。

public static <T> Collection<T> synchronizedCollection(Collection<T> c)
public static <T> List<T> synchronizedList(List<T> list)
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
public static <T> Set<T> synchronizedSet(Set<T> s)
public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)

下面的代码实现了自定义同步集合以及使用上述方法生成的同步集合,两种方法相比较,很明显,使用工具类能够大大提高效率。注意自定义集合中泛型的使用。

 package p07.ColletionsDemo.p01.SynchronizedFunctionDemo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List; public class SynchronizedFunctionDemo { public static void main(String[] args) {
Demo01();//自定义同步集合 Demo02();//使用Collecionts.xxx得到同步的集合
} private static void Demo02() {
/*
* 使用Collections提供的方法则要简单的多。
*/
List<String>list=Collections.synchronizedList(new ArrayList<String>());
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.remove("lisi");
Iterator<String>it=list.iterator();
while(it.hasNext())
{
String str=it.next();
System.out.println(str);
}
} private static void Demo01() {
MyList <String>list=new MyList<String>(new ArrayList<String>());
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.remove("lisi");
Iterator<String>it=list.iterator();
while(it.hasNext())
{
String str=it.next();
System.out.println(str);
}
}
} /*
* 该类将List集合转换成同步的List集合,需要重新写许多方法,非常麻烦
*/
class MyList<E>
{
private List<E> list;
private final Object obj=new Object();
public MyList(){}
public MyList(List<E> list)
{
this.list=list;
}
public boolean add(E obj)
{
synchronized(obj)
{
return this.list.add(obj);
}
}
public boolean remove(E obj)
{
synchronized(obj)
{
return this.list.remove(obj);
}
}
public Iterator<E> iterator()
{
/*
* 没有涉及到元素的删除和添加就不加同步。
*/
return this.list.iterator();
}
}

7.其它方法。

public static <T> Enumeration<T> enumeration(Collection<T> c)
public static <T> ArrayList<T> list(Enumeration<T> e)
public static <T> void fill(List<? super T> list,T obj)
public static void shuffle(List<?> list)
public static void shuffle(List<?> list,Random rnd)

下面只演示前两个方法:

 package p06.ColletionsDemo.p01.EnumerationAndListDemo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector; public class EnumerationAndListDemo { public static void main(String[] args) {
Demo01();
Demo02();
} private static void Demo02() {
Vector<String>v=new Vector<String>();
v.add("张三");
v.add("李四");
v.add("王五");
v.add("赵六"); ArrayList<String>al=Collections.list(v.elements());//两点在这一行
Iterator<String>it=al.iterator();
while(it.hasNext())
{
String str=it.next();
System.out.println(str);
} } public static void Demo01() {
ArrayList<String>list=new ArrayList<String>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoliu");
Enumeration<String> e=Collections.enumeration(list);
while(e.hasMoreElements())
{
String str=e.nextElement();
System.out.println(str);
}
} }

三、Arrays类。

1.toString方法。

public static String toString(int[] a)

上述的方法只是一个例子,该方法由多种重载形式。可以接受的参数包括各种基本数据类型。

功能是返回指定数组内容的字符串表示形式。

 package p08.ArraysDemo.p01.ToStringDemo; import java.util.Arrays; public class ToStringDemo {     public static void main(String[] args) {
Demo01();
}
private static void Demo01() {
int[]arr=new int[10];
for(int i=0;i<arr.length;i++)
{
arr[i]=i;
}
String str=Arrays.toString(arr);
System.out.println(str);
} }

该方法的使用方法很简单,但是我们应当注意其源码的实现形式,特别是对for循环的处理,是很值得借鉴的地方

  public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]"; StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}

上述代码中的for循环没有判断条件,这样就大大提高了代码效率。

2.asList方法。

public static <T> List<T> asList(T... a)

该方法使用了可变参数,这点应当注意。功能是返回一个受指定数组支持的固定大小的列表,也就是将数组转换成集合的方法。该方法的目的是使用更多的方法对数组的元素进行操作,毕竟数组中的方法并不多,即使有了Arrays方法也还是不够,如果能转换成集合进行操作,将能够使用更多更有效的方法,比如contains方法等。

 package p09.ArraysDemo.p01.AListDemo; import java.util.Arrays;
import java.util.List; public class AlistDemo { public static void main(String[] args) {
Demo01();
Demo02();
} /**
* 如果数组存放基本数据类型,则转变成集合之后存放的是数组的引用
*/
private static void Demo02() {
int arr[]=new int[10];
for(int i=0;i<arr.length;i++)
{
arr[i]=i;
}
List<int[]>list_1=Arrays.asList(arr);
System.out.println(list_1); Integer arr_1[]=new Integer[10];
for(int i=0;i<arr.length;i++)
{
arr_1[i]=i;
}
List<Integer>list_2=Arrays.asList(arr_1);
System.out.println(list_2);
} /**
* 如果数组内存放对象,则存放的是一个个对象的内容
*/
private static void Demo01() {
String arr[]=new String[10];
for(int i=0;i<arr.length;i++)
{
arr[i]=i+"";
}
List<String>list=Arrays.asList(arr);
System.out.println(list);
} }

注意,虽然该方法可以将数组转换成集合,但是不能进行增删操作,否则会有异常产生,这是因为数组就是数组的长度是不可变的。

3.集合转数组的方法:toArray。

集合转换成数组的目的一般就是减小对元素的操作权限,比如不允许增删操作了。

 package p10.ArraysDemo.p01.ListToArr; import java.util.ArrayList; public class ListToArr {     public static void main(String[] args) {
Demo01();
} private static void Demo01() {
ArrayList <Integer>list=new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
System.out.println(list);
Integer []arr=list.toArray(new Integer[list.size()]);//将集合转变成数组,注意类型应当匹配,否则会抛出ArrayStoreException异常。
System.out.println(arr);
for(int i=0;i<arr.length;i++)
{
System.out.println(arr[i]);
}
} }
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,077
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,552
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,400
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,176
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,813
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,895