表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
Javaで学ぶ魔法入門  作者: つむらてんほ
幕間
23/64

コードの温度差

2017/08/20コードの記述ミスを修正

 さて、メリッサとジョージの温度差について説明する必要があるだろう。

 そもそも、メリッサが言う”冗長な呪文(コード)”とは、このようなコードを言っている。

 これは並の魔法使いが書くコードだ。

public static void main(String[] args){

  List<Object> list = Magic.getTargetObjectList();

  TheMark[] mark= new TheMark[2];

  int markIndex=0;

  for(int i = 0;i <list.size();i++){

    Object object = list.get(i);

    if(object instanceof TheMark){

      TheMark tempMark = (TheMark)object;

      mark[markIndex] = tempMark;

      markIndex++;

    }

  }

  for(int j = 0;j < 5;j++){

    Missile missile1 = new Missile(1);

    FireElement fire1 = new FireElement(200);

    missile1.addElement(fire1);

    missile1.setTarget(mark[0]);

    missile1.start();

  }

  Object target2 = list.get(1);

  for(int k = 0;k < 5;k++){

    Missile missile2 = new Missile(1);

    FireElement fire2 = new FireElement(-10);

    missile2.addElement(fire2);

    missile2.setTarget(mark[1]);

    missile2.start();

  }

}

 いろいろと突っ込みどころがあるのを敢えてスルーして、結果だけ見ると、Effect(ここではMagic)の生成には時間コストが1秒ほど発生するため、単純に他の要素を無視しても、この呪文は1秒ごとに矢を生成し、発射し、命中してから再度生成し、と繰り返すため、(1生成時間+2距離時間)×10本でこれだけで30秒、実際にはそれ以外のコストがあるため20秒どころか30秒を切ることすらできない。

 一方メリッサが競技に使用しようとしたコードはこうだ。

public static void main(String[] args){

  List<Object> list=Magic.getTargetObjectList();

  List<Object> markList=new ArrayList<Object>();

  for(Object object:list)

    if(object instanceof TheMark)

      markList.add(object);

  List<Effect> effectList=new ArrayList<Effect>();

  int[] temperatures={200,-10};

  for(int i=0,s=0;i<10;++i,s=1-s)

    effectList.add(makeEffect(temperatures[s],markList.get(s)));

  for(Effect effect:effectList)

    effect.start();

}

private static Effect makeEffect(int temperature,Object target){

  Effect effect=new Missile(1);

  effect.addElement(new FireElement(temperature));

  effect.setTarget(target);

  return effect;

}

 矢が出現するのはEffectのインスタンスが出来たタイミング、つまりnew Missile(1)が実行されたタイミングである。

 よって、このコードを実行した場合、まず10秒かけて矢が10本できてから、その後発射、命中を繰り返す。

 結果として10秒+2×10秒=30秒かかるので、最初のコードと変わらないように見えるが、これは”魔法が発動してから全てが当たるまでの時間”の理解の差によるものだ。

 メリッサの言う”魔法が発動”、つまり魔法競技での”魔法が発動”とは、”効果を発揮した”の意味であり、今回の場合は”的に命中した瞬間”を意味していた。

 この場合、最初のコードでは27秒かかるが、メリッサのコードは最初の1矢が命中したあとは2秒ごとに9本、つまり18秒+αが”魔法が発動してから全てが当たるまでの時間”となる。


 では、ジョージが書いたコードはどうだったか。

public static void main(String[] args){

  final TheMark[] targets=

      Magic.getTargetObjectList()

      .stream()

      .filter(o->o instanceof TheMark)

      .toArray(TheMark[]::new);

  IntConsumer shooter=new IntConsumer(){

    public void accept(int value) {

      Effect effect=new Missile(1);

      effect.addElement(new FireElement(value==0?200:-10));

      effect.setTarget(targets[value]);

      effect.start();

    }

  };

  IntStream.iterate(0,n->1-n).parallel().limit(10).forEach(shooter::accept);

}

 もはや逆の意味でどこから突っ込んだらいいのかわからない、(無駄に)関数インターフェースを駆使したJava8 Stream APIコードであった。


 ジョージのコードでは矢の生成から命中までの3秒が並列に実行されます。

 この並列には上限があり、PCであればコア数であったりスレッド数であったりというのが上限となります。

 ただ、この世界では幸いなことにJDK Server VirtualMageが動作している場所は、超並列環境()なので、並列可能数は”物凄い数”(MPが尽きるまで)、となります。

評価をするにはログインしてください。
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

この作品はリンクフリーです。ご自由にリンク(紹介)してください。
この作品はスマートフォン対応です。スマートフォンかパソコンかを自動で判別し、適切なページを表示します。

↑ページトップへ