Java 8が準備していること

新しい方法でニュースとコードを見てみましょう。



それでは、リストから始めましょう。


リストがあるとします。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
      
      







昔の私たちがどのように反復したかを思い出してください:

 for (int i = 0; i < numbers.size(); i++){ System.out.println(numbers.get(i)); }
      
      







すべてが素晴らしいですが、つまずいて<の代わりに<=を置くか、0の代わりに1から始めるのは非常に簡単です。上記のコードでは、メカニズムを完全に制御し、すべての可動部分を念頭に置いています。 多くの場合、これは良いことです。Java5では、砂糖を追加しただけで誰もそれを採用しませんでした。



 for(int num:numbers){ System.out.println(num); }
      
      







Java 8では、彼らはまだ何も取りませんが、「宣言的」アプローチを提供します。つまり、やりたいことを宣言し、すべてのメカニズムをJVMに配置します。



  numbers.forEach(value -> System.out.println(value));
      
      







この例ではラムダ式を使用していることに注意してください。 次の段落で彼について。 多くの人がすでにforEachを多くの言語とライブラリで見ています。 したがって、forEachを使用すると、「最初から始めて最後で終わり、1つずつ反復して各要素を使用する」のではなく、「ここにコレクションがあり、この式をそのすべての要素に適用します」(宣言的アプローチ)を1行で表現できます。



ラムダ式について。


匿名クラスを関数に置き換えることができる非常においしい革新。



すでに上記の例を考えてみましょう。

  numbers.forEach(value -> System.out.println(value));
      
      







ラムダ式がない場合、この例は次のようになります。

 numbers.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } @Override public Consumer<Integer> andThen(Consumer<? super Integer> after) { return null; } });
      
      







複雑ですね。 しかし、単純な1行の式に戻ります。ここでは、何かを単純化することができます。他の変数が存在しないことが既に明らかである場合、なぜ2回値に言及する必要があります。

 numbers.forEach(System.out::println);
      
      







はい、はい、メソッドを関数として渡しました(*)。 そこで、「ここに方法があります。ループで適用してください。」



以下は、匿名クラスを関数で置き換えるいくつかの例です。



ストリーム作成:

 new Thread(SomeClass::runSomething).start();
      
      







コンパレーターソート

 Collections.sort(numbers, (o1, o2)-> o2.compareTo(o1));
      
      







コレクションフレームワークの変更


ラムダ式を理解したら、Collections Frameworkの最新版に進みます。 リスト内のすべての数値の合計に2を掛けて計算する必要があるとします。 考え直すことなく、コードを作成します。



  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); int sum = 0; for (int num : numbers) { sum += num * 2; }
      
      







それでは、宣言的なアプローチに移りましょう。

 int result = numbers.stream(). mapToInt(value->value*2). sum();
      
      





ちょっと待ってください、このmap-reduceではありませんか? 彼が一番です。 順番に分析します。 したがって、mapToIntはマップ操作を実行し、その結果、要素は2回になります。 sumは、整数に対してのみ使用可能な縮小変換です。



コードを変更し、奇数のもののみを処理し、奇数のものをフィルタリングする命令を受け取ったとします。

  System.out.println(numbers.stream(). filter(value -> value % 2 == 0). mapToInt(value -> value * 2). sum());
      
      







反対に、奇数カウント、さらには破棄:

  System.out.println(numbers.stream(). filter(value -> value % 2 != 0). mapToInt(value -> value * 2). sum());
      
      







別の新しい言語機能


私たちは、インターフェイスが「何をするのか」を教えてくれますが、それ自体では何もしないという事実に慣れています。 Java 8では、インターフェースは時々何かをします。



以下に例を示します。

 public interface IFly { public void takeOff(); public default void cruise() { System.out.println("IFly.cruise"); }; public void turn(); public void land(); }
      
      







C ++でプログラムを作成し、BjörnStaustrupを読んだ人は、「ダイヤモンドの問題はどうですか?」という質問をします。 質問は興味深いです。 そして答えがあります。



クラスが2つのインターフェイスを継承し、それぞれにデフォルトのメソッドがあるとします。 コンパイル中にエラーが発生します。



  public interface A { default void hello() { System.out.println("Hello World from A"); } } public interface B { default void hello() { System.out.println("Hello World from B"); } public class D implements A,B {}
      
      







別の例を見てみましょう:三角形

  public interface A { default void hello() { System.out.println("Hello World from A"); } } public interface B extends A { default void hello() { System.out.println("Hello World from B"); } } public class C implements B, A { public static void main(String... args) { new C().hello(); } }
      
      







この場合、階層内で最も近いもの、つまりインターフェースBが優先されます。インターフェースAのメソッドを使用する場合は、明示的に指定する必要があります



 A.super.hello();
      
      







3番目の例を見てみましょう:抽象クラスとインターフェイスには競合するメソッドがあります。 ルール-クラスは常に勝ちます。



したがって、問題は解決されます。





さらにいくつかのグッズ




Base64、廃止されたsun.misc.Base64についてコンパイラがひどいメッセージをくれた時間と、一見単純なことのためにApachevライブラリを使用しなければならなかった時間。

これで問題は解決されました:java.util.Base64

 Base64.getEncoder().encode(new byte[]{1, 2, 3, 4, 5});
      
      







新しい日付と時刻のAPI。 古き良きGregorianCallendarを想像できない場合は、新しいClock、Time、LocalTimeクラスを試すことができます



  import java.time.LocalDate; import java.time.Period; ... LocalDate time = LocalDate.now(); Period period = Period.ofDays(2); LocalDate newDate = time.plus(period); System.out.println("year:"+newDate.getYear()); System.out.println("month:"+newDate.getMonth()); System.out.println("day:"+newDate.getDayOfMonth());
      
      






All Articles