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));
}
}
注意:
-
指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。当指定类型的数组长度大于了集合的size,那么就不会新创建数组,而是使用传递进来的数组。所以创建一个刚刚好的数组最优。 -
为什么要将集合变数组?
为了限定对元素的操作,不需要进行增删了。 -
最后,所有的集合都可以用
T[] Collection.toArray(T[] a)
这个方法复制到数组中。通常会用这样的方式调用:return coll.toArray(new T[coll.size()]);
这个方法会分配足够大的数组来储存所有的集合,这样
toArray()
方法在返回值时就不必再分配空间了。