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 <T extends Comparable<? super T>> void sort(List<T> list)  -------  默认只支持升序(支持内部比较器)

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

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) ------------ 也支持Set

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

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

public static <T> void sort(List<T> list, Comparator<? super T> c)  -------------------  支持外部比较器

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CollectionDemo01 {
	public static void main(String[] args) {
		List<Integer> 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>集合实现排序,即对Person类的对象进行排序,主要有两种方式:Comparable和Comparator。

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

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

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

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

内部比较器Comparable接口:

public class Person implements Comparable<Person>{
	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>中,只有Person类实现了Comparable接口,重写compareTo方法,才可以对Person类对象中的属性进行排序。同时对象中存在多个属性时,在compareTo方法需要进行多个属性的判断,防止因为单个属性相同而将其看作一个属性而出现错误。

public class SortDemo {
	public static void main(String[] args) {
		List<Person> 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<list.size()-1;i++) {
			for(int j=i+1;j<list.size();j++) {
				if(list.get(i).age < list.get(j).age) {//*****类似于compareTo()方法
					*//**
					 * int temp = arr[i];
					 * arr[i] = arr[j];
					 * arr[j] = temp;
					 *//*
					Person temp = list.get(i); ------ 利用list中独有的get,set方法可以进行集合元素位置的调换
					list.set(i, list.get(j));
					list.set(j, temp);
				}
			}
		}
		System.out.println(list);*/		
		Collections.sort(list);
		//对集合: 按照年龄升序
		System.out.println(list);
	}
}

外部比较器Comparator接口:

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

public class ComparatorDemo01 {
	public static void main(String[] args) {
		//Integer中默认升序,如果要实现降序
		List<Integer> 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 <T> void sort(List<T> list, Comparator<? super T> c)
		 * public interface Comparator<T> {
		 * 		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<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2-o1;
			}		
		});
		System.out.println(list);
	}
}
//这种方式不建议,很繁琐。
class IntegerComparator implements Comparator<Integer>{
	@Override
	public int compare(Integer o1, Integer o2) {
		return o2-o1;
	}	
}

源码分析:

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

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

Collections工具类中的sort()方法
======================================================================
public static <T> void sort(List<T> list, Comparator<? super T> c) {
    list.sort(c);
}
List接口中的sort方法
================================================================
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);
    }
}
位于Arrays.class中
====================================================================
public static <T> void sort(T[] a, Comparator<? super T> 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 <T> void legacyMergeSort(T[] a, Comparator<? super T> 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; i<high; i++)
             for (int j=i; j>low && ((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方法。 --- 形成了所谓的自定义降序

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值