Javaで機能する


Javaはそれが起動して以来、most popular languageされているので、クリエイターは、言語が何かを見逃すことはありませんし、新興の変更とのオリジナル性を維持していることを確認している.

関数型プログラミング
関数プログラミングは、ラムダ計算から発想されるプログラミングの概念です.この概念では、各計算は関数として考えられる.これらの関数は、スコープ外の状態/データを変更することはできません.


なぜ?
ソフトウェア開発は、コードを書くだけでなく、他の人が書いたコードを理解する反復的なプロセスです.
あなたはそれを挑戦し、その逆を見つけることがあります:D
引数として使用する関数によって変更された場合、特定のオブジェクトの状態を把握するのに時間がかかります.したがって、プログラムの動作を予測することは困難になる.
ドキュメントなしのサードパーティAPIのように考えてください.特定の関数を呼び出すときに何を期待するかはわからない.
これは、機能プログラミングの概念と同じではありません.状態と変更可能なデータを変更できないことにより、side-effectsを回避します.

どうやって?
すべてのこの理論は素晴らしいですが、どのようにJava開発者としてそれを使用しますか?
ほとんどの人はこの質問について考えなければならない.答えはJavaファミリーラムダの新しいメンバーです.

ラメラ
ラムダはオブジェクトのように動作する関数です.を渡すことができます.必要に応じて実行できます.単一の行で定義できます.クラスなしで作成できます.そして、ずっと.Javaによって以前に必要とされた多くのボイラープレートコードを取り除くのを助けます.
Syntax - (Parameter Declaration) -> {Lambda Body}
Examples -
Without parameters - () -> System.out.println("Hello lambda")
With one parameter - s -> System.out.println(s)
With two parameters - (x, y) -> x + y
With multiple line body - (x, y) -> {}
涼しい右?しかし、どのようにJavaはどのラムダがどの関数にマップされているかを知っていますか?

深く掘る
インターフェースはラムダのバックボーンです.javaは,ラムダが定義されている機能インタフェースとして知られている新しい概念を導入した.

機能界面
それらは1つの主要な違いでJavaの通常のインターフェースに類似しています.彼らはサムルールに従います.SAM規則によると、インターフェイスは単一抽象メソッド(SAM)のみで許可されます.
このチェックは、@ function alinterface注釈を使用してコンパイル時に実施することができます.
各々のラムダのために、我々は新しい機能的なインターフェースをつくる必要があります?
それは便利です.正しい?
Javaのようなルックスも、この問題の世話をしました.
パッケージJava.Util関数は、ほぼ50の機能インターフェースを含んでいる.あなたが彼らの範囲から何かを必要とするかもしれないことは、非常にありそうもありません.

機能界面族
すべてのインターフェイスをマスタリング多くのように見えるかもしれません.むしろ彼らの家族を理解するならば、我々は簡単に正しいインターフェースを指し示すことができます.
機能的インターフェイスの4つのファミリがあります.

消費者-消費と破棄
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
オブジェクトを受け入れ、何らかのアクションを行い、出力を返しません.つまり平均


Consumer<String> stringConsumer = string -> System.out.println(string);
ラムダ関数とprintln ()は同じ引数を受け取りますので、このようにメソッドリファレンスを使用することもできます.
Consumer<String> stringConsumer = System.out::println;

関数-マップ、変換または計算
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
それは1つのオブジェクトを受け入れて、いくつかの行動を実行して、もう一つのオブジェクトを返します.


Function<String, String> stringStringFunction = String::toUpperCase;

述語-テストまたはフィルタ
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}
一つのオブジェクトを受け取り、booleanを返します.通常ルールを定義します.


Predicate<String> stringPredicate = String::isEmpty;

供給元
@FunctionalInterface
public interface Supplier<T> {
    T get();
}
これは何も受け付けませんが、オブジェクトを返します.とても寛大な:D


Supplier<String> stringSupplier = () -> "Hello, World";

実世界
今ではいくつかの現実世界の課題に我々の知識を適用する時間です.Hackerrank - camelCaseから基本的なプログラミング課題を取り上げましょう.
Problem - Count number of words in a camelCase string.

Example - saveChangesInTheEditor
Result - 5
それで、我々の動機は、この問題を解決するだけでなく、機能的な方法を使ってそれを解決することです.
解決策は直進し、文字列の大文字の数を数え、結果は+ 1です.
これを機能的に行うには-
文字列内の個々の文字の
  • ストリーム、
  • 大文字をフィルタリングするのを助ける述語.
  • Solution -
    
    /* Stream - s.chars()
    Predicate - Character::isUpperCase */
    
    static long camelcase(String s) {
        return s.chars().filter(Character::isUpperCase).count() + 1;
    }
    

    ハーレイ!
    一行と問題を解決する.
    このアプローチは、開発者が簡単にスニペットの挙動を理解するのに役立ちます.上記の行は、文字列からの大文字のチャーターをフィルタリングすることができます.それは私たちが欲しかったものです.
    機能になることは上記の例に限られない.それは経験によって開発されたものです.なぜなら、私たちがどのように問題に近づくかについてです.
    Java開発者は、このアプローチを学ぶために余分な努力をしなければならないかもしれません.ディー