五、集合框架工具類Collections和Arrays
Collections是集合框架的工具類,里面的方法都是靜態的。
** 例1:根據字符串長度的正序和倒序排序。**
用到比較器的地方都可以用Collections.reverseOrder()。
- static void reverse(List<?> list) 反轉指定列表中元素的順序。
- static reverseOrder()
- static reverseOrder(Comparator<T> cmp)
- <T> Comparator<T> 返回一個比較器,它強行逆轉實現了 Comparable 接口的對象 collection 的自然順序。
- <T> Comparator<T> 返回一個比較器,它強行逆轉指定比較器的順序。
比較器ComparatorByLength.java:
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:
public static void demo_3() {
// reverse實現原理
/*
* TreeSet<String> ts = new TreeSet<String>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int temp = o2.compareTo(o1);
return temp;
}
});
*/
TreeSet<String> treeset = new TreeSet<String>(new ComparatorByLength());
treeset.add("abc");
treeset.add("hahaha");
treeset.add("zzz");
treeset.add("aa");
treeset.add("cba");
System.out.println(treeset);
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));//都是靜態方法,直接類名調用
ts.add("abc");
ts.add("hahaha");
ts.add("zzz");
ts.add("aa");
ts.add("cba");
System.out.println("after reverse:\t" + ts);
}
public static void main(String[] args) {
demo_3();
}<em id="__mceDel" style="background-color: #ffffff; font-family: "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px"><br data-filtered="filtered"></em>
運行結果
[aa, abc, cba, zzz, hahaha]
after reverse: [hahaha, zzz, cba, abc, aa]
例2:用工具類Collections.sort()進行排序:
public static void demo_2() {
List<String> list = new ArrayList<String>();
list.add("abcde");
list.add("cba");
list.add("aa");
list.add("zzz");
list.add("cba");
list.add("nbaa");
System.out.println(list);
Collections.sort(list);
System.out.println("after sort:\n" + list);
Collections.sort(list, Collections.reverseOrder());
System.out.println("after reverse sort:\n" + list);
int index = Collections.binarySearch(list, "cba");
System.out.println("index=" + index);
// 獲取最大值。
String max = Collections.max(list, new ComparatorByLength());
System.out.println("maxLength=" + max);
}
public static void main(String[] args) {
demo_2();
}
運行結果
[abcde, cba, aa, zzz, cba, nbaa]
after sort:
[aa, abcde, cba, cba, nbaa, zzz]
after reverse sort:
[zzz, nbaa, cba, cba, abcde, aa]
index=2
maxLength=abcde
例3:給非同步的集合加鎖,方法太多就不一一列舉了,自己查看API。(掌握,面試會問到)
- static <T> Collection<T>
synchronizedCollection(Collection<T> c)
返回指定 collection 支持的同步(線程安全的)collection。 - static <T> List<T>
synchronizedList(List<T> list)
返回指定列表支持的同步(線程安全的)列表。 - static <K,V> Map<K,V>
synchronizedMap(Map<K,V> m)
返回由指定映射支持的同步(線程安全的)映射。 - static <T> Set<T>
synchronizedSet(Set<T> s)
返回指定 set 支持的同步(線程安全的)set。
簡單說一下給集合加鎖的思想。
List list = new ArrayList();// 非同步的list。
list=MyCollections.synList(list);// 返回一個同步的list.
class MyCollections{
/**
* 返回一個加鎖的List
* */
public static List synList(List list){
return new MyList(list);
}
// 內部類
private class MyList implements List{
private List list;
private static final Object lock = new Object();
MyList(List list){
this.list = list;
}
public boolean add(Object obj){
synchronized(lock)
{
return list.add(obj);
}
}
public boolean remove(Object obj){
synchronized(lock)
{
return list.remove(obj);
}
}
}
}
例4:將集合轉成數組,Arrays.asList()方法 (掌握)
應用場景:數組方法有限,需要使用集合中的方法操作數組元素時。
注意1:
數組的長度是固定的,所以對于集合的增刪方法(add()和remove())是不能使用的。
Demo:
public static void demo_1() {
String[] arr = { "abc", "haha", "xixi" };
List<String> list = Arrays.asList(arr);
boolean b1 = list.contains("xixi");
System.out.println("list contains:" + b1);
// list.add("hiahia");//引發UnsupportedOperationException
System.out.println(list);
}
運行結果
list contains:true
[abc, haha, xixi]
注意2:
如果數組中的元素是對象(包裝器類型),那么轉成集合時,直接將數組中的元素作為集合中的元素進行集合存儲。(比如上面那個Demo)
如果數組中的元素是基本數據類型,那么會將該數組作為集合中的元素進行存儲。(比如下面這個Demo)
Demo:
public static void demo_2() {
/*
* 如果數組中的元素是對象,那么轉成集合時,直接將數組中的元素作為集合中的元素進行集合存儲。
*
* 如果數組中的元素是基本類型數值,那么會將該數組作為集合中的元素進行存儲。
*
*/
int[] arr = { 31, 11, 51, 61 };
List<int[]> list = Arrays.asList(arr);
System.out.println(list);
System.out.println("數組的長度為:" + list.size());
}
運行結果
[[I@659e0bfd]
數組的長度為:1
由結果可以看出,當數組中的元素時int類型時,集合中存的元素是整個數組,集合的長度為1而不是4。
** 例5:將數組轉成集合,List.toArray()方法**
- Object[]
toArray()
Returns an array containing all of the elements in this list in proper sequence (from first to last element). - <T> T[]
toArray(T[] a)
Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array.
應用場景:對集合中的元素操作的方法進行限定,不允許對其進行增刪時。
注意:toArray方法需要傳入一個指定類型的數組,數組的長度如何定義呢?
如果定義的數組長度小于集合的size,那么該方法會創建一個同類型并和集合相同size的數組。
如果定義的數組長度大于集合的size,那么該方法就會使用指定的數組,存儲集合中的元素,其他位置默認為null。
所以,一般將數組的長度定義為集合的size。
Demo:
public class ToArray {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
String[] arr = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(arr));
}
}
例6:foreach語句
應用場景:遍歷數組或Collection單列集合。
對數組的遍歷如果僅僅是獲取數組中的元素用foreach可以簡化代碼,如果要對數組的角標進行操作建議使用傳統for循環。
格式:
for(類型 變量 :Collection集合|數組)
{}
Demo:
public class ForEachDemo {
public static void main(String[] args) {
// 遍歷數組
int[] arr = { 3, 1, 5, 7, 4 };
for (int i : arr) {
System.out.println(i);
}
//遍歷List
List<String> list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
for (String s : list) {
System.out.println(s);
}
// 遍歷map
// 可以使用高級for遍歷map集合嗎?不能直接用,但是將map轉成單列的set,就可以用了。
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(3, "zhagsan");
map.put(1, "wangyi");
map.put(7, "wagnwu");
map.put(4, "zhagsansan");
for (Integer key : map.keySet()) {
String value = map.get(key);
System.out.println(key + "::" + value);
}
for (Map.Entry<Integer, String> me : map.entrySet()) {
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key + ":" + value);
}
// 老式的迭代器寫法
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}