🎃

『Javaによる関数型プログラミング』を読んだ

2023/05/10に公開
  • 本記事のコード例は、『Javaによる関数型プログラミング』内で出てくるコードを改変したものです
    • importだけ書けば動くようにしました(最後以外)

どんな本か

この本は、
このコードを、

public class Main {
    public static void main(String[] args) {
        List<String> cities = Arrays.asList("Tokyo", "Sapporo");

        boolean found = false;
        for (String city : cities) {
            if (city.equals("Tokyo")) {
                found = true;
                break;
            }
        }
        System.out.println("Found Chicago?:" + found);
    }
}

こうする。

public class Main {
    public static void main(String[] args) {
        List<String> cities = Arrays.asList("Tokyo", "Sapporo");

+        System.out.println("Found Chicago?:" + cities.contains("Tokyo"));
-        boolean found = false;
-        for (String city : cities) {
-            if (city.equals("Tokyo")) {
-                found = true;
-                break;
-            }
-        }
-        System.out.println("Found Chicago?:" + found);
    }
}

これを繰り返していくのが『Javaによる関数型プログラミング』という本の書式であり、内容です。
これに魅力を感じ、Java8以降を扱える環境にあるなら、読む価値があると思います。
(本書の対象バージョンはJava8です)

リストを倒す

みんな大好きStreamAPIでリストを倒すのが2章です。

public class Main {
    public static void main(String[] args) {
        List<String> cities = Arrays.asList("Tokyo", "Sapporo");

        final List<String> startsWithN = cities.stream()
                .filter(name -> name.startsWith("S"))
                .collect(Collectors.toList());

        System.out.println(startsWithN);

    }
}

返り値のない関数をリストに当てるならこんな風に。

文字列リストを大文字でprintする
public class Main {
    public static void main(String[] args) {
        List<String> cities = Arrays.asList("Tokyo", "Sapporo");

        cities.stream()
                .map(String::toUpperCase)
                .forEach(name -> System.out.println(name + " "));
    }
}

文字列も倒す

String型もchar()でStreamを返すことで扱える。
ただしそのままだとIntStreamを返す

public class Main {
    public static void main(String[] args) {
        String str = "Hello";
        str.chars()
                .forEach(System.out::println);
        // 72 101 108 108 111
    }
}

stream中に文字にするならこんな風に

public class Main {
    public static void main(String[] args) {
        String str = "Hello";
        str.chars()
                .mapToObj(ch -> (char)ch)
                .forEach(System.out::println);
        // H e l l o
    }
}

4章以降はここに乗せるには複雑性が高いので省略

その他気になった部分

Stream型を引数にしておくことで、ParallelStreamも渡せる(8章より)

この関数にはStreamだけじゃなくParallelStreamも渡せる
public static void findHighPriced(final Stream<String> symbols) {
    final StockInfo highPriced =
        symbols.map(StockUtil::getPrice)
            .filter(StockUtil.isPriceLessThan(500))
            .reduce(StockUtil::pickHigh)
            .get();
  System.out.println("High priced under $500 is " + highPriced);}

気づき

  • 一通り読んだが、4章以降はまだ理解できていない、業務上で使う機会が少なそうなパターンが多かった。
    • 自分で機会を作っていかないと身につかなそう

わからなかったこと

  • stream-apiでインデックスを扱うのは難しいのだろうか
    • インデックスを使ってなにかする、という操作自体が設計によって変えられる部分なのかもしれない

Discussion