タグ「Java」の一覧
使っている技術としては、JavaのSwing+SQLite+XMLくらいでしょうか。やっぱり大学時代と違ってSQLをかなり書けるようになったのが大きいですね。SQLは偉大です、本当に。
でも、正直なところO/Rマッピングツールもちょっと使ってみたいなとも思ったりしてます。
SQLiteはかなり適当なRDBMSなんで、もうちょっとしっかりとしたやつでもいいかもしれませんね。スキーマも本来はあった方がいいだろうし、型がもうちょっと厳密であってくれた方が実装面でも迷わないし。もうちょっと完成に近づいたら、そのあたりも検討してみます。
今のところ、支出と収入などの履歴は登録できるんですが、それを参照する機能が中途半端。(手許のお金の推移だけは分かる。カードの使用状況はさっぱり...。)あと、ちょっと実装で困りそうなのが、支出内容のグループ化。(例えば、電気代と水道代を光熱費に統合するとか。)これも検討課題です。
でも、これだけJSPが簡単に書けるならもうちょっと早くから手がけておけばよかったと切に思いますね。eclipseを使えば、さくさくとコードもかけるし、実際に動いてる状況も確認できるし。ちょっと前に調べておいたLoggingパッケージの効果も相まって、デバッグもけっこう簡単に済みました。確かに異常系に関してはすごく手を抜いてるんですけど、これは追々詰めていくということで。
今日はすごくきれいな空が拝めました!明日もこんな天気になってくれるとうれしいですねゝ(^O^)丿
そんなわけで、M1の時に講義で習ったJSP*1を用いてちゃっちゃと検索システムを構築しています。
講義のときはいろいろと日程と方針のとり間違いでえらい目に遭いましたが、今回はもう拡張性や汎用性なんて何のその。バリバリの環境依存プログラムで、とりあえず8割くらいは作成できました。あとは、最後の仕上げとデザインの修正に手をつけるだけです。
JSPを使ってみて分かったんですが、かなりPHPの勉強が役に立ってるな?って思いました。セッション管理やJSPの書き方とか、ちょっとした違いだけなんですぐに使えます。問題はデプロイ*2した時にどんな例外が発生するかをもうちょっと検討しないといけないんですけど、それはもうちょっと先の課題と言うことで。
ともかく時間がないので、理想に溺れて溺死しないように邁進するのみです。
探しても探してもわいてくるバグ。今回のバグはかなり難しい!と自負できます。 これはもう、設計段階でどれだけ例外的な場合を考えることができるかにかかっています。 完璧なアルゴリズムに則ってさっさと組んでしまいたいです。
さて、そんなわけでこのブログの読者様にもぜひ挑戦してみて欲しいです。 ちなみに本来のコードを改造して、ちょっとだけ解きやすくなっています。 クラス名が適当なのは無視ということで...。
class Entry { private String id; private double value; public static Comparator<Entry> ID_ASCEND_COMP; // getter, setter は定義済みとします。 } class Application { // 問題のメソッド public List<Entry> merge(List<Entry> list1, List<Entry> list2 ){ Collections.sort(list1, Entry.ID_ASCEND_COMP); Collections.sort(list2, Entry.ID_ASCEND_COMP); Iterator<Entry> it1 = list1.iterator(); Iterator<Entry> it2 = list2.iterator(); Entry e1 = null; Entry e2 = null; List<Entry> merged = new ArrayList<Entry>(); while(it1.hasNext() && it2.hasNext()){ if(e1==null) e1 = it1.next(); if(e2==null) e2 = it2.next(); int key = Entry.ID_ASCEND_COMP.compare(e1,e2); if(key<0){ merged.add(e1); e1 = null; } else if(key==0) { e1.setValue(e1.getValue()+e2.getValue()); merge.add(e1); e1 = null; e2 = null; } else { merged.add(e2); e2 = null } } if(e1!=null) merged.add(e1); if(e2!=null) merged.add(e2); while(it1.hasNext()) merged.add(it1.next()); while(it2.hasNext()) merged.add(it2.next()); return merged; } }
で、このメソッドが何をしているかというと、引数に与えられた2つのコレクションを1つにまとめるということをしています。ただし、IDが重複しているインスタンスがあれば、片方のインスタンスに value を加算してそれを追加するというメソッドです。ちなみに、list1とlist2がnullの場合は考えなくても構いません。(NullPointerExceptionが発生して終了するだけなんで。)また、ID_ASCEND_COMPは、Entryのidをソーとキーとして昇順に並び替えるComparatorです。*3
昨日、あまりに実験結果の評価が悪かったのでプログラムの見直し+実験結果の見直しをしていました。そしたらやっぱりいました、あの嫌なやつ。バグが潜んでいました。今回のは、これまでバグの確認のために使っていたデータ以外の、本番用のデータで確認したらけっこうあっさり分かってしまいました。これはちゃんとテストをしろよ!という神からの思し召しなんでしょうか。それにしても、これまでこんなにバグが潜んでいたのかを思うと凹みます。
しかも間違えていたのが、コレクション中の最小値を見つける部分という、かなり情けない場所。やっぱり例外処理をちゃんとするべきですね。
double min(Collection<Result> col) { double min = Double.MAX_VALUE; for(Result r : col) { min = r.getValue() < min ? r.getValue() : min; } return min; }
はい、これが問題のソースコードです。一見正しそうに見えますが、ちょっと処理が抜け落ちています。さて、どこでしょう…。
大学での研究を行うために、Cygwin上でPerlのスクリプトを実行することにしました。*4
これまではLinux上で動かすだけだったので、PerlからJavaプログラムを呼び出しても
全然問題なかったんですが、Cygwinになるとちょっと厄介な問題が発生します。
その問題というのは、PerlとJavaでパスの指定の仕方が異なるという点です。
Perlでは、よくCygwinでも使われている /cygdrive/c/(以下略) という形式で書くことができます。
また、スクリプトが存在する位置から見た相対パスでももちろん指定することができます。
しかし、このPerlスクリプトからJavaプログラムを呼び出した場合は、Windows形式で
直接指定しないといけません。(例えば、c:/Documents\ and\ Settings/hogehoge/ とか。)
なので、Perlスクリプト用のパスとJavaプログラム用のパスを別々に考えないといけないわけです。
ウェブ上を探してみると、Javaプログラムのためにパスを変換してくれるラッパー
アプリケーションがあるようなんですが、まだ試していません。
これがうまく動作するなら、とても便利そうなんですけどね。
なんとかならないんでしょうか、このCygwinの仕様。
さっきやっと研究用プログラムのデバッグが終了して、実際に走らせられる状態にまで持ってこれました。これでほぼJavaのプログラムを書くのは終了ということで、あとは実験スクリプトと論文に着手していく感じになります。のろのろ走るプログラムともこれでさよならですゝ(^O^)丿
[blog] 長丁場の終了 - LostMemories
前回の記録から1週間以上も経っているわけですが、これまで何に苦戦していたかというと、現行のプログラムにも実はバグが存在していて、それが高速化プログラムのテストの動作チェックを妨げていた点です。しかも比較に大きく動作に影響する場所だったりしたので、原因を追及していくことが難しかったのです。で、今日はその現行プログラムのバグも無事にとれ、高速化プログラムがちゃんと動くことが確かめられたというわけです。
…実は、高速化プログラムには現行プログラム以上のバグがあったんですけどね(;´д⊂
とにもかくにもプログラムは完成したので、明日からは新しいプログラムでガリガリ計算させる予定です。
Javaで行列式を計算させるのに一番手っ取り早いのはフリーのライブラリを利用することでしょう。ですが、そのようなことができない場合*5、自分でソースコードを書く必要があります。そのことについて、ちょっと前に話に挙がっていたので作ってみました。
public class Matrix { // 行列式を求めるメソッド public static double det(double[][] args){ final int size = args[0].length; for(int i=0; i<args.length; i++){ if(args[i].length!=size) throw new IllegalArgumentException(); } double det = 0; for(int i=0; i<size; i++){ double rightdown = 1; double leftdown = 1; for(int j=0; j<size; j++){ rightdown *= args[(i+j)%size][j%size]; leftdown *= args[(i+size-j)%size][j%size]; } det += rightdown - leftdown; } return det; } // テストコード public static void main(String[] args){ double[][] matrix = new double[][]{ {1,2,3}, {4,5,6}, {7,8,9} }; System.out.println(det(matrix)); } }
これは行列式を計算させる時によく用いられるサラスの方法を実装したものです。引数として配列の配列を渡していますが、この配列のサイズは全て同じでないといけません。また、どちらが行でどちらが列とかそんなことは気にしなくても正しい結果が得られます*6。
注意しなければいけないのが、サラスの方法では4次以上の正方行列の行列式は計算できないこと。4次以上の場合は、余因子展開をするなどして次数を落とす必要があります。
ちなみに、このコードはBSDライセンスです。とは言っても、普通に書いても同じようなコードになるんで、適当に利用してやってください。このコードで発生した不具合については、なんら責任を負いません。また、これに基づいたコードについては著作権表示を忘れないようにお願いします*7。
ふとした思い付きで、Integer を返すメソッドが null を返したとき、プリミティブな int 型にアンボクシングさせるようなコードを書くとどうなるか疑問に思ったので試してみました。
public static void main(String[] args){ int i = getNullInteger(); System.out.println("i:"+i); } private static Integer getNullInteger(){ return null; }
例えばこんな感じ。
で、実行してみると、NullPointerException が返ってきました。
勝手に NullPointerException を返してプログラムが止まってしまうと困る場合は多いと思うので、メソッドの呼出し元で null チェックをするか、メソッドで null を返すのではなくて、キャッチされる例外をスローするようにしたいところですね。
ここ最近は、JavaのStringインスタンスを切ってはつなげるコードをひたすら書いてます。1回書いて、見事に失敗。もう1回作り直しているところです。それにしても、これって簡単に書く方法ってないんですかね。
やっぱりパーザもどきを作ろうと思ったら、String→char[]に変換して、ひたすら置換するくらいしかないんだろうか。毎回Stringクラスのsubstringメソッドを呼び出して結合するなんてことをしてたら、かなり面倒だし。いい方法を模索中です。
「Java World」という月刊の本に「良いプログラムの条件」に関して記述があったのでメモしておきます。この本は結構タメになるので、Javaに興味がある方は読んでみるといいかも知れません。
そこにはこんな記述がありました。
「クラスやメソッドが適切な単位で分割されており、それらは命名規則にしたがって(中略)」−実は、こうした事柄は、「良いプログラム」に直結する条件ではありません。(中略)ユーザーの視点で見たときに評価の高いプログラムが「良いプログラム」であり、その評価対象となるポイントがプログラムの価値を決めるポイントだと言えます。
その「ポイント」というのが、ユーザーの目的に合っているか(合目的性)、プログラムによって効率があがるか(生産性)、ユーザーにとって使いやすいか、プログラムの出力が適しているか(クォリティ)、情報の漏洩に対して対策があるか(安全性)などです。
確かにこの記事は的を得ていて、本当なら重要視されるはずのユーザーからの視点がなおざりにされていることの警鐘であるともいえます。
URL : Java World Online http://www.javaworld.jp/
Javaの1.5 ( 5.0 ) にはCloseableというインターフェースが導入されています。このインターフェース自体は、閉じることができるソースに対して実装されています。宣言されているメソッドは、close()です。Reader や Writer の内部では、リソースへアクセスできる変数に null を代入することによって切り離している場合が多いです。
それに対して、1.0から存在している Cloneable は、インスタンスのコピーを生成できるクラスが実装しています。このインターフェース自体はメソッドは定義していませんが、Objectクラスのclone()をオーバーライドすることによってcloneメソッドが使用できるようになります。Cloneableインターフェースを実装していない場合はcloneメソッドを呼び出しても、例外(CloneNotSupportedException)がスローされます。
さて、見た目はよく似ていますが、使い方はかなり違います。基本的に、よく知られているクラスの中ではCloneableは実装されていない場合が多いので、一度確認してみると良いかと思います。
Javaの拡張for文と、PHPのforeach文では使い方がけっこう違うことに気づきました。(今さらな話ですが・・・。)
Javaの5.0から導入された拡張for文は以下のような記述をします。
for($var : $collection){ ・・・・ }
それに対して、PHPでは以下のようになってます。
foreach($array as $var){ ・・・・ } foreach($array as $key => $val){ ・・・・ }
ちょっと油断すると忘れるんですよね?。ってことで、メモっときます。
この前書いた「RSA暗号」のエントリについて、学科の友達と話していたら、「Javaのio関連のクラスに暗号化のクラスをラッピングできたらいい感じじゃないか?」という話題が出てきたので、調べてみました。
検索で引っ掛けてみると、JavaAPIの中のページに詳細な情報がありました。
http://java.sun.com/j2se/1.4/ja/docs/ja/guide/security/CryptoSpec.html
java.securityパッケージは、RSA暗号も含めた暗号化に関するクラスが含まれています。でも、さすがにjava.io.*Streamをラッピングしたらすぐに暗号が送れるようになるというわけではなさそうです。公開鍵暗号で通信するとしたら、相手から公開鍵をもらってこないといけないし、ソケットでの通信と同じような前準備をもう一回しないとダメそうです。ioをラッピングしてくれそうなクラスは、自作しないとダメっぽいですね。
とりあえず現段階ではこうかと思いますが、本当は違うのかも。また調べてみます。
テストということでそっちに気を取られているうちに、えらい仕事がたまってしまいました。特に編曲は合宿中にはあまりできない、かつ合宿中に1回はその曲を合わせたいので、なんとしてでも今日中に完成させないといけません。後半分とはいえ、結構しんどいです。あと、プロジェクトでFFT*8の実装をしないといけないので、それに関しても調べないといけないです。はあ、考えただけでもため息が出ます。
紹介文っていうのは、クラブの4回生の紹介文のことです。3回生で書くことになっていたのですが、あまりにネタ切れな状態でM氏に丸投げしようとしたのですが、作戦が失敗して結局書くことになりました。ちょっと思いつかなかったので、先輩の未来を想定した話を書いてみました。想定したといっても、今を投影しているような話なんですけどね。きっと文体見たら誰が書いたかすぐ分かります。
最近、ゲームのプログラムにはまりすぎて、サイトの管理がおろそかになっていたので、更新されない場所とかを削除したりとかも今日してみました。Javaでもそうなんですが、昔のソースはやっぱり汚くて、全部直してたらきりがないので、適当なところで打ち切ってます。HTMLのソースもオブジェクト指向にのっとって考えると、管理がしやすいみたいなので、そのことをまた書いていくかもしれません。
さて、明日は合宿。初見大会は「ブラ1」と「ハイバリ(「ハイドンの主題による変奏曲」の略)」らしいです。とりあえず個人的には2ndにたくさんのせてくれたら満足です。はい。