第三十六讲 集合框架工具类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yerenyuan_pku/article/details/84206633

Collections工具类

Collections类概述

针对集合操作的工具类,里面的方法都是静态的,可以对集合进行排序、二分查找、反转、混排等。

Collection和Collections的区别

Collection是单列集合的顶层接口,有子接口List和Set;而Collections是针对集合操作的工具类,有对集合进行排序和二分查找等方法。

Collections类的常用方法

对List集合排序

public static <T extends Comparable<? super T>> void sort(List<T> list)方法根据元素的自然顺序对指定列表按升序进行排序,列表中的所有元素都必须实现Comparable接口。

package cn.liayun.collections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsSimple {

	public static void main(String[] args) {
		methodDemo();
	}

	public static void methodDemo() {
		List<String> list = new ArrayList<String>();
		list.add("abce");
		list.add("z");
		list.add("hehe");
		list.add("nba");
		
		System.out.println(list);
		//对list排序,自然排序。使用的是元素的CompareTo方法
		Collections.sort(list);
		System.out.println(list);
	}

}

以上是使用Collections类中的sort()方法对List集合进行排序,而且使用的是自然排序。但现在我们想要按照字符串的长度进行排序,那又该如何做呢?这时需要用到下面的方法,根据指定比较器产生的顺序对指定列表进行排序。此列表内的所有元素都必须可使用指定比较器相互比较。

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

很显然,这时我们需要自定义一个比较器,使得比较是按照字符串的长度来排序的。

package cn.liayun.comparator;

import java.util.Comparator;

public 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;
	}

}

测试Demo为:

package cn.liayun.collections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import cn.liayun.comparator.ComparatorByLength;

public class CollectionsSimple {

	public static void main(String[] args) {
		methodDemo();
	}

	public static void methodDemo() {
		List<String> list = new ArrayList<String>();
		list.add("abce");
		list.add("z");
		list.add("hehe");
		list.add("nba");
		
		System.out.println(list);
		//对list排序,自然排序。使用的是元素的CompareTo方法
//		Collections.sort(list);
		Collections.sort(list, new ComparatorByLength());
		System.out.println(list);
	}

}

逆序

方法声明 功能描述
public static <T> Comparator<T> reverseOrder() 返回一个比较器,它强行逆转实现了Comparable接口的对象Collection的自然顺序
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) 返回一个比较器,它强行逆转指定比较器的顺序

下面分别对以上两个方法进行案例演示。我们首先按照字符串的自然顺序排序。

package cn.liayun.collections;

import java.util.TreeSet;

public class CollectionsSimple {

	public static void main(String[] args) {
		orderDemo();
	}
	
	public static void orderDemo() {
		TreeSet<String> set = new TreeSet<String>();
		set.add("abcde");
		set.add("aaa");
		set.add("k");
		set.add("cc");
		
		System.out.println(set);
	}

}

接下来,我们要反转其自然排序。

package cn.liayun.collections;

import java.util.Collections;
import java.util.TreeSet;

public class CollectionsSimple {

	public static void main(String[] args) {
		orderDemo();
	}
	
	public static void orderDemo() {
		TreeSet<String> set = new TreeSet<String>(Collections.reverseOrder());
		set.add("abcde");
		set.add("aaa");
		set.add("k");
		set.add("cc");
		
		System.out.println(set);
	}

}

当然了,我们也可以使用比较器来做。首先我们定义一个反转字符串的自然顺序的比较器,然后再调用此比较器。

package cn.liayun.collections;

import java.util.Comparator;
import java.util.TreeSet;

public class CollectionsSimple {

	public static void main(String[] args) {
		orderDemo();
	}
	
	public static void orderDemo() {
		Comparator<String> comparator = new Comparator<String>() {
			
			@Override
			public int compare(String o1, String o2) {
				return o2.compareTo(o1);
			}
		};
		
		TreeSet<String> set = new TreeSet<String>(comparator);
		set.add("abcde");
		set.add("aaa");
		set.add("k");
		set.add("cc");
		
		System.out.println(set);
	}

}

