首先看到Collections,是不是想到Collection,他俩很相似,就多了个s,那他们有什么区别呢?
1.Collection是集合的顶层接口,本身是一个Interface接口,里面包含了一些集合的基本操作,需要实例化Collection下的list、set、map、vector接口才能调用里面的方法。
2.Collections是集合框架的工具类,里面包含一些对集合的排序,搜索以及序列化的操作,内部的方法都是静态的,没有构造方法,不能实例化,要调用内部方法直接用类名调用(Collections.sort),并且Collections类服务于Collection框架。
好了,既然知道区别了就可以开始好好学习Collections类。
1.介绍一下Collections类
简单来说,Collections 类是Java中集合的工具类,服务于Collection框架,不能实例化。Collections 类中的方法都是静态方法,位于java.util包中。
2.Collections中常用的静态方法
1.public static void shuffle(List<?> list)
作用:打乱集合顺序。
2.public static <T extends Comparable<? super T>> void sort(List<T> list)
作用:将集合中元素按照默认规则排序。
3.public static <T> void sort(List<T> list,Comparator<? super T> )
作用:将集合中元素按照指定规则排序。
4.public static <T> boolean addAll(Collection<T> c, T... elements)
作用:往集合中添加一些元素。
接下来,我将对前面两种方法进行详细的讲解,后面两种方法下一篇博客再做详细讲解!
1.shuffle方法
作用是为了打乱集合顺序,顾名思义,只能在有排列顺序的List接口中使用,而Set和Map接口都是无需的Set接口和Map接口中使用都会报错。
具体使用例子如下:
import java.util.ArrayList;
import java.util.Collections;
public class Test{
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<>();
list.add(111);
list.add(222);
list.add(333);
list.add("abcd");
list.add(444);
list.add(555);
list.add(666);
list.add("999");
Collections.shuffle(list);
System.out.println("打乱顺序后为:"+list);
}
}
我们发现添加的基本类型和字符串类型都可以打乱顺序,那引用类型可以打乱吗?我们来浅试一下:
import java.util.ArrayList;
import java.util.Collections;
//需求,对一批客户的资产进行降序排序,有姓名和资产两个属性
public class Test3{
public static void main(String[] args) {
ArrayList<People> list = new ArrayList<>();
list.add(new People("张三",7373553));
list.add(new People("李四",873772247));
list.add(new People("王二",78625773));
list.add(new People("小赵",3125727));
list.add(new People("江总",888888888));
Collections.shuffle(list);
for (People people : list) {
System.out.println(people);
}
}
}
class People{
String name;
int money;
public People(String name, int money) {
this.name = name;
this.money = money;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
}
观察运行结果我们发现引用类型也可以打乱顺序,那到这里我们不由得想shuffle方法是怎样打乱顺序的呢?是通过打乱下标来改变位置还是直接换元素位置呢?
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
去看了一下shuffle下的源码,从源码可知,进行shuffle时候,是分成两种情况:
1. 若集合元素个数小于shuffle阈值或者集合支持随机访问,那么从后往前遍历集合,交换元素。
2. 否则,先将集合转化为数组(提高访问效率),再进行遍历,交换元素(在数组中进行),最后设置集合元素。
shuffle方法的应用场景:比如斗地主扑克牌,将54张牌分给三个人,就可以使用shuffle方法来打乱牌,麻将也是一样的道理。
2.sort排序方法
看到sort有没有很熟悉,是不是想起了Arrays中的sort方法,那么他们俩同为sort方法有什么区别呢?
Collections中sort方法专门给List排序,而Arrays中sort方法专门给数组进行排序。
通过查看Collections中sort方法源码我们发现,Collections.sort的底层实现就是Arrays.sort
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
下面我们来实现sort方法
正常使用sort方法:
import java.util.ArrayList;
import java.util.Collections;
public class Test{
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(666);
list.add(111);
list.add(333);
list.add(222);
list.add(555);
list.add(444);
Collections.sort(list);
System.out.println("排序后为:"+list);
}
}
import java.util.ArrayList;
import java.util.Collections;
public class Test{
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("abc");
list.add("AbC");
list.add("ABc");
list.add("A");
list.add("B");
Collections.sort(list);
System.out.println("排序后为:"+list);
}
}
我们发现字符串类型的排序是从字符串中的第一个字符开始比较其编码的大小,按照升序排序。如果第一个相同比较第二个,如果第二个相同比较第三个,以此类推。
不正常使用sort方法:
import java.util.ArrayList;
import java.util.Collections;
public class Test{
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(666);
list.add(111);
list.add(333);
list.add(333);
list.add("222");
list.add(222);
list.add(555);
list.add(444);
Collections.sort(list);
System.out.println("排序后为:"+list);
}
}
我们发现运行后出现类转换异常,说明了什么?
说明sort方法只能对同种类型集合进行排序,并且只能对集合进行升序排序。
看到这里,我们在使用的过程中知道了sort方法可以进行升序排序,那么我们想倒叙排序呢?或者根据自己的需求来排序呢?接下来由我为大家介绍sort的自定义类型排序。
自定义类型排序需要用到Comparable接口,此接口中只有一个方法:
public int compareTo(T o);
作用: 此接口强行对实现它的每个类的对象进行整体排序。
例子如下:对一批客户的资产进行降序排序,有姓名和资产两个属性
import java.util.ArrayList;
import java.util.Collections;
//需求,对一批客户的资产进行降序排序,有姓名和资产两个属性
public class Test3{
public static void main(String[] args) {
ArrayList<People> list = new ArrayList<>();
list.add(new People("张三",7373553));
list.add(new People("李四",873772247));
list.add(new People("王二",78625773));
list.add(new People("小赵",3125727));
list.add(new People("江总",888888888));
Collections.sort(list);
for (People people : list) {
System.out.println(people);
}
}
}
class People implements Comparable{
String name;
int money;
public People(String name, int money) {
this.name = name;
this.money = money;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
@Override
public int compareTo(Object o) {
People s=(People)o;
return s.money-this.money;
}
}
注意:在使用Comparable接口的时候需要重写compareTo方法,根据自己需要返回值,并且在测试类中实例化对象泛型的类型必须是你添加的类型,否则就会编译错误。
(后面两种方法后面的博客再为大家讲解,感谢阅读!)
今天的敲代码时间就到此为止吧,再敲就不礼貌啦,明天依旧是敲代码的一天。