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
Tauriでネイティブアプリを作りたい
tsucchinoko
0
370
イベント駆動で成長して委員会
happymana
1
320
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
とにかくAWS GameDay!AWSは世界の共通言語! / Anyway, AWS GameDay! AWS is the world's lingua franca!
seike460
PRO
1
880
役立つログに取り組もう
irof
28
9.6k
Arm移行タイムアタック
qnighy
0
330
シェーダーで魅せるMapLibreの動的ラスタータイル
satoshi7190
1
480
エンジニアとして関わる要件と仕様(公開用)
murabayashi
0
300
광고 소재 심사 과정에 AI를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
Nurturing OpenJDK distribution: Eclipse Temurin Success History and plan
ivargrimstad
0
940
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.2k
Featured
See All Featured
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.2k
Done Done
chrislema
181
16k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
370
Scaling GitHub
holman
458
140k
Building a Scalable Design System with Sketch
lauravandoore
459
33k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
Agile that works and the tools we love
rasmusluckow
327
21k
Testing 201, or: Great Expectations
jmmastey
38
7.1k
Code Review Best Practice
trishagee
64
17k
Building Better People: How to give real-time feedback that sticks.
wjessup
364
19k
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!ʯͳͷͰങ͍!!