java8--集合(瘋狂java講義3復習筆記)


1、集合分四類:set,map,list,queue

位於java.util包下.

集合類和數組的區別,數組可以保存基本類型的值或者是對象的引用,而集合里只能保存對象的引用.

集合類主要由兩個接口派生而出:Collection和Map

collection集合里面一共10個可用的類.

 

其中,

set里面4個: EnumSet, TreeSetHashSet, LinkedHashSet

Queue里面2個: ArrayDeque, PriorityQueue,

List里面3個: ArrayList, Vector, Stack

同時實現Queue和List的一個: LinkedList

 常用的有5個.

 

Map中實現類一共9個,常用的是HashMap, TreeMap

 

collection中方法,也就是Set, Queue, List共同的方法.

所有的collection的實現類都從寫了toString()方法,該方法可一次性輸出集合中所有元素.

包括:

求並集(添加元素或集合):

求補集(刪除某元素或集合):

求交集:

是否包含某元素或集合:

 

是否為空:

遍歷集合:

books.forEach(obj -> System.out.println("迭代集合元素:"+obj));

 

或者如下:

Iterator<String> it = books.iterator();
//這種形式遍歷可以用it.remove()來刪除元素,其他的方式都不可以,會引發異常.
while(it.hasNext()){
    System.out.println(it.next());
}

或者如下:

for(String book : books){
    System.out.println(book);
}

清空集合:

元素個數:

轉成數組:

2、用java8增強的Iterator遍歷集合元素

Iterator接口里定義了4個方法:

boolean hasNext(): 如果被迭代的集合元素還沒有被遍歷完,則返回true

Object next(): 返回集合里的下一個元素

void remove(): 刪除集合里上一次next方法返回的元素

void forEachRemaining(Consumer action),這是java8為Iterator新增的默認方法,可使用Lambda表達式來遍歷集合元素.

Iterator<String> it = books.iterator();
it.forEachRemaining(obj -> System.out.println("迭代集合元素:"+obj));

 

8.2.5 使用Java8 新增的predicate操作集合

打印長度小於10的元素:

books.removeIf(ele -> ((String)ele).length() <10);
System.out.println(books);

返回符合條件的元素的個數:

public static void main(String[] args){
    System.out.println(callAll(books,ele -> ((String)ele).contains("瘋狂")));
}
public static int callAll(Collection<String> books, Predicate<Object> p){
     int total = 0;
     for(Object obj :books){
       if(p.test(obj)){
        total ++;
     }
   }
   return total;
 }

 

8.2.6 Java8新增的Stream操作集合

java8新增了Stream,IntStream,LongStream等,其中Stream是一個通用的流接口.還為每個流式Api提供了對應的Builder,例如Stream.Builder,開發者可以通過這些Builder來創建對應的流.

獨立使用Stream的步驟如下:

1.使用Stream或XxxStream的builder()類方法創建改Stream對應的Builder.

2.重復調用Builder的add()方法向該流中添加多個元素.

3.調用Builder的build()方法獲取對應的Stream.

4.調用Stream的聚集方法.

第4步可以根據需求來調用不同的方法,Stream提供了大量的聚集方法供用戶調用,對應大部分聚集方法而言,每個Stream只能執行一次.

public static void main(String[] args) {
        IntStream is = IntStream.builder()
                .add(20)
                .add(13)
                .add(-2)
                .add(18)
                .build();
        
//        System.out.println("最大值:"+ is.max().getAsInt());
//        System.out.println("最小值:"+ is.min().getAsInt());
//        System.out.println("總和:"+ is.sum());
//        System.out.println("總數:"+ is.count());
//        System.out.println("平均值:"+ is.average());
//        System.out.println("平方均大於20:"+ is.allMatch(ele -> ele*ele > 20));
//        System.out.println("某個元素平方大於20:"+ is.anyMatch(ele -> ele*ele > 20));
        //將is映射成一個新的Stream,新Stream的每個元素是原Stream元素的2倍+1
        IntStream newIs = is.map(ele -> ele * 2 +1);
//        //使用方法引用的方式來遍歷集合元素
        newIs.forEach(System.out::println);
        
    }

因為collection有Stream接口,所以,用Stream方法來重寫上面的"返回符合條件的元素的個數"

public static void main(String[] args) {
        Collection<String> books = new HashSet<>();
        books.add("123241232");
        books.add("wdw12ddw");
        books.add("es23d");
        System.out.println(books.stream()
                .filter(ele -> ((String) ele).contains("123")).count());
        
    }

 

8.3 Set集合

HashSet的特點:

1.不能保證元素的排列順序

2.不是同步的,如果多線程訪問,必須通過代碼來保證其同步

3.集合元素之可以是null 

比較的規則是,equals()方法和HashCode()方法返回的值都相等,那么set認為是同一個對象.

所以,當把一個對象放到HashSet中時,如果需要重寫該對象對應類的equals()方法,那么也要重寫其hashCode()方法.

因此,當程序把可變對象添加到HashSet中之后,盡量不要去修改該集合元素中參與計算hashCode(),equals()的實例變量,否則會導致HashSet無法正確操作這些集合元素.

8.3.2 LinkedHashSet類

LinkedHashSet集合也是根據元素的hashCode值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,這樣使得元素看起來是以插入的順序保存的,也就是說,當遍歷LinkedHash集合里的元素時,LinkedHashSet將會元素的添加順序來訪問集合里的元素.

LinkedHashSet需要維護元素的插入順序,因此新呢過略低於HashSet的性能,但在迭代訪問Set里的全部元素時將有很好的性能,因為天以鏈表來維護內部順序.

LinkedHashSet<String> books = new LinkedHashSet<>();

8.3.3 TreeSet 類

TreeSet是SortedSet接口的實現類,正如SortedSet名字所暗示的,TreeSet可以確保集合元素處於排序狀態.與HashSet集合相比,TreeSet還提供了如下幾個額外的方法.

訪問前一個,后一個,第一個,最后一個元素的方法,並提供了三個從TreeSet中截取子TreeSet的方法,以及一個Comparator()來返回該TreeSet的定制的排序方法.默認使用自然排序,即從小的到大的順序.

public static void main(String[] args) {
        // TODO Auto-generated method stub
        TreeSet nums = new TreeSet<>();
        nums.add(5);
        nums.add(2);
        nums.add(6);
        nums.add(-4);
        System.out.println(nums);
    }

如果試圖把一個對象添加到TreeSet時,則改對象的類必須實現Comparable接口,否則程序將會拋出ClassCastException異常.不過java一些常用類已經實現了Comparable接口,並提供了比較大小的標准.

另外一點:大部分類在實現compareTo(Object obj)方法時,都需要將被比較對象obj強制類型轉換成相同的類型,因為只有相同類的兩個實例才會比較大小.所以向TreeSet中添加的應該是同一個類(或者有繼承關系)的對象.

為了讓程序更加健壯,推薦不要修改放入HashSet和TreeSet集合中元素的關鍵實例變量.

2.定制排序

兩種方法,一個是要比較的類,需要實現Comparator接口,一個是創建TreeSet時使用Lambda表達式.

 

8.3.4EnumSet類

EnumSet是一個專為枚舉類設計的集合類,EnumSet中的所有元素都必須是指定枚舉類型的枚舉值,該枚舉類型在創建EnumSet時顯示或隱式地指定.EnumSet的集合元素也是有序的,EnumSet以枚舉值在Enum類內的定義順序來決定集合元素的順序.

EnumSet在內部以位向量的形式存儲,這種存儲形式非常緊湊,高效,因此EnumSet對象占用內存很小,而且運行效率也很好,尤其是進行批量操作(如調用containsAll()和retainAll()方法時),如果其參數也是Enumset機會,則該批量操作的執行速度非常快.

EnumSet機會不允許加入null元素.

8.3.5 各Set實現類的性能分析

EnumSet性能最好,但只能保存同一個枚舉類

HashSet很快,通常用它.

LinkedSet保持了存入順序,一般操作比HashSet慢,但遍歷時比HashSet快.

TreeSet,只有當需要一個保持排序的Set時,才應該使用TreeSet.

另外,這四個類都是現場不安全的,如果多線程調用,需要用synchronizedSortedSet方法包裝起來.

SortedSet<String> s = Collections.synchronizedSortedSet(new TreeSet<>());

 

8.4 List集合

 

List判斷兩個對象相等只要通過equals()方法比較返回true即可.

public static void main(String[] args)
    {
        List<Object> books = new ArrayList<>();
        // 向books集合中添加4個元素
        books.add(new String("輕量級Java EE企業應用實戰"));
        books.add(new String("瘋狂Java講義"));
        books.add(new String("瘋狂Android講義"));
        books.add(new String("瘋狂iOS講義"));
        // 使用目標類型為Comparator的Lambda表達式對List集合排序
        books.sort((o1, o2)->((String)o1).length() - ((String)o2).length());
        System.out.println(books);
        // 使用目標類型為UnaryOperator的Lambda表達式來替換集合中所有元素
        // 該Lambda表達式控制使用每個字符串的長度作為新的集合元素
        books.replaceAll(ele->((String)ele).length());
        System.out.println(books); // 輸出[7, 8, 11, 16]

    }

public static void main(String[] args)
    {
        String[] books = {
            "瘋狂Java講義", "瘋狂iOS講義",
            "輕量級Java EE企業應用實戰"
        };
        List<String> bookList = new ArrayList<String>();
        for (int i = 0; i < books.length ; i++ )
        {
            bookList.add(books[i]);
        }
        ListIterator<String> lit = bookList.listIterator();
        while (lit.hasNext())
        {
            System.out.println(lit.next());
            lit.add("-------分隔符-------");
        }
        System.out.println("=======下面開始反向迭代=======");
        while(lit.hasPrevious())
        {
            System.out.println(lit.previous());
        }
    }

public static void main(String[] args)
    {
        List<String> fixedList = Arrays.asList("瘋狂Java講義", "輕量級Java EE企業應用實戰");
        // 獲取fixedList的實現類,將輸出Arrays$ArrayList
        System.out.println(fixedList.getClass());
        // 使用方法引用遍歷集合元素
        fixedList.forEach(System.out::println);
        // 試圖增加、刪除元素都會引發UnsupportedOperationException異常
        fixedList.add("瘋狂Android講義");
        fixedList.remove("瘋狂Java講義");
    }

8.5 Queue集合

用來模擬隊列,先進先出

8.5.1 PriorityQueue實現類

PriorityQueue保存隊列元素的順序並不是安計入隊列的順序,而是安隊列元素的大小進行重新排序,因此當調用peek()方法或者poll()方法取出隊列中的

元素時,並不是取出最先進入隊列的元素,而是取出隊列中最小的元素.

 

 

 

 

 

 

 

 

 

 
         
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM