JAVA常用类(十):Collections类(与Arrays类对比)

目录

Collections类

常用成员方法:

比较器的使用:

源码分析:


Collections类

Collection和Collections区别:

         Collection: 是单列集合的根接口

         Collections: 集合的工具类

集合转数组:集合对象.toArray()  -------------返回一个Object[ ]

数组转集合: Arrays.asList(T...t)  ----------- 得到的集合不能add ,remove,需要 new ArrayList<>(Arrays.asList(T...t))

常用成员方法:

public static Comparable> void sort(List list)  -------  默认只支持升序(支持内部比较器)

public static int binarySearch(List> list, T key)  -----------  默认支持只升序

public static > T max(Collection coll) ------------ 也支持Set

public static void reverse(List list) -------------- 集合的逆序

public static void shuffle(List list)  -------------- 打乱集合的排序

public static void sort(List list, Comparator c)  -------------------  支持外部比较器

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CollectionDemo01 {
	public static void main(String[] args) {
		List list = Arrays.asList(12,3,6,5,9,4,5,60);
		
		Collections.sort(list);//默认是升序的
		System.out.println(list);  //[3, 4, 5, 5, 6, 9, 12, 60]
		System.out.println(Collections.binarySearch(list, 4));  //1
		System.out.println(Collections.max(list)); //60 --- 参数为Collection类型的,因此也可以是Set
		
		Collections.reverse(list);  //反转
		System.out.println(list);  //[60, 12, 9, 6, 5, 5, 4, 3]
		System.out.println(Collections.binarySearch(list, 4)); //-1 ,Collection的二分查找与list一致,只适合升序
		
		Collections.shuffle(list); //随机大乱(斗地主发牌)
		System.out.println(list); //[3, 5, 9, 6, 12, 60, 4, 5]
		/**
		 * Collection怎么对对象排序
		 * 该对象所在的类必须实现Comparable接口
		 */
	}

比较器的使用:

通过Collections.sort()方法已经可以对一些集合实现排序的功能,如果想对List集合实现排序,即对Person类的对象进行排序,主要有两种方式:Comparable和Comparator。

Comparable:内部比较器,java.lang; 如果一个List想要使用Collections.sort() 做排序,需要集合中的元素所在的类实现Comparable接口,重写compareTo:

         this在前:升序;         参数在前:降序

Comparator:外部比较器,java.util;  如果一个类中不能实现Comparable,或者是对应Comparable中的排序方式不满意,可以通过Comparator重新定义排序的规则,而不需要修改原有类的结构。Collections.sort(list,Comparator) //匿名内部类;

与Comparable接口相比,Comparator不需要修改类的结构,更加灵活。

内部比较器Comparable接口:

public class Person implements Comparable{
	String name;
	int age;
	double score;
	public Person() {
		super();
	}
	public Person(String name, int age, double score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	//需求:默认使用年龄的升序,如果年龄相同,按照分数的降序
	@Override
	public int compareTo(Person o) {  //int类型不可更改
		//Person p = (person)o;
		if(this.age == o.age) {
			//return (int)(o.score - this.score); --- 强制类型转换的会使得相近的double类型的数字的差变为0
			return (o.score>this.score)?-1:(o.score==this.score)?0:1;
		}
		return (this.age - o.age);
	}
}

注:集合List中,只有Person类实现了Comparable接口,重写compareTo方法,才可以对Person类对象中的属性进行排序。同时对象中存在多个属性时,在compareTo方法需要进行多个属性的判断,防止因为单个属性相同而将其看作一个属性而出现错误。

public class SortDemo {
	public static void main(String[] args) {
		List list = new ArrayList<>();
		list.add(new Person("Jerry",19));
		list.add(new Person("Tom",15));
		list.add(new Person("Jack",39));
		list.add(new Person("Rose",29));
/*		for(int i=0;i

外部比较器Comparator接口:

注:有的类已经实现了Comparable接口,此时如果希望修改实现方式只能继承后重写compareTo方法,但并不是所有的类都能继承,比如Integer类中实现了Comparable接口,默认使用升序,此时想要继承Integer类重写compareTo方法则不可能,因为他是用final修饰的。

public class ComparatorDemo01 {
	public static void main(String[] args) {
		//Integer中默认升序,如果要实现降序
		List list = Arrays.asList(1,2,5,6,3,8,9);
		
		Collections.sort(list);
		System.out.println(list); //[1, 2, 3, 5, 6, 8, 9]
		/**
		 * public static  void sort(List list, Comparator c)
		 * public interface Comparator {
		 * 		int compare(T o1, T o2);
		 * }
		 */
		//改写方式一:
		Collections.sort(list,new IntegerComparator());
		System.out.println(list); //[9, 8, 6, 5, 3, 2, 1]
		
		Collections.shuffle(list); //打乱顺序
		//改写方式二:使用匿名内部类
		Collections.sort(list, new Comparator() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2-o1;
			}		
		});
		System.out.println(list);
	}
}
//这种方式不建议,很繁琐。
class IntegerComparator implements Comparator{
	@Override
	public int compare(Integer o1, Integer o2) {
		return o2-o1;
	}	
}

源码分析:

public static void sort(List list, Comparator c) 

我们在使用外部比较器Comparator时进行排序时,会重写compare(T o1,T o2)方法。o1,o2是集合中相邻位置的元素。通过改变相邻位置元素o1与o2的位置我们会得到降序或升序的List集合。那具体底层是怎么设定的呢?我们来看一下:

Collections工具类中的sort()方法
======================================================================
public static  void sort(List list, Comparator c) {
    list.sort(c);
}
List接口中的sort方法
================================================================
default void sort(Comparator c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator i = this.listIterator();
    for (Object e : a) {
         i.next();
         i.set((E) e);
    }
}
位于Arrays.class中
====================================================================
public static  void sort(T[] a, Comparator c) {
    if (c == null) {
        sort(a);
    } else {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, 0, a.length, c, null, 0, 0);
    }
}
private static  void legacyMergeSort(T[] a, Comparator c) {
    T[] aux = a.clone();
    if (c==null)
        mergeSort(aux, a, 0, a.length, 0);
    else
        mergeSort(aux, a, 0, a.length, 0, c);
    }

private static void mergeSort(Object[] src,
                              Object[] dest,
                              int low,
                              int high,
                              int off) {
    int length = high - low;

    // Insertion sort on smallest arrays
    if (length < INSERTIONSORT_THRESHOLD) {
        for (int i=low; ilow && ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                  swap(dest, j, j-1);
            return;
        }
...
}

由上可知:方法最终会调用到 mergeSort 方法上。当相邻元素o1,o2满足 dest[j-1]).compareTo(dest[j])>0,会调用swap操作,实现位置的互换。

当compare方法中的:

 return o1-o2;

返回值为负数表示第一个参数比较小;

返回值为正数表示第一个参数比较大,调用swap方法。 ---  形成了所谓的默认升序

 return o2-o1;

返回值为负数表示第二个参数比较小;

返回值为正数表示第二个参数比较大,调用swap方法。 --- 形成了所谓的自定义降序

你可能感兴趣的:(java)