Upgrade to Pro — share decks privately, control downloads, hide ads and more …

忙しい人のための Functional Programming in Java / Funct...

Youhei Nitta
November 14, 2014

忙しい人のための Functional Programming in Java / Functional Programming in Java for business person

社内勉強会でサンプルコードをベースに「Javaによる関数型プログラミング」の簡単なふりかえりをしました.
喋りで補ったところが多いかも...

Youhei Nitta

November 14, 2014
Tweet

More Decks by Youhei Nitta

Other Decks in Programming

Transcript

  1. @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
  2. ैདྷͷํ๏ 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 ͳม਺Λѻ͍ͬͯΔ
  3. 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) ԿΛ࣮ߦ͢΂͖͔Λهड़ ࠶୅ೖΛճආ͍ͯ͠Δ
  4. ಗ໊ΫϥεͷΠϯελϯε friends.forEach(new Consumer<String>() {! public void accept(final String name) {!

    System.out.println(name);! }! }); Java 7 Ҏલͷจ๏ʹԊͬͨه๏ɻ Iterable ͷ forEach ϝιουʹ Consumer ಗ໊Ϋϥεͷ ΠϯελϯεΛ౉͍ͯ͠Δɻ
  5. ϥϜμࣜ ! //ॲཧ͕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 Ͱ࣮ߦ࣌ʹಗ໊ΫϥεΛੜ੒͢Δॲཧʹஔ͖׵ΘΔɻΫϥεϑΝΠϧΛ࡞Βͤͳ͍ͨΊɻ
  6. 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 Ͱ΋ॻ͚ΔΑ͏ʹͳͬͨɻ
  7. 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"));
  8. 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(); ! }! } యܕతͳύλʔϯ͕ͩɺίʔυ͕൥ࡶʹͳΔɻ ྫ֎ॲཧΛͪΌΜͱ΍Δͱߋʹɻɻ
  9. 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 Λ๨Εͣʹ࢖Θ ͳ͍ͱ͍͚ͳ͍ɻ
  10. 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 ͷ؅ཧʹ΋Ԡ༻Ͱ͖Δɻ
  11. ॳظԽͷ஗Ԇ public class HolderNaive {! private Heavy heavy;! ! public

    Heavy getHeavy() {! if(heavy == null) {! heavy = new Heavy();! }! ! return heavy;! }! }! ͓ͳ͡Έͷॲཧ͚ͩͲɺ৭ʑରॲ͢΂͖໰୊͕͋Δɻ
  12. εϨουηʔϑ public class HolderThreadSafe {! private Heavy heavy;! ! public

    synchronized Heavy getHeavy() {! if(heavy == null) {! heavy = new Heavy();! }! ! return heavy;! }! ! } ڝ߹ঢ়ଶΛഉআͨ͠ɻ εϨουͷ༗ແʹؔΘΒͣϝϞϦόϦΞΛ௒͑ͳ͚Ε͹͍͚ͳ͍ɻ ڝ߹͕໰୊ʹͳΔͷ͸࠷ॳ͚ͩɻ
  13. 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();! }! ! }
  14. Java ʹΑΔؔ਺ܕϓϩάϥϛϯά Java 8 ϥϜμࣜͱ Stream ଞʹ΋ϥϜμࣜͷ࢖͑ΔςΫχοΫ͕ͨ͘͞ Μࡌ͍ͬͯ·͢ʢແݶϦετɺ࠶ؼݺͼग़͠ ࠷దԽͳͲʣɻ ࠓճ͸

    Stream API ʹ͍ͭͯେ෯ʹলུͯ͠ ͍·͕͢ɺͦͪΒ΋͔ͬ͠Γ͓͍͑ͯ͞·͢ɻ ! ʮ࣌୅͸ Java!ʯͳͷͰങ͍!!