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
930
忙しい人のための 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
180
Other Decks in Programming
See All in Programming
ソフトウェア設計の実践的な考え方
masuda220
PRO
4
630
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
230
20251016_Rails News ~Rails 8.1の足音を聴く~
morimorihoge
2
670
Foundation Modelsを実装日本語学習アプリを作ってみた!
hypebeans
1
120
組込みだけじゃない!TinyGo で始める無料クラウド開発入門
otakakot
2
360
技術的負債の正体を知って向き合う
irof
0
230
monorepo の Go テストをはやくした〜い!~最小の依存解決への道のり~ / faster-testing-of-monorepos
convto
2
530
タスクの特性や不確実性に応じた最適な作業スタイルの選択(ペアプロ・モブプロ・ソロプロ)と実践 / Optimal Work Style Selection: Pair, Mob, or Solo Programming.
honyanya
3
190
Flutterで分数(Fraction)を表示する方法
koukimiura
0
140
One Enishi After Another
snoozer05
PRO
0
150
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
200
AI駆動で0→1をやって見えた光と伸びしろ
passion0102
1
780
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
100
5.8k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
610
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
9
930
Building a Scalable Design System with Sketch
lauravandoore
463
33k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.2k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
130k
A Tale of Four Properties
chriscoyier
161
23k
YesSQL, Process and Tooling at Scale
rocio
173
15k
Thoughts on Productivity
jonyablonski
70
4.9k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
How to Think Like a Performance Engineer
csswizardry
27
2.1k
The Illustrated Children's Guide to Kubernetes
chrisshort
49
51k
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!ʯͳͷͰങ͍!!