Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
忙しい人のための Functional Programming in Java / Funct...
Search
Youhei Nitta
November 14, 2014
Programming
0
910
忙しい人のための Functional Programming in Java / Functional Programming in Java for business person
社内勉強会でサンプルコードをベースに「Javaによる関数型プログラミング」の簡単なふりかえりをしました.
喋りで補ったところが多いかも...
Youhei Nitta
November 14, 2014
Tweet
Share
More Decks by Youhei Nitta
See All by Youhei Nitta
実践 Git / Pragmatic Git
youhei
2
170
Other Decks in Programming
See All in Programming
.NET Frameworkでも汎用ホストが使いたい!
tomokusaba
0
200
Domain-Driven Transformation
hschwentner
2
1.9k
color-scheme: light dark; を完全に理解する
uhyo
7
490
Datadog Workflow Automation で圧倒的価値提供
showwin
1
150
Honoのおもしろいミドルウェアをみてみよう
yusukebe
1
220
ナレッジイネイブリングにAIを活用してみる ゆるSRE勉強会 #9
nealle
0
150
メンテが命: PHPフレームワークのコンテナ化とアップグレード戦略
shunta27
0
300
How mixi2 Uses TiDB for SNS Scalability and Performance
kanmo
40
16k
Amazon Q Developer Proで効率化するAPI開発入門
seike460
PRO
0
120
新宿駅構内を三人称視点で探索してみる
satoshi7190
2
120
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.5k
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
5
950
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
10
1.3k
Code Reviewing Like a Champion
maltzj
521
39k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Designing Experiences People Love
moore
140
23k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
21
2.5k
Building an army of robots
kneath
303
45k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Typedesign – Prime Four
hannesfritz
40
2.5k
For a Future-Friendly Web
brad_frost
176
9.6k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
100
18k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Transcript
@youhei Software Engineer Fri Nov 14 © 2014 Youhei Nitta,
All rights reserved. Redistribution or public display not permitted without written permission from Youhei Nitta. ͍͠ਓͷͨΊͷ Functional Programming in Java
Java ʹΑΔؔܕϓϩάϥϛϯά Java 8 ϥϜμࣜͱ Stream ಡΈ·ͨ͠ɻ ྑॻͩͬͨͷͰɺखʹৼΓ ฦͬͯΈ·͢ɻ
ैདྷͷํ๏ public static void main(final String[] args) {! BigDecimal totalOfDiscountedPrices
= BigDecimal.ZERO;! ! for(BigDecimal price : prices) {! if(price.compareTo(BigDecimal.valueOf(20)) > 0) ! totalOfDiscountedPrices = ! totalOfDiscountedPrices.add(price.multiply(BigDecimal.valueOf(0.9)));! }! System.out.println("Total of discounted prices: " + totalOfDiscountedPrices);! } ໋ྩܕελΠϧ ͲͷΑ͏ʹ࣮ߦͯ͠ཉ͍͔͠Λهड़ mutable ͳมΛѻ͍ͬͯΔ
Java 8 public static void main(final String[] args) {! final
BigDecimal totalOfDiscountedPrices = ! prices.stream()! .filter(price -> price.compareTo(BigDecimal.valueOf(20)) > 0)! .map(price -> price.multiply(BigDecimal.valueOf(0.9)))! .reduce(BigDecimal.ZERO, BigDecimal::add);! ! System.out.println("Total of discounted prices: " + totalOfDiscountedPrices);! } ؔܕελΠϧ ྲྀΕΔΑ͏ʹॲཧΛॻ͘ (Stream API) ԿΛ࣮ߦ͖͔͢Λهड़ ࠶ೖΛճආ͍ͯ͠Δ
ͳͥؔܕΛ͏ͷ͔ • એݴతͰಡΈ͍͢ • ෆมੑʹΑΓόάΛࠞೖ͠ʹ͍͘ • ฒྻԽ͕༰қ • ԆධՁʹΑΓޮత
Java 8 ϥϜμࣜ
Java 8 ͷϥϜμࣜͷϙΠϯτ ୯ҰϝιουΠϯλϑΣʔε (Comparable, Runnable ͳͲ) ͷಗ໊ΫϥεͷΠϯελϯεΛ͢ɺͱ͍͏ݩʑ ͋ͬͨίϯηϓτΛ֦ுͨ͠ɻ ܰྔͳه๏ͱͯ͠ϥϜμࣜΛಋೖ͠ɺ͔͋ͨؔΛ
͍ͯ͠ΔΑ͏ʹݟͤͯɺ࣮୯Ұϝιουಗ໊Ϋϥεͷ ΠϯελϯεΛ͍ͯ͠Δɻ طଘͷ JDK ϥΠϒϥϦʹޓੑΛͭͷ͕རɻ
ಗ໊ΫϥεͷΠϯελϯε friends.forEach(new Consumer<String>() {! public void accept(final String name) {!
System.out.println(name);! }! }); Java 7 Ҏલͷจ๏ʹԊͬͨه๏ɻ Iterable ͷ forEach ϝιουʹ Consumer ಗ໊Ϋϥεͷ ΠϯελϯεΛ͍ͯ͠Δɻ
ϥϜμࣜ ! //ॲཧ͕1ߦͩͱίʔυϒϩοΫͷׅހলུՄɻҾʹ final Λ໌ࣔͰ͖Δɻ! friends.forEach((final String name) -> System.out.println(name));!
//ܕਪͰҾͷܕએݴΛলུՄɻ! friends.forEach((name) -> System.out.println(name));! //Ҿ͕1ݸͩͱׅހΛলུՄɻ! friends.forEach(name -> System.out.println(name)); ϥϜμࣜҥߏจɻ ίϯύΠϥ͕߹ϝιουΛੜ͍ͯ͠Δɻ ※ ࣮ґଘ͕ͩಗ໊ΫϥεͷΠϯελϯεੜͷҥߏจͰͳ͘ɺinvokedynamic Ͱ࣮ߦ࣌ʹಗ໊ΫϥεΛੜ͢Δॲཧʹஔ͖ΘΔɻΫϥεϑΝΠϧΛ࡞Βͤͳ͍ͨΊɻ
ϝιουࢀর //Ҿলུ! friends.forEach(System.out::println); ϝιουͷ໊લΛ͢ͷͰՄಡੑ͕ߴ͍ɻ ϝιουࢀরҾΛิ͠ίϯύΠϥ͕߹ϝιουʹ ม͍ͯ͠Δɻ
࣮ࡍʹͬͯΈͯ ଞͷݴޠͷϥϜμࣜͱ༻ײ͕ҧͬͨɻ API Λఏڙ͢Δଆ͔ΒΈͯҧ͍͕ͳ͍ɻ ! API ར༻ଆͷࢹ: ؔʢϥϜμࣜɾϝιουࢀরʣΛҾʹ͍ͯ͠Δ ! API
ఏڙଆͷࢹ: Ҿʹ͜Ε·Ͱ௨ΓͷΠϯελϯεΛड͚औ͍ͬͯΔ
Strategy Pattern
Predicate<T> ͰϩδοΫΛ͚Δ ! public static int totalAssetValues(final List<Asset> assets,! final
Predicate<Asset> assetSelector) {! return assets.stream()! .filter(assetSelector)! .mapToInt(Asset::getValue)! .sum();! }! ! //! totalAssetValues(assets, asset -> true);! totalAssetValues(assets, asset -> asset.getType() == AssetType.BOND));! totalAssetValues(assets, asset -> asset.getType() == AssetType.STOCK));! Strategy Pattern ͰϩδοΫΛൈ͖ग़͍ͯ͠Δɻ ࠓ·Ͱ৽͍͠ΫϥεΛ༻ҙ͍͕ͯͨ͠ɺϥϜμࣜͰදݱͰ͖ΔΑ͏ʹͳͬͨɻ ؔܕʹ׳Ε͍ͯΔͱී௨ͷύλʔϯ͚ͩͲɺJava Ͱॻ͚ΔΑ͏ʹͳͬͨɻ
Decorator Pattern
Stream API Ͱ࣍ʑʹద༻͢Δ public class Camera { ! private Function<Color,
Color> filter;! ! public void setFilters(final Function<Color, Color>... filters) {! filter = ! Stream.of(filters)! .reduce((filter, next) -> filter.compose(next))! .orElse(color -> color);! //.orElseGet(Function::identity); Ͱಉ͡! }! }! ! camera.setFilters(Color::brighter);! camera.setFilters(Color::darker);! camera.setFilters(Color::brighter, Color::darker); Decorator ύλʔϯɻΫϥεΛೖΕࢠʹͤͣ Stream API Ͱద༻ͨ݁͠ՌΛฦ͢ɻ ΫϥεΛఆٛͯ͠ೖΕࢠʹ͢Δख͕ؒল͚Δɻ දྫ. new BufferedReader(new InputStreamReader(is, "UTF-8"));
Execute Around Method Pattern
try-finally ͷϦιʔεղ์ public static void main(final String[] args) throws IOException
{! final FileWriterExample writerExample = ! new FileWriterExample("peekaboo.txt");! try {! writerExample.writeStuff("peek-a-boo"); ! } finally {! writerExample.close(); ! }! } యܕతͳύλʔϯ͕ͩɺίʔυ͕ࡶʹͳΔɻ ྫ֎ॲཧΛͪΌΜͱΔͱߋʹɻɻ
try-with-resources ͷϦιʔεཧ public static void main(final String[] args) throws IOException
{! try(final FileWriterARM writerARM = new FileWriterARM("peekaboo.txt")) {! writerARM.writeStuff("peek-a-boo");! ! ! System.out.println("done with the resource...");! }! } Java 7 ͔Βಋೖ͞Εͨɻ AutoCloseable ࣮ΫϥεͰ͋Δඞཁ͕͋Δɻ ։ൃऀ͕ AutoCloseable ͷ࣮Λ࣮֬ʹߦ͍ɺtry-with-resources ΛΕͣʹΘ ͳ͍ͱ͍͚ͳ͍ɻ
Execute Around Method Pattern public static void use(final String fileName,
! // UseInstance accept(T instance) throws X; Λͭ FunctionalInterface! final UseInstance<FileWriterEAM, IOException> block) throws IOException {! ! final FileWriterEAM writerEAM = new FileWriterEAM(fileName); ! try {! block.accept(writerEAM);! } finally {! writerEAM.close();! }! }! ! public static void main(final String[] args) throws IOException {! ! FileWriterEAM.use("eam2.txt", writerEAM -> {! writerEAM.writeStuff("how");! writerEAM.writeStuff("sweet"); ! });! }! } ϥϜμࣜΛ͏ɻ API Λ༻͢ΔਓʹϦιʔεཧΛҙࣝͤ͞ͳ͍ɻ JDBC ͷτϥϯβΫγϣϯཧɺLock ͷཧʹԠ༻Ͱ͖Δɻ
Virtual Proxy Pattern
ॳظԽͷԆ public class HolderNaive {! private Heavy heavy;! ! public
Heavy getHeavy() {! if(heavy == null) {! heavy = new Heavy();! }! ! return heavy;! }! }! ͓ͳ͡Έͷॲཧ͚ͩͲɺ৭ʑରॲ͖͕͋͢Δɻ
εϨουηʔϑ public class HolderThreadSafe {! private Heavy heavy;! ! public
synchronized Heavy getHeavy() {! if(heavy == null) {! heavy = new Heavy();! }! ! return heavy;! }! ! } ڝ߹ঢ়ଶΛഉআͨ͠ɻ εϨουͷ༗ແʹؔΘΒͣϝϞϦόϦΞΛ͑ͳ͚Ε͍͚ͳ͍ɻ ڝ߹͕ʹͳΔͷ࠷ॳ͚ͩɻ
Virtual Proxy Pattern ! public class Holder {! private Supplier<Heavy>
heavy = () -> createAndCacheHeavy();! ! public Heavy getHeavy() {! return heavy.get();! }! ! ϥϜμࣜͷϑΝΫτϦʔΫϥεΛఆٛͯ͠ɺ࠷ॳ͚ͩڝ߹ঢ়ଶʹରॲ͍ͯ͠Δɻ ೋճҎ߱ϑΝΫτϦʔΫϥεΛࠩ͠ସ͑ͯ synchronized ௨Βͣ୯७ʹΠϯελ ϯεΛฦ͢ɻैདྷ͋ͬͨ null νΣοΫͳ͘ͳͬͨɻ private synchronized Heavy createAndCacheHeavy() {! class HeavyFactory implements Supplier<Heavy> {! private final Heavy heavyInstance = new Heavy();! ! public Heavy get() { return heavyInstance; }! }! ! if(!HeavyFactory.class.isInstance(heavy)) {! heavy = new HeavyFactory();! }! ! return heavy.get();! }! ! }
Conclusion
Java ʹΑΔؔܕϓϩάϥϛϯά Java 8 ϥϜμࣜͱ Stream ଞʹϥϜμࣜͷ͑ΔςΫχοΫ͕ͨ͘͞ Μࡌ͍ͬͯ·͢ʢແݶϦετɺ࠶ؼݺͼग़͠ ࠷దԽͳͲʣɻ ࠓճ
Stream API ʹ͍ͭͯେ෯ʹলུͯ͠ ͍·͕͢ɺͦͪΒ͔ͬ͠Γ͓͍͑ͯ͞·͢ɻ ! ʮ࣌ Java!ʯͳͷͰങ͍!!