JAVA 8 併發增強 (4) ConcurrentHashMap批量操作
阿新 • • 發佈:2018-12-12
/* * java8為併發雜湊對映提供了批量操作資料操作,即使在其他執行緒同時操作對映時也可以安全的執行。 * 批量資料操作會遍歷對映並對匹配的元素進行操作。在批量操作過程中,不需要凍結對映的一個快照。除非你恰好知道在這段時間 * 內對映沒有被修改,否則你應該將結果看作是對映狀態的一個近似值。批量操作有三類 * a,search會對每個鍵或值應用一個函式,直到函式返回一個null的結果。然後search會終止並返回該函式的結果。 * b,reduce會通過提供的積累函式,將所有的鍵或指結合起來。c,forEach會對所有鍵或值對應一個函式。 * 使用這幾種操作時,需要指定一個並行閾值 * ,如果對映包含的元素數目超過了這個閾值,批量操作以並行的方式執行。如果希望批量操作資料在一個執行緒執行, * 請使用Long.MAX_VALUE作為閾值。如果希望批量操作儘可能使用更多的執行緒,則應該使用1作為閾值。 */ /* * 比如希望找到第一個出現超過1000次的的單詞,我們需要搜尋鍵和值。 返回結果為第一個匹配的元素,或者沒有找到任何元素則返回null */ ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>(); for (int i = 0; i < 1000; i++) { map.merge("a", 2L, Long::sum);//2000 map.merge("b", 1L, Long::sum);//1000 } String rs = map.search(1, (k, v) -> v > 1000 ? k : null); System.out.println(rs); /* * foreach方法有兩種,第一種只是對每個對映資料項簡單的用一個消費者函式 * 第二種是額外接受一個轉換器函式,首先會應用此轉換器函式,然後再將結果傳遞給消費者函式、 * 轉換器函式可以被用作一個過濾器。當轉換器函式返回null時,值會被自動跳過 */ map.forEach(1, (k, v) -> System.out.println(k + "->" + v)); map.forEach(1, (k, v) -> k + "->" + v, System.out::println); map.forEach(1, (k, v) -> v > 1000 ? k + "->" + v : null, System.out::println); /* *reduce操作將其輸入與一個累加函式結合起來。例如下面是計算所有值的總和 */ Long sum = map.reduceValues(1, Long::sum); /* *同forEach一樣,你也可以提供一個轉換器函式。比如計算長度最長的鍵 */ Integer maxLength = map.reduceKeys(1, String::length, //轉換器 Integer::max); //累加器 System.out.println(maxLength); /* * 轉換器函式可以作為一個過濾器,通過返回null來排除不想要的輸入。 * tips:如果對映是空的,或者所有的資料項都被過濾掉了,則reduce操作會返回null。如果只有一個元素, * 那麼會返回它轉換後的值,並且不會應用累加函式。 */ Long count = map.reduceValues(1, v->v>1000?1L:null, //轉換器 Long::sum); //累加器 System.out.println(count); /* * 對於int,long,double型別的輸出,reduce操作提供了專門的方法,分別以ToInt,ToLong和ToDouble結尾。 * 你需要將輸入轉換為原始型別值,並指定一個預設值和累加器函式。當對映為空時返回預設值。 * tips:這幾個專門的方法與用於物件的方法行為不同,它們只會考慮一個元素。與返回轉換後的元素不同 * ,他們會對預設值進行累加,因此。預設值必須是累加器的中立元素。 */ long sum2 = map.reduceValuesToLong(1, Long::longValue, //轉換為原始型別 0, //空對映的預設值 Long::sum);//原始型別累加器 }