再来看第二个方法。我们首先定义一个按照字符串的长度排序的比较器,接着按照字符串的长度排序。

package cn.liayun.collections;

import java.util.Comparator;
import java.util.TreeSet;

public class CollectionsSimple {

	public static void main(String[] args) {
		orderDemo();
	}
	
	public static void orderDemo() {
		Comparator<String> comparator = new Comparator<String>() {
			
			@Override
			public int compare(String o1, String o2) {
				int temp = o1.length() - o2.length();
				return temp == 0 ? o1.compareTo(o2) : temp;
			}
		};
		
		TreeSet<String> set = new TreeSet<String>(comparator);
		set.add("abcde");
		set.add("aaa");
		set.add("k");
		set.add("cc");
		
		System.out.println(set);
	}

}

最后,我们反转其顺序:

package cn.liayun.collections;

import java.util.Collections;
import java.util.Comparator;
import java.util.TreeSet;

public class CollectionsSimple {

	public static void main(String[] args) {
		orderDemo();
	}
	
	public static void orderDemo() {
		Comparator<String> comparator = new Comparator<String>() {
			
			@Override
			public int compare(String o1, String o2) {
				int temp = o1.length() - o2.length();
				return temp == 0 ? o1.compareTo(o2) : temp;
			}
		};
		
		TreeSet<String> set = new TreeSet<String>(Collections.reverseOrder(comparator));
		set.add("abcde");
		set.add("aaa");
		set.add("k");
		set.add("cc");
		
		System.out.println(set);
	}

}

获取集合中的最大元素

方法声明 功能描述
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) 根据元素的自然顺序,返回给定Collection的最大元素
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定比较器产生的顺序,返回给定Collection的最大元素

下面分别对以上两个方法进行案例演示,先来看第一个方法。

package cn.liayun.collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

public class CollectionsSimple {

	public static void main(String[] args) {
		Collection<String> coll = new ArrayList<String>();
		coll.add("abcd");
		coll.add("aa");
		coll.add("z");
		coll.add("nba");
		
		String max = Collections.max(coll);
		System.out.println("max = " + max);
	}
	
}

如果说现在要让我们自己模拟一个获取集合最大值的功能,那又该怎么做呢?直接贴出代码如下:

/**
 * 模拟一个获取集合最大值的功能
 */
public static <T extends Object & Comparable<? super T>> T getMax(Collection<? extends T> coll) {
	Iterator<? extends T> it = coll.iterator();
	//1,定义变量,记录容器中的其中一个。
	T max = it.next();
	//2,遍历容器中所有的元素。
	while (it.hasNext()) {
		T temp = it.next();
		//3,在遍历过程中进行比较,只要比变量中的值大,用变量记录下来,就哦了。
		if (temp.compareTo(max) > 0) {
			max = temp;
		}
		
	}
	return max;
}

我们查看Java源代码,发现它写的和我们写的一模一样。
再来看第二个方法。首先,我们先自定义一个按照字符串的长度排序的比较器。

package cn.liayun.comparator;

import java.util.Comparator;

public 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;
	}

}

然后再根据此比较器的排序获取集合中的最大元素。

package cn.liayun.collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import cn.liayun.comparator.ComparatorByLength;

public class CollectionsSimple {

	public static void main(String[] args) {
		Collection<String> coll = new ArrayList<String>();
		coll.add("abcd");
		coll.add("aa");
		coll.add("z");
		coll.add("nba");
		
		String max = Collections.max(coll, new ComparatorByLength());
		System.out.println("max = " + max);
	}
	
}

将非同步集合转成同步集合

Collections还有一个可以将非同步集合转成同步集合的方法,如下:

同步集合 synchronized集合(非同步的集合)

Arrays工具类

Arrays类概述

此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。

Arrays类的常用方法

方法声明 功能描述
public static <T> List<T> asList(T... a) 可以从Array转换成List,也可以作为其他集合类型构造器的参数
public static void sort(...) 对整个数组或者数组的一部分进行排序。也可以使用此方法用给定的比较器对对象数组进行排序
public static String toString(...) 打印数组的内容

数组转成集合

将数组转换为集合,使用的方法为:

public static <T> List<T> asList(T... a):返回一个受指定数组支持的固定大小的列表
package cn.liayun.arrays;

import java.util.Arrays;
import java.util.List;

public class ArraysSimple {

	public static void main(String[] args) {
		String[] strs = {"abc", "haha", "nba", "zz"};
		List<String> list = Arrays.asList(strs);
//		list.add("qq");//java.lang.UnsupportedOperationException,注意,不能使用集合的增删方法,不能改变集合的长度。
		System.out.println(list.contains("nba"));
	}

}

那么问题就来了,把数组变成List集合有什么好处? 可以使用集合的思想和方法来操作数组中的元素。但要注意,将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定的。可以使用集合的诸如contains()、get()、indexOf()、subList()等等方法,如果你增删,那么会产生UnsupportedOperationException异常。
再看下面一段代码,试着运行一下,看看会输出什么结果。

package cn.liayun.arrays;

import java.util.Arrays;
import java.util.List;

public class ArraysSimple {

	public static void main(String[] args) {
		int[] arr = {45, 23, 78, 11, 99};
		List list = Arrays.asList(arr);
		System.out.println(list);
	}

}

此时将会输出[[I@15db9742]类似结果,以上代码没有使用泛型,使用泛型应是如此。

package cn.liayun.arrays;

import java.util.Arrays;
import java.util.List;

public class ArraysSimple {

	public static void main(String[] args) {
		int[] arr = {45, 23, 78, 11, 99};
		List<int[]> list = Arrays.asList(arr);
		System.out.println(list);
	}

}

如果将上面的代码修改为如下。

package cn.liayun.arrays;

import java.util.Arrays;
import java.util.List;

public class ArraysSimple {

	public static void main(String[] args) {
		Integer[] arr = {45, 23, 78, 11, 99};
		List<Integer> list = Arrays.asList(arr);
		System.out.println(list);
	}

}

此时输出[45, 23, 78, 11, 99]。所以,可得出结论:如果数组中的元素都是引用数据类型,那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组([[I@15db9742])对象作为集合中的元素存在

集合转成数组

集合转成数组,使用的是Collections接口中的toArray()方法。

package cn.liayun.arrays;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CollectionToArray {

	public static void main(String[] args) {
		//集合转成数组。Collection集合中的toArray方法
		List<String> list = new ArrayList<String>();
		
		list.add("abc");
		list.add("haha");
		
		/*
		 * 传入的数组长度如果小于集合长度,方法中会创建一个新的长度和集合长度一致的数组。
		 * 如果传入的数组长度大于等于集合长度,会使用传入的值,所以建议长度定义为集合的size()
		 * 
		 * 为什么要把集合转成数组?
		 * 就是为了限定对元素的操作,比如增删。
		 */
		String[] arr = list.toArray(new String[list.size()]);
		System.out.println(Arrays.toString(arr));
		
	}

}

注意:

  1. 指定类型的数组到底要定义多长呢?
    当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。当指定类型的数组长度大于了集合的size,那么就不会新创建数组,而是使用传递进来的数组。所以创建一个刚刚好的数组最优。

  2. 为什么要将集合变数组?
    为了限定对元素的操作,不需要进行增删了。

  3. 最后,所有的集合都可以用T[] Collection.toArray(T[] a)这个方法复制到数组中。通常会用这样的方式调用:

    return coll.toArray(new T[coll.size()]);
    

    这个方法会分配足够大的数组来储存所有的集合,这样toArray()方法在返回值时就不必再分配空间了。

猜你喜欢

转载自blog.csdn.net/yerenyuan_pku/article/details/84206633