Java集合框架體系詳細梳理,含面試知識點。(三)

五、集合框架工具類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());
        }
    }
}

歡迎加入學習交流群569772982,大家一起學習交流。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容