Lambdas 和 Streams

Java 8 的新特性,有哪些?
  • 為了更易于創(chuàng)建函數(shù)對(duì)象文留,加入了 functional interfaces, lambdas 和 method references
  • 為了處理序列數(shù)據(jù)元素泞边,加入了 Streams API
解釋一下 function types
  • 只含有一個(gè)抽象方法的接口或抽象類
解釋一下 function objects
  • function types的實(shí)例,相當(dāng)于 functions 或者 actions
解釋一下 functional interfaces
  • 只含有一個(gè)抽象方法的接口
在創(chuàng)建函數(shù)對(duì)象時(shí)裙犹,為什么優(yōu)先使用lambdas,而不使用匿名類
  • 使用匿名類的實(shí)例作為函數(shù)對(duì)象衔憨,已經(jīng)過時(shí)
  • 匿名類冗長叶圃,Lambdas 支持類型推斷,更簡潔
舉幾個(gè)例子践图,說明Lambdas比匿名類好用
Collections.sort(words, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
    }
});
Collections.sort(words,
        (s1, s2) -> Integer.compare(s1.length(), s2.length()));
Collections.sort(words, comparingInt(String::length));
words.sort(comparingInt(String::length));
使用Lambdas的注意事項(xiàng)
  • 由于Lambdas 缺少 names 和 documentation掺冠,如果一次計(jì)算不是自解釋性的夹供,或者超過3行熊经,則最好不要放在Lambdas里冀痕。
  • 只有在創(chuàng)建 functional interfaces 的實(shí)例時(shí)弟胀,才建議使用Lambdas
  • Lambdas 和 匿名類一樣,你不應(yīng)該去序列化以及反序列化它們眉厨,如果你想序列化或反序列化一個(gè)function object锌奴,則使用一個(gè) private static nested class
什么時(shí)候只能使用匿名類,而不能使用lambdas
  • lambdas只限于functional interfaces憾股,如果想創(chuàng)建含有多個(gè)抽象方法的實(shí)例鹿蜀,則要使用匿名類
  • lambda不能獲取對(duì)自己的引用,在lambdas中服球, this關(guān)鍵字指的是enclosing instance茴恰,在匿名類中,this關(guān)鍵字指的是anonymous class instance有咨。
為什么優(yōu)先使用method references琐簇,而不是lambdas
  • 舉個(gè)java8 Map接口中的merge方法的例子,第一行是使用lambdas座享,第二行是使用method references
map.merge(key, 1, (count, incr) -> count + incr);
map.merge(key, 1, Integer::sum);
  • method references 往往能生成更簡潔清晰的代碼婉商,如果一個(gè)lambdas的代碼片段太長或太復(fù)雜,可以把這段代碼抽出來生成一個(gè)新方法渣叛,可以對(duì)該新方法起個(gè)好名字丈秩,然后把lambdas替換成對(duì)該新方法的引用
  • method 和 lambda在同一個(gè)類中時(shí),或者使用Function接口中的identity方法淳衙,此時(shí)應(yīng)該優(yōu)先使用lambda蘑秽,如下:
service.execute(GoshThisClassNameIsHumongous::action);

等價(jià)于

service.execute(() -> action());

相似地,

Function.identity()

等價(jià)于

x -> x
有哪幾種方法引用箫攀?
  • Static引用
Integer::parseInt

對(duì)應(yīng)的Lambda

str -> Integer.parseInt(str)
  • Bound引用
Instant.now()::isAfter

對(duì)應(yīng)的Lambda

Instant then = Instant.now(); 
t -> then.isAfter(t)
  • Unbound引用
String::toLowerCase

對(duì)應(yīng)的Lambda

str -> str.toLowerCase()
  • Class Constructor引用
TreeMap<K,V>::new

對(duì)應(yīng)的Lambda

() -> new TreeMap<K,V>
  • Array Constructor 引用
int[]::new

對(duì)應(yīng)的Lambda

len -> new int[len]
優(yōu)先使用 standard functional interfaces, 說說你對(duì)java.util.function.Function中的函數(shù)接口的了解
  • java.util.Function中一共有43個(gè)函數(shù)接口肠牲,可以概括成6種基本函數(shù)接口,從這6種基礎(chǔ)接口靴跛,可以推導(dǎo)出其他接口缀雳,同時(shí)每一種基本接口,都有對(duì)原始類型int, long 和 double的變體梢睛,6種基本函數(shù)接口如下:
Interface Function Signature Example
UnaryOperator<T> T apply(T t) String::toLowerCase
BinaryOperator<T> T apply(T t1, T t2) BigInteger::add
Predicate<T> boolean test(T t) Collection::isEmpty
Function<T,R> R apply(T t) Arrays::asList
Supplier<T> T get() Instant::now
Consumer<T> void accept(T t) System.out::println
在使用Streams API時(shí)肥印,應(yīng)該注意什么?
  • 使用流绝葡,是為了讓程序變得更shorter and clearer深碱,如果流使你的程序在簡潔的基礎(chǔ)上,又便于閱讀和維護(hù)藏畅,那么就去用它敷硅,否則就遠(yuǎn)離它
  • 濫用流,會(huì)讓程序變得難以閱讀和維護(hù)
  • 用 流 替換 loop 時(shí),也要注意代碼的可讀性和維護(hù)性的問題
  • forEach函數(shù)應(yīng)該僅僅用于report流計(jì)算的結(jié)果竞膳,而不應(yīng)該執(zhí)行計(jì)算
在流中航瞭,如何使用無副作用的函數(shù)
  • 不要使用下面的方式實(shí)例化frequency table
Map<String, Long> freq = new HashMap<>();
try (Stream<String> words = new Scanner(file).tokens()) {
    words.forEach(word -> {
        freq.merge(word.toLowerCase(), 1L, Long::sum);
    });
}
  • 應(yīng)該使用下面的方式實(shí)例化frequency table
Map<String, Long> freq;
try (Stream<String> words = new Scanner(file).tokens()) {
    freq = words
        .collect(groupingBy(String::toLowerCase, counting()));
} 
  • 應(yīng)該使用下面方式獲取 top10 words from a frequency table
List<String> topTen = freq.keySet().stream()
    .sorted(comparing(freq::get).reversed())
    .limit(10)
    .collect(toList());
  • 使用 toMap collector 來構(gòu)建一個(gè)<string, enum> 的 map
private static final Map<String, Operation> stringToEnum =
    Stream.of(values()).collect(
        toMap(Object::toString, e -> e));
  • 使用 toMap collector 生成針對(duì)key的特定的value的map
Map<Artist, Album> topHits = albums.collect(
   toMap(Album::artist, a->a, maxBy(comparing(Album::sales))));

Collector to impose last-write-wins policy

toMap(keyMapper, valueMapper, (v1, v2) -> v2)
  • groupingBy的簡單使用
words.collect(groupingBy(word -> alphabetize(word)))
Map<String, Long> freq = words
        .collect(groupingBy(String::toLowerCase, counting()));
  • 多關(guān)注 java.util.stream.Collectors中的靜態(tài)方法
為了同時(shí)提供使用 iteration 和 stream 的功能诫硕,應(yīng)該優(yōu)先使用Collection作為返回類型坦辟,而不是Stream
謹(jǐn)慎使用streams parallel,在使用時(shí)應(yīng)該注意的問題
  • 現(xiàn)在的Java章办,寫concurrent programs 越來越簡單锉走,但寫出 correct 以及 fast 的 concurrent programs 依舊很難
  • 不要盲目的 parallelize stream pipelines
  • 如果流的源頭來自Stream.iterate或者在中間操作中使用limit,那么parallelizing a pipeline 不會(huì)提高性能
  • 如果流的源頭是 ArrayList, HashMap, HashSet, ConcurrentHashMap instances藕届;arrays; int ranges; long ranges挪蹭,那么parallelizing a pipeline 可能會(huì)提高性能
  • parallelizing a stream 不但很可能造成差的性能,它還可能導(dǎo)致不正確的結(jié)果和不可預(yù)測的行為
  • 總之休偶,不要輕易 parallelize a stream pipeline
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梁厉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子踏兜,更是在濱河造成了極大的恐慌词顾,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碱妆,死亡現(xiàn)場離奇詭異肉盹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)疹尾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門上忍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纳本,你說我怎么就攤上這事窍蓝。” “怎么了繁成?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵吓笙,是天一觀的道長。 經(jīng)常有香客問我朴艰,道長观蓄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任祠墅,我火速辦了婚禮侮穿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘毁嗦。我一直安慰自己亲茅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著克锣,像睡著了一般茵肃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袭祟,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天验残,我揣著相機(jī)與錄音,去河邊找鬼巾乳。 笑死您没,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胆绊。 我是一名探鬼主播氨鹏,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼压状!你這毒婦竟也來了仆抵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤种冬,失蹤者是張志新(化名)和其女友劉穎镣丑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碌廓,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡传轰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谷婆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慨蛙。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖纪挎,靈堂內(nèi)的尸體忽然破棺而出期贫,到底是詐尸還是另有隱情,我是刑警寧澤异袄,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布通砍,位于F島的核電站,受9級(jí)特大地震影響烤蜕,放射性物質(zhì)發(fā)生泄漏封孙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一讽营、第九天 我趴在偏房一處隱蔽的房頂上張望虎忌。 院中可真熱鬧,春花似錦橱鹏、人聲如沸膜蠢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挑围。三九已至礁竞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杉辙,已是汗流浹背模捂。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奏瞬,地道東北人枫绅。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓泉孩,卻偏偏與公主長得像硼端,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寓搬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容