- PR -

デバッグ時に HashMap/HashSet の中身を素早く見る方法は?

投票結果総投票数:19
HashMap/HashSet をひたすら覗く 3 15.79%
デバッグ用の Map/Set を作って使う 1 5.26%
便利なライブラリーがある 1 5.26%
eclipse に 14 73.68%
  • 投票は恣意的に行われます。統計的な調査と異なり、投票データの正確性や標本の代表性は保証されません。
  • 投票結果の正当性や公平性について、@ITは一切保証も関与もいたしません。
投稿者投稿内容
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-03-10 11:35
eclipse などでデバッグしている時に、配列や ArrayList の中身は簡単に覗けるのですが、HashMap や HashSet の中身はその内部構造が複雑であり、中になにが入っているのかを探すのが一苦労です。
みなさまはどうやってデバッグされているのでしょうか?Hash を使わずに、Hash を使わない自前のシンプルな Map や Set の実装クラスを作って、それを一時的に使えば良いのでしょうが、本番時に HashMap/HashSet に切り替えるのも面倒です。equals と hashCode のオーバーライドの間違いなども発見しにくくなるような気がします。
望むのとしては eclipse のデバッガーを動かすと、自動的に HashMap/HashSet のデバッグバージョンにすりかえて動いてくれるようなことを期待するのですが、それに近いものってなにかないでしょうか。

投票機能:
・HashMap/HashSet をひたすら覗く
・デバッグ用の Map/Set を作って使う
・便利なライブラリーがある
・eclipse にそういう機能がある

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-03-10 11:54
List/Map/SetはtoString()で済ませることが多いですね。
配列クラスはさすがにデバッガですが。

バッドノウハウかもしれませんが、
本番とデバッグで切り替えたいのであれば、ファクトリを使うのは如何でしょう。
例えば、Map map = MapFactory.newMap();
本番とデバッグでファクトリの中だけ差し替えれば大丈夫です。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-10 17:05
3.2系だとブレークした際のオブジェクトの内容が見やすくなりましたね。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-03-10 17:37
引用:

かつのりさんの書き込み (2007-03-10 11:54) より:
List/Map/SetはtoString()で済ませることが多いですね。


コレクションの要素に入れるクラスで toString() を定義しておけば(あるいは toString() を持っているクラス(String や Integer など)を使えば)、良いのですね。しかし、クラスが何十個もフィールドを持っていたり、クラスAがクラスBを集約していたりすると、toString() が定義しきれないので悩んでいます。
引用:

かつのりさんの書き込み (2007-03-10 11:54) より:
バッドノウハウかもしれませんが、
本番とデバッグで切り替えたいのであれば、ファクトリを使うのは如何でしょう。
例えば、Map map = MapFactory.newMap();
本番とデバッグでファクトリの中だけ差し替えれば大丈夫です。


切り替えが面倒、ということと、ソースコードをパッと見たときやあるいはソースコード内を検索する際に、HashMap を使うことを予期していることが分かりにくい、ということでちょっと億劫になっています。あと、人が書いたコードの中までデバッガーで追いかけるような場合は、対処できない、ということもあります。(事前に分かればそこだけファクトリーに差し替えてからデバッガーを起動すれば良いわけですが。)
引用:

nagiseさんの書き込み (2007-03-10 17:05) より:
3.2系だとブレークした際のオブジェクトの内容が見やすくなりましたね。


これは良く分かりませんでした。普段、3.2 を使っているのですが新機能があるのでしょうか。

結局、かつのりさんの toString() ということにヒントを得て、つぎのようなやりかたなら便利かな、と考えました。
コード:

import java.util.*;

class SetList {

private Object[] array;

public SetList(Set set) {
array = new Object[set.size()];
int i = 0;
for (Iterator it = set.iterator(); it.hasNext(); ) {
array[i] = it.next();
i++;
}
}
}

class Foo {

private int x;

public Foo(int argX) {
x = argX;
}

// public String toString() {
// return "(" + "x is " + x + ")";
// }
}

public class Hoge {

public static void main(String[] args) {
Set set = new HashSet();
for (int i = 0; i < 10; i++) {
Foo foo = new Foo(i);
set.add(foo);
}
System.out.println("set = " + set.toString());
}
}


変数 set の中身を見たいときに、eclipse の Expressions のウィンドウの中で "Add Watch Expression" をおこない、そこに、
new SetList(set)
を指定します。
こうすると配列で表示されます。
簡単にするため Set の例を書きましたが、Map もこの応用でできるかなと思っています。

#以下、あとで追加。

nagiseさんが書かれた3.2系のは "Detail Formatter" という機能なのですね。Expressions のウィンドウで右クリックするとこの機能を呼び出せますね。こういう機能があるとは今まで知りませんでした。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}

[ メッセージ編集済み 編集者: unibon 編集日時 2007-03-10 17:46 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-03-10 18:15
デバッガでも文字列表現は見えますので、
System.out.printlnで出力する必要がないですね。

値を示すオブジェクトはCommons-LangのToStringBuilderで予め、
出力時を考慮しておくといいかもしれません。
リフレクション対応のToStringBuilderもあるので、
基底クラス側で定義しておいて、
各値クラスは基底クラスを継承するというのもありでしょう。

すでに進んでしまっているプロジェクトでは難しいかもしれませんが・・・
会議室デビュー日: 2006/10/17
投稿数: 13
投稿日時: 2007-03-10 20:39

AspectJを使って、デバック文,ダンプ等を追加してみるのも手かな。


nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-11 14:26
3.2系からは「変数」のビューに「論理構造の表示」アイコンがついており、
Mapなどのコレクションの表示方法を切り替えることが出来ます。

たとえばTreeMapの場合、通常モードでは
コード:

map
comparator
+ entrySet
keySet
modCount
+ root
size
values


とったフィールドの表示になります。
Map内のエントリを確認するにはrootを開いて
leftとrightのエントリを開いて…と2分木を辿る必要がありました。

「論理構造の表示」モードにすると
コード:

map
+ [0]
+ [1]
- [2]
+ key
+ value
+ [3]


といったように配列のごとくエントリが表示されます。

この機能のおかげで随分とデバッグがやりやすくなりました。
<編集>codeタグをつけました</編集>

[ メッセージ編集済み 編集者: nagise 編集日時 2007-03-11 19:27 ]
ちいにぃ
大ベテラン
会議室デビュー日: 2002/05/28
投稿数: 244
投稿日時: 2007-03-11 15:11
自分の備忘録も兼ねて補足します。

変数ビューの「論理構造の表示」機能については、
Eclipse 3.2の付属のヘルプのTips and Tricks (JDT)
「Logical Structures(論理構造)」や「Detail formatters(詳細フォーマット)」で
説明されています。

これらはJavaの標準ライブラリ以外のクラスに対しても独自に設定することができるようです。

設定画面は以下の場所にあります。(日本語版の場合)
- ウィンドウ -> 設定 -> Java -> デバッグ の「詳細フォーマット」と「論理構造」
英語版では以下の場所にあります。
- Window > Preference > Java > Debug の 「Detail Formatter」と「Logical Structure」

私自身はlog4jに出力するときのために、大抵はtoString()メソッドをオーバーライドしているので、
(製造初期はJakarta Commons LangのToStringBuilder, RefrestionToStringBuilderを使い、
あとで性能に影響する部分だけ手で書き直す)、この機能は使ったことがないのですが、
便利そうです。

スキルアップ/キャリアアップ(JOB@IT)