アカウント名:
パスワード:
リフレクションを使えば、ってのがあまりリフレクションを使ったことがなくてピンとこなかったので、添削してもらうつもりで。
String ret;Class clazz = KeyEvent.class;Field[] fields = clazz.getFields();for (Field field : fields) { try { if (keyCode == field.get(null)) { ret = field.getName(); } } catch (Exception e) { }}
こんな感じ?或いは、今ならJava8だからlambdaで
Class clazz = KeyEvent.class;List fields = Arrays.asList(clazz.getFields());String ret = fields.stream().filter(field -> { try { return keyCode == field.get(null); } catch (Exception e) { return false; }}).findAny().get().getName();
こうとか?Field型の中身を取ってくるのに例外処理を書かなきゃいけなくて、全然簡潔にならなかったけど・・・。
http://twitpic.com/e9bo50 [twitpic.com]http://twitpic.com/e9boe9 [twitpic.com]
本当に適切な代案はあるのか?代案コードの掲載に1pとして、代案コードの解説を残り3pで出来るのか?多分アホみたいに列挙したのは改造が簡単だからだろうと思われるのだが、そうする場合にどうするべきかについてまで説明はできるのか?
具体的なコードを元に、その辺を話そうぜ、ってフリなんだけど?
KeyName = KeyNameArr(enum.keycode001)KeyCode = KeyCodeArr(enum.keyname001)
Javaは知らん素人ですが、分岐とかループなんか使わなくてもこんな感じのマッピングで一発なんじゃ。
HashMapはこの数だとパフォーマンス的に単純分岐のコードに負ける可能性があるし、65536のString配列はメモリの無駄だろうし。
そもそもIDを文字に変換してどうするの? デバッグメッセージ用?まさか、文字列でIDを比較とかしないよね?要件がちゃんと分かればもっとよい代替案があるかもよ。
そもそもIDを文字に変換してどうするの? デバッグメッセージ用?。
SQLクエリの動的生成用、とか?
素直なので、Excel でちゃんと本の通りのコードを生成してソースに貼り付けます。
最初に考えるべきなのはアルゴリズムじゃなくてデータ構造だ、って、ばっちゃが言ってた(cf. 実装 [grepcode.com])
これでどうかな?https://gist.github.com/anonymous/b8fbebc92117d15caba5 [github.com]
> put( 8,"KEYCODE_1");
"KEYCODE_1"のIDが本当に8でよいのかどのようにコードレビューしますか?
> "KEYCODE_1"のIDが本当に8でよいのかどのようにコードレビューしますか?・ω・ 。o ( ドキュメントを見るんだ! )
KeyEvent | Android Developers [android.com]
public static final int KEYCODE_1Added in API level 1Key code constant: '1'key.Constant Value: 8 (0x00000008)
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.a... [grepcode.com]
put( KeyEvent.KEYCODE_1,"KEYCODE_1");の方が良さそう
でも、結局ずらずら書くのは一緒で、元のソースに比べて良いかと言われると微妙では
結局のところこの話の問題点は以下の2点に集約出来る。1. メンバ変数(定数)の値とメンバ変数名の対応を全て列挙する作業が手作業であるという問題。2. 検索が線形検索になっていることによる検索コストがO(N)という問題。
#2651418 [developers.srad.jp]について見てみると、1. は AWK スクリプトで自動生成しているのでクリア出来ている。ただし、実行環境の定数がコンパイル時と変わってしまっていた場合に不具合を生じる。せめて
あんまり核心付くとマイナス付けられますよ。Javaの世界では、コードやデータ生成のマクロ、なんて書いた日にはマイナスなんですから。
#トピ主のリアルを観察したほうが楽しそうです。
ベンチマークなしに闇雲に計算量のオーダーだけ減らしても意味ないと言う主張なら賛同だが、== の比較による単純な代入をするために if else 文が数ページの長さ続くのはちょっとおかしい。こういう場合は普通 Key-Value の対応にして、適切にコンテナを選ぶことで、実行速度を最適化するのが定石。
ぶっちゃけ、開発時の動作確認のためだけに使うので、最小の労力で必要な出力が得られれば十分とか、正当な理由がついていて、CDやwebからコピーしろと指示があれば、目くじらを立てるコードじゃないけど、入門書で数ページも割くのは、ページの無駄使いと言われても仕方ない。
自分のコードなら、別途辞書を作って1行で済ますの一択。ただ初心者向けのサンプルコードだったらどうかなぁ。
よし。俺に任せろ。ここはswitchで..。
case KeyEvent.KEYCODE_1: ret = "KEYCODE_1"; break;case KeyEvent.KEYCODE_2: ret = "KEYCODE_2"; break;...
隊長、大変です。4ページより長くなってしまいました。
ここは、C/C++ならマクロの出番なんでしょうけどねぇ…
#define KEYTOSTRING(code) case KeyEvent.KEYCODE_##code: ret = "KEYCODE_"#code; breakKEYTOSTRING(1);KEYTOSTRING(2);KEYTOSTRING(3);…
よし、こうするんだ!
case KeyEvent.KEYCODE_1: ret = "KEYCODE_1"; break;case KeyEvent.KEYCODE_2: ret = "KEYCODE_2"; break;
# コードレビューでキレられる気がするのでAC
テーブルを使うといいのでしょうか?
String[][] KeyEventTable = {{KeyEvent.KEYCODE_1, "KEYCODE_1"}, {KeyEvent.KEYCODE_2, "KEYCODE_"}, …};for (int i = 0 ;; i++) if (keyCode == KeyEventTable[i][0]) ret=KeyEventTable[i][1];
2行で書けた ^^/
> 2行で書けた ^^/
だが待って欲しい。それを2行と言うなら、原典は1つのif文だから1行ではないだろうか。
keyCodeがsignedで負値だった場合への対応とか、想定外の値をとった場合の対応が必要そう。
8bitの時は全パターン網羅しておくのも大した手間じゃなかったが、16bit以上で網羅は・・やったことはあるんだけどw
色々突っ込みが入ったので直してみました。
// keyCodeはintでKeyEventで定義される値以外が入ってはいけない。違反したときの戻り値は不定String[][] KeyEventTable = {{Integer.toString(KeyEvent.KEYCODE_1), "KEYCODE_1"}, {Integer.toString(KeyEvent.KEYCODE_2), "KEYCODE_2"}};for (int i = 0 ; i KeyEventTable.length ; i++) if (keyCode == Integer.parseInt(KeyEventTable[i][0])) ret=KeyEventTable[i][1];
仕様を定義すればいいのですよね。1行増えてしまった(;_;)
あちこちで、「switch使え」とか「リフレクションって言ってるやつはわかってない」って言ってるのは、「線形探索するな」って意味だと思いますよ。せっかくソート済みのテーブルがあるなら、二分木探索しないと。
なるほど。
TreeMapとか
if (keyCode 32767) if (keyCode 16383) if (…とかやればいいんですね。
この例題だと、単に"KEYCODE_1"を返してるだけですが、教科書ということを踏まえればあとあとには押されたキーに応じた処理をそこに埋め込むようになるのではないかと予想します。
それならば、この単純な配列での実装は如何なものかと思うのです・・・・。
Eclipse: 129個のエラーがあります。
懲戒解雇通知書
貴殿が2014年08月05日 11時33分に提示したプログラムは、当社就業規則第35条(当社品質基準に達しないプログラムの作成の禁止)に該当する違反行為であるとともに、あまつさえ「2行で書けた ^^/」などと、その行為を誇る様な言辞を弄する事は、当社就業規則第36条(違反行為の誇示及び正当化の禁止)に該当する違反行為であります。従いまして、当社就業規則第63462条の規則に基づき、2014年08月05日 12時04分付をもって、貴殿を懲戒解雇することとし、ここに通知いたします。
株式会社 まともなソフト屋 代表取締役 真朋祖太屋
#2651220AC殿
解雇ですか?ちゃんと直したのでお許しお。
三項演算子を使えば1行だよ。
ret = keyCode == KeyEvent.KEYCODE_1 ? "KEYCODE_1" : keyCode == KeyEvent.KEYCODE_2 ? "KEYCODE_2" : ...;
分かりやすく書くと、下のようになるけど、自動生成するのが当たり前だから、1行で問題ないでしょ?
定数同士の置き換えだから普通にマップで書くそもそも置き換え必要ないような。
ret = KeyEvent.keyCodeToString(keyCode);
調べてなくてすみませんがーkeyCodeToStringの中身はどうなってるのだ?
調べてないけどリフレクションAPI使ってMap型にテーブルを作っておいて、変換時にはテーブルを引く、って実装じゃないかな?KeyEventクラスにこのメソッドがなければそうやって実装するし。
調べてみた…テーブルを作って引くのはあってたけどテーブル自体は手動で作ってた…
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.a... [grepcode.com] KeyEvent.keyCodeToString(int keyCode) の実装
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.a... [grepcode.com] テーブルの作成処理
SparseArrayを使っているようです。データ数から考えて、HashMapより速いという判断でしょう。
恐らくページ数を楽して稼ぎたい、という意図だと思われるので、}else if ( key_code == KeyEvent.KEY_CODE1 ){ ret = "KEY_CODE_1";}else if ( key_code == KeyEvent.KEY_CODE2 ){ ret = "KEY_CODE_2";を}else if ( key_code == KeyEvent.KEY_CODE1 ){ ret = "KEY_CODE_1";}else if ( key_code == KeyEvent.KEY_CODE2 ){ ret = "KEY_CODE_2";や}else if ( key_code == KeyEvent.KEY_CODE1 ){ ret = "KEY_CODE_1";}else if ( key_code == KeyEvent.KEY_CODE2 ){ ret =
こんなもんですかね。https://twitter.com/vjroba/status/495245672975564800 [twitter.com]https://twitter.com/vjroba/status/495246734474215425 [twitter.com]
こんなもんかと。https://twitter.com/vjroba/status/495245672975564800 [twitter.com]https://twitter.com/vjroba/status/495246734474215425 [twitter.com]
定数の判定は変数名で判別すればもう4行削れます。初心者向けの本でリフレクション使うのが正しいとは思いませんが、そもそもリフレクション使わないとまともなコードにならないような課題を選んだことが間違ってると思います。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
にわかな奴ほど語りたがる -- あるハッカー
文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:2)
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
リフレクションを使えば、ってのがあまりリフレクションを使ったことがなくてピンとこなかったので、添削してもらうつもりで。
String ret;
Class clazz = KeyEvent.class;
Field[] fields = clazz.getFields();
for (Field field : fields) {
try {
if (keyCode == field.get(null)) {
ret = field.getName();
}
} catch (Exception e) {
}
}
こんな感じ?或いは、今ならJava8だからlambdaで
Class clazz = KeyEvent.class;
List fields = Arrays.asList(clazz.getFields());
String ret = fields.stream().filter(field -> {
try {
return keyCode == field.get(null);
} catch (Exception e) {
return false;
}
}).findAny().get().getName();
こうとか?
Field型の中身を取ってくるのに例外処理を書かなきゃいけなくて、全然簡潔にならなかったけど・・・。
ネタ元で代案出てるけど? (スコア:1)
http://twitpic.com/e9bo50 [twitpic.com]
http://twitpic.com/e9boe9 [twitpic.com]
Re:ネタ元で代案出てるけど? (スコア:1)
本当に適切な代案はあるのか?
代案コードの掲載に1pとして、代案コードの解説を残り3pで出来るのか?
多分アホみたいに列挙したのは改造が簡単だからだろうと思われるのだが、
そうする場合にどうするべきかについてまで説明はできるのか?
具体的なコードを元に、その辺を話そうぜ、ってフリなんだけど?
Re: (スコア:0)
KeyName = KeyNameArr(enum.keycode001)
KeyCode = KeyCodeArr(enum.keyname001)
Javaは知らん素人ですが、分岐とかループなんか使わなくても
こんな感じのマッピングで一発なんじゃ。
Re: (スコア:0)
HashMapはこの数だとパフォーマンス的に単純分岐のコードに負ける可能性があるし、
65536のString配列はメモリの無駄だろうし。
そもそもIDを文字に変換してどうするの? デバッグメッセージ用?
まさか、文字列でIDを比較とかしないよね?
要件がちゃんと分かればもっとよい代替案があるかもよ。
Re: (スコア:0)
そもそもIDを文字に変換してどうするの? デバッグメッセージ用?。
SQLクエリの動的生成用、とか?
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
素直なので、Excel でちゃんと本の通りのコードを生成してソースに貼り付けます。
マクロの基本は検索置換(by y.mikome)
Re: (スコア:0)
最初に考えるべきなのはアルゴリズムじゃなくてデータ構造だ、って、ばっちゃが言ってた
(cf. 実装 [grepcode.com])
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
これでどうかな?
https://gist.github.com/anonymous/b8fbebc92117d15caba5 [github.com]
Re: (スコア:0)
> put( 8,"KEYCODE_1");
"KEYCODE_1"のIDが本当に8でよいのかどのようにコードレビューしますか?
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:2)
> "KEYCODE_1"のIDが本当に8でよいのかどのようにコードレビューしますか?
・ω・ 。o ( ドキュメントを見るんだ! )
KeyEvent | Android Developers [android.com]
public static final int KEYCODE_1
Added in API level 1
Key code constant: '1'
key.Constant Value: 8 (0x00000008)
Use the Source Luke (スコア:0)
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.a... [grepcode.com]
put( KeyEvent.KEYCODE_1,"KEYCODE_1");
の方が良さそう
Re: (スコア:0)
でも、結局ずらずら書くのは一緒で、元のソースに比べて良いかと言われると微妙では
Re: (スコア:0)
結局のところこの話の問題点は以下の2点に集約出来る。
1. メンバ変数(定数)の値とメンバ変数名の対応を全て列挙する作業が手作業であるという問題。
2. 検索が線形検索になっていることによる検索コストがO(N)という問題。
#2651418 [developers.srad.jp]について見てみると、
1. は AWK スクリプトで自動生成しているのでクリア出来ている。ただし、実行環境の定数がコンパイル時と変わってしまっていた場合に不具合を生じる。せめて
Re: (スコア:0)
Re: (スコア:0)
あんまり核心付くとマイナス付けられますよ。
Javaの世界では、コードやデータ生成のマクロ、なんて書いた日にはマイナスなんですから。
#トピ主のリアルを観察したほうが楽しそうです。
Re: (スコア:0)
ベンチマークなしに闇雲に計算量のオーダーだけ減らしても意味ないと言う主張なら賛同だが、== の比較による単純な代入をするために if else 文が数ページの長さ続くのはちょっとおかしい。こういう場合は普通 Key-Value の対応にして、適切にコンテナを選ぶことで、実行速度を最適化するのが定石。
ぶっちゃけ、開発時の動作確認のためだけに使うので、最小の労力で必要な出力が得られれば十分とか、正当な理由がついていて、CDやwebからコピーしろと指示があれば、目くじらを立てるコードじゃないけど、入門書で数ページも割くのは、ページの無駄使いと言われても仕方ない。
Re: (スコア:0)
自分のコードなら、別途辞書を作って1行で済ますの一択。
ただ初心者向けのサンプルコードだったらどうかなぁ。
Re: (スコア:0)
よし。俺に任せろ。ここはswitchで..。
case KeyEvent.KEYCODE_1:
ret = "KEYCODE_1";
break;
case KeyEvent.KEYCODE_2:
ret = "KEYCODE_2";
break;
...
隊長、大変です。4ページより長くなってしまいました。
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:2)
ここは、C/C++ならマクロの出番なんでしょうけどねぇ…
#define KEYTOSTRING(code) case KeyEvent.KEYCODE_##code: ret = "KEYCODE_"#code; break
KEYTOSTRING(1);
KEYTOSTRING(2);
KEYTOSTRING(3);
…
Re: (スコア:0)
よし、こうするんだ!
case KeyEvent.KEYCODE_1:
ret = "KEYCODE_1"; break;
case KeyEvent.KEYCODE_2:
ret = "KEYCODE_2"; break;
# コードレビューでキレられる気がするのでAC
Re: (スコア:0)
テーブルを使うといいのでしょうか?
String[][] KeyEventTable = {{KeyEvent.KEYCODE_1, "KEYCODE_1"}, {KeyEvent.KEYCODE_2, "KEYCODE_"}, …};
for (int i = 0 ;; i++) if (keyCode == KeyEventTable[i][0]) ret=KeyEventTable[i][1];
2行で書けた ^^/
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
> 2行で書けた ^^/
だが待って欲しい。
それを2行と言うなら、原典は1つのif文だから1行ではないだろうか。
keyCodeがsignedで負値だった場合への対応とか、想定外の値をとった場合の対応が必要そう。
8bitの時は全パターン網羅しておくのも大した手間じゃなかったが、
16bit以上で網羅は・・やったことはあるんだけどw
Re: (スコア:0)
色々突っ込みが入ったので直してみました。
// keyCodeはintでKeyEventで定義される値以外が入ってはいけない。違反したときの戻り値は不定
String[][] KeyEventTable = {{Integer.toString(KeyEvent.KEYCODE_1), "KEYCODE_1"}, {Integer.toString(KeyEvent.KEYCODE_2), "KEYCODE_2"}};
for (int i = 0 ; i KeyEventTable.length ; i++) if (keyCode == Integer.parseInt(KeyEventTable[i][0])) ret=KeyEventTable[i][1];
仕様を定義すればいいのですよね。
1行増えてしまった(;_;)
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
あちこちで、「switch使え」とか「リフレクションって言ってるやつはわかってない」って言ってるのは、「線形探索するな」って意味だと思いますよ。せっかくソート済みのテーブルがあるなら、二分木探索しないと。
Re: (スコア:0)
なるほど。
TreeMapとか
if (keyCode 32767)
if (keyCode 16383)
if (…
とかやればいいんですね。
Re: (スコア:0)
この例題だと、単に"KEYCODE_1"を返してるだけですが、教科書ということを踏まえれば
あとあとには押されたキーに応じた処理をそこに埋め込むようになるのではないかと予想します。
それならば、この単純な配列での実装は如何なものかと思うのです・・・・。
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
Eclipse: 129個のエラーがあります。
svn-init() {
svnadmin create .svnrepo
svn checkout file://$PWD/.svnrepo .
}
Re: (スコア:0)
懲戒解雇通知書
貴殿が2014年08月05日 11時33分に提示したプログラムは、当社就業規則第35条
(当社品質基準に達しないプログラムの作成の禁止)に該当する違反行為であるとともに、
あまつさえ「2行で書けた ^^/」などと、その行為を誇る様な言辞を弄する事は、
当社就業規則第36条(違反行為の誇示及び正当化の禁止)に該当する違反行為であります。
従いまして、当社就業規則第63462条の規則に基づき、2014年08月05日 12時04分付をもって、
貴殿を懲戒解雇することとし、ここに通知いたします。
株式会社 まともなソフト屋
代表取締役 真朋祖太屋
#2651220AC殿
Re: (スコア:0)
解雇ですか?
ちゃんと直したのでお許しお。
Re: (スコア:0)
三項演算子を使えば1行だよ。
分かりやすく書くと、下のようになるけど、自動生成するのが当たり前だから、1行で問題ないでしょ?
Re: (スコア:0)
定数同士の置き換えだから普通にマップで書く
そもそも置き換え必要ないような。
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
Re: (スコア:0)
ret = KeyEvent.keyCodeToString(keyCode);
Re: (スコア:0)
調べてなくてすみませんがー
keyCodeToStringの中身はどうなってるのだ?
Re: (スコア:0)
調べてないけどリフレクションAPI使ってMap型にテーブルを作っておいて、変換時にはテーブルを引く、って実装じゃないかな?
KeyEventクラスにこのメソッドがなければそうやって実装するし。
Re:文句を言う資格のある奴はより良い案を出した奴だけだ。 (スコア:1)
調べてみた…テーブルを作って引くのはあってたけどテーブル自体は手動で作ってた…
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.a... [grepcode.com] KeyEvent.keyCodeToString(int keyCode) の実装
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.a... [grepcode.com] テーブルの作成処理
Re: (スコア:0)
SparseArrayを使っているようです。
データ数から考えて、HashMapより速いという判断でしょう。
Re: (スコア:0)
恐らくページ数を楽して稼ぎたい、という意図だと思われるので、
}else if ( key_code == KeyEvent.KEY_CODE1 ){
ret = "KEY_CODE_1";
}else if ( key_code == KeyEvent.KEY_CODE2 ){
ret = "KEY_CODE_2";
を
}
else if ( key_code == KeyEvent.KEY_CODE1 ){
ret = "KEY_CODE_1";
}
else if ( key_code == KeyEvent.KEY_CODE2 ){
ret = "KEY_CODE_2";
や
}
else if ( key_code == KeyEvent.KEY_CODE1 )
{
ret = "KEY_CODE_1";
}
else if ( key_code == KeyEvent.KEY_CODE2 )
{
ret =
Re: (スコア:0)
こんなもんですかね。
https://twitter.com/vjroba/status/495245672975564800 [twitter.com]
https://twitter.com/vjroba/status/495246734474215425 [twitter.com]
Re: (スコア:0)
こんなもんかと。
https://twitter.com/vjroba/status/495245672975564800 [twitter.com]
https://twitter.com/vjroba/status/495246734474215425 [twitter.com]
定数の判定は変数名で判別すればもう4行削れます。
初心者向けの本でリフレクション使うのが正しいとは思いませんが、
そもそもリフレクション使わないとまともなコードにならないような課題を
選んだことが間違ってると思います。