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
『テスト書いた方が開発が早いじゃん』を解き明かす #phpcon_nagoya
o0h
PRO
2
260
Honoとフロントエンドの 型安全性について
yodaka
7
1.2k
DROBEの生成AI活用事例 with AWS
ippey
0
130
プログラミング言語学習のススメ / why-do-i-learn-programming-language
yashi8484
0
130
『GO』アプリ データ基盤のログ収集システムコスト削減
mot_techtalk
0
120
PHPカンファレンス名古屋2025 タスク分解の試行錯誤〜レビュー負荷を下げるために〜
soichi
1
200
Pythonでもちょっとリッチな見た目のアプリを設計してみる
ueponx
1
570
第3回 Snowflake 中部ユーザ会- dbt × Snowflake ハンズオン
hoto17296
4
370
苦しいTiDBへの移行を乗り越えて快適な運用を目指す
leveragestech
0
600
仕様変更に耐えるための"今の"DRY原則を考える / Rethinking the "Don't repeat yourself" for resilience to specification changes
mkmk884
0
190
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
2
350
pylint custom ruleで始めるレビュー自動化
shogoujiie
0
120
Featured
See All Featured
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
630
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
The Cost Of JavaScript in 2023
addyosmani
47
7.3k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Facilitating Awesome Meetings
lara
52
6.2k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Unsuck your backbone
ammeep
669
57k
How to Think Like a Performance Engineer
csswizardry
22
1.3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
133
33k
Adopting Sorbet at Scale
ufuk
74
9.2k
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!ʯͳͷͰങ͍!!