Java
この前のパズルの答えです。
TAGS: Java |
2013年6月6日7:25 PM |
Java
今日も朝早くから「もっと Lambda」シリーズの始まりです。
Java Day Tokyo 2013 でテストパイロットを大募集していたらしいので UnaryOperator を試しがてらにちょっと確認を。
まず UnaryOperator の確認をします。
java.util.function
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T>
An operation upon a single operand yielding a result. The operand and the result are of the same type. This is a specialization of Function
for the case where the operand and result are of the same type.
パラメータ:
T
– the type of operand to apply
and of the result
日付:
1.8
参照:
Function
そして今回使う DoubleUnaryOperator は次のように double 専用に用意されたものです。
java.util.function
@FunctionalInterface
public interface DoubleUnaryOperator
An operation on a double
operand yielding a double
result. This is the primitive type specialization of UnaryOperator
for double
.
日付:
1.8
参照:
UnaryOperator
applyAsDouble(double operand) は次のようになってます。
java.util.function.DoubleUnaryOperator
public double applyAsDouble(double operand)
Returns the double
result of the operation upon the double
operand.
パラメータ:
operand
– the operand value
戻り値:
the operation result value
それでは無限小から 1 を引いた値の表示とその値と無限小が等しいか確認するプログラムを創ってみました。
ついでに無限小から無限小を引いてみました。(普通ありえない計算ですよね(^_^;)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
package jp.yucchi.tryintunaryoperator; import java.util.function.DoubleUnaryOperator; public class TryIntUnaryOperator { public static void main(String[] args) { DoubleUnaryOperator operator = f -> f - 1; double j = operator.applyAsDouble(Double.NEGATIVE_INFINITY); System.out.println(j); if(Double.NEGATIVE_INFINITY == j){ System.out.println("無限小"); }else{ System.out.println("なんでやねん。"); } DoubleUnaryOperator operator2 = f -> f - Double.NEGATIVE_INFINITY; double k = operator2.applyAsDouble(Double.NEGATIVE_INFINITY); System.out.println(k); if(0 == k){ System.out.println("0"); }else{ System.out.println("むりぽ"); } } } |
実行結果は次のように期待通りになりました。
-Infinity
無限小
NaN
むりぽ
ここでバグがでたら片言の英語で「なんでやねん?」と言ってやろうと思ったがこんな単純なバグはそうそうあるもんじゃないですね。
TAGS: Java |
2013年6月2日5:27 AM |
Java
今日のエントリーも「もっと Lambda」シリーズです。
今回はよく使われるデザインパターンで知られている Factory Method pattern を Java8 を使ってコーディングしてみます。
ちなみにこのネタは海外のサイトで紹介されていたものです。
それを少し変えて写経しただけですが随分シンプルになるので感激です。
それでは現在の Java だと下記のようになります。
|
package jp.yucchi.factorymethodpattern4oldjava; public interface Airplane { public void pilot(); public void maintain(); } |
|
package jp.yucchi.factorymethodpattern4oldjava; public class JetAirplane implements Airplane { @Override public void pilot() { System.out.println("ジェット機を操縦します。"); } @Override public void maintain() { System.out.println("ジェット機を整備します。"); } } |
|
package jp.yucchi.factorymethodpattern4oldjava; public class FighterPlane implements Airplane { @Override public void pilot() { System.out.println("戦闘機を操縦します。"); } @Override public void maintain() { System.out.println("戦闘機を整備します。"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
package jp.yucchi.factorymethodpattern4oldjava; abstract class AirplanePilot { public abstract Airplane getAirplane(); public void pilotAirplane() { getAirplane().pilot(); } public void maintainAirplane() { getAirplane().maintain(); } } class JetAirplanePilot extends AirplanePilot { @Override public Airplane getAirplane() { return new JetAirplane(); } } class FighterPlanePilot extends AirplanePilot { @Override public Airplane getAirplane() { return new FighterPlane(); } } |
|
package jp.yucchi.factorymethodpattern4oldjava; public class FactoryMethodPattern4OldJava { public static void main(String[] args) { pilotAirplane(new JetAirplanePilot()); pilotAirplane(new FighterPlanePilot()); } private static void pilotAirplane(AirplanePilot aPilot) { System.out.println("I pilot a new airplane."); aPilot.pilotAirplane(); aPilot.maintainAirplane(); } } |
Factory Method pattern でよく見かける典型的なサンプルですね。
インスタンスの生成をサブクラスに任せることによって柔軟に生成するインスタンスを選択することを可能としています。
では Java8 ではどのようなコードになるのでしょうか?
|
package jp.yucchi.factorymethodpattern4lambda; public interface Airplane { public void pilot(); public void maintain(); } |
|
package jp.yucchi.factorymethodpattern4lambda; public class JetAirplane implements Airplane { @Override public void pilot() { System.out.println("ジェット機を操縦します。"); } @Override public void maintain() { System.out.println("ジェット機を整備します。"); } } |
|
package jp.yucchi.factorymethodpattern4lambda; public class FighterPlane implements Airplane { @Override public void pilot() { System.out.println("戦闘機を操縦します。"); } @Override public void maintain() { System.out.println("戦闘機を整備します。"); } } |
|
package jp.yucchi.factorymethodpattern4lambda; public interface AirplanePilot { public Airplane getAirplane(); public default void pilotAirplane() { getAirplane().pilot(); } public default void maintainAirplane() { getAirplane().maintain(); } } |
|
package jp.yucchi.factorymethodpattern4lambda; public class FactoryMethodPattern4Lambda { public static void main(String[] args) { pilotAirplane(JetAirplane::new); pilotAirplane(FighterPlane::new); } static void pilotAirplane(AirplanePilot aPilot) { System.out.println("I pilot a new airplane."); aPilot.pilotAirplane(); aPilot.maintainAirplane(); } } |
Java8 では抽象化クラス AirplanePilot とそれの具象化クラス二つが必要とされません。
その代わりに、Java8 の新機能の Default methods ( Virtual extension methods ) を実装したインターフェイスを利用します。
実行結果はどちらも次のようになります。
I pilot a new airplane.
ジェット機を操縦します。
ジェット機を整備します。
I pilot a new airplane.
戦闘機を操縦します。
戦闘機を整備します
実にシンプルで綺麗なコードで Factory Method pattern が実装できてしまうんですね!
TAGS: Java |
2013年6月1日8:36 PM |
Java
昨日の Java パズラーの超ウルトラヒントを・・・
たぶん、必要ないと思うけど・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
package jp.yucchi.infinity; import java.util.stream.IntStream; public class Infinity { public static void main(String[] args) { IntStream.range(Integer.MAX_VALUE - 3, Integer.MAX_VALUE, 2).limit(5).forEach(System.out::println); System.out.println("***********************************"); int count = 0; for (int i = 0; i <= Integer.MAX_VALUE; Math.addExact(0, i++)) { count++; if (i > Integer.MAX_VALUE - 5) { System.out.println(i); } } System.out.println(count); } } |
このパズルは古典的なオーバーフローをとりあげてます。
|
IntStream.range(Integer.MAX_VALUE - 3, Integer.MAX_VALUE, 2) |
この新しい構文は、
|
for (int i = startInclusive; i < endExclusive ; i += step) { ... } |
と同じで、i += step のところでオーバーフローをおこします。
|
for (int i = 0; i <= Integer.MAX_VALUE; Math.addExact(0, i++)) { ... } |
このループ文は一見すると Math.addExact() メソッドを利用しているので例外が出ると思ってしまいがちですが、
よ~~~く見ると引数の i++ でオーバーフローするので無限ループになってしまいます。
とても古典的で簡単なパズルでした。
これだけだと寂しいので Math.addExact() メソッドを覗いてみました。
|
public static int addExact(int x, int y) { int r = x + y; // HD 2-12 Overflow iff both arguments have the opposite sign of the result if (((x ^ r) & (y ^ r)) < 0) { throw new ArithmeticException("integer overflow"); } return r; } |
なんか良く解らないけどビット演算を駆使して判定しているようですね。
なんで今頃こんなものを・・・以下自粛。(^_^;)
TAGS: Java |
2013年5月29日10:44 AM |
Java
Java8 でパズルを創ってしまいました。
Java™ Platform, Standard Edition 8 Early Access with Lambda Support b88 で創りました。
簡単なパズルです。
低レベルなものですが、よければあなたの頭脳をもってしてコンパイル、実行してみてください。(^_^)
とても素敵な答えが見つかるでしょう。(^_^;)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
package jp.yucchi.infinity; import java.util.stream.IntStream; public class Infinity { public static void main(String[] args) { IntStream.range(Integer.MAX_VALUE - 3, Integer.MAX_VALUE, 2).limit(5).forEach(System.out::println); System.out.println("***********************************"); int count = 0; for (int i = 0; i <= Integer.MAX_VALUE; Math.addExact(0, i++)) { count++; if (i > Integer.MAX_VALUE - 5) { System.out.println(i); } } System.out.println(count); } } |
解りましたでしょうか?
答えは秘密にしておきますので気になる方は実際にコンパイル、実行させてみてくださいね。
TAGS: Java |
2013年5月28日7:37 AM |