- OZ
- 常連さん
- 会議室デビュー日: 2006/02/27
- 投稿数: 45
|
投稿日時: 2006-05-12 16:17
お世話になってます。前回、Beanの比較についてでアドバイス頂いたののですが
今回も助言頂ければと思います。
今回実現したい事は、Beanの配列を作成し、その配列を特定のフィールドで
ソートする事なのですがソートの実行方法として、
1.指定されたフィールドに対するソートを行う
2.指定された2つのフィールドに対するソートを行う
を満たしたいのです。
コード: |
|
1 : public Class BeanSamp() {
2 : private int height = 0;
3 : private int weight = 0;
4 : private String blood;
5 :
6 : public setHeight(int i){
7 : height = i;
8 : }
9 :
10: public setWeight(int i){
11: weight = i;
12: }
13:
14: public setBlood(String s){
15: blood = s;
16: }
17:
18: public void getHeight(){
19: return height;
20: }
21:
22: public void getWeight(){
23: return weight;
24: }
25:
26: public void getBlood(){
27: return blood;
28: }
29:
30: }
31:
32: class beanComp1 implements Comparator() {
33: public int compare(Object o1,Object o2){
34: //BeanSampのheightを昇順で比較してintをリターンする実装クラス
35: }
36: }
|
この例でいいますと、予めフィールド「height」でソートする事が分かっていれば、
height用のComparator実装クラス「beanComp1」を準備する事で解決します。
これが、「指定されたフィールド」でソートとなると
・1.の場合、さらに「weight」「blood」用のComparator実装クラスをそれぞれ準備する
・2.の場合、2つのフィールドの組み合わせ数分(例の場合6つ)のComparator実装を準備する
Arrays.sortの引数に指定されたフィールド用の上記Comparator実装クラスを渡す事しか
思いつきません。
1つのComparator実装クラスで比較対照を動的に変更する事は可能でしょうか?
(これが不可能であると、例えば10個のフィールドを持つクラスで指定された3つの
フィールドに対するソートを実行したい場合は、10x9x8=720個のComparator実装クラスを
準備しなければならない事になる・・・)
宜しくお願い致します。
|
- びしばし
- 大ベテラン
- 会議室デビュー日: 2002/03/13
- 投稿数: 181
|
投稿日時: 2006-05-12 16:32
リフレクションでできません ?
Class#getField(String)で名前指定できますし、
Class#getFields()で得た全フィールドから2個でも3個でも組み合わせればいいと思いますよ。
Jakarta Commons-BeanUtilsですでに実装されているかもしれません(私は詳しく見ていないので知りません)。
http://jakarta.apache.org/commons/beanutils/
[ メッセージ編集済み 編集者: びしばし 編集日時 2006-05-12 16:46 ]
|
- yamasa
- ベテラン
- 会議室デビュー日: 2003/02/15
- 投稿数: 80
|
投稿日時: 2006-05-12 17:18
コード: |
|
public class CompositeComparator<T> implements Comparator<T> {
private final Comparator<? super T>[] comparators;
public CompositeComparator(Comparator<? super T>... comparators) {
this.comparators = comparators;
}
public int compare(T o1, T o2) {
for (Comparator<? super T> comparator : comparators) {
int tmp = comparator.compare(o1, o2);
if (tmp != 0) return tmp;
}
return 0;
}
}
|
こんな感じのクラスを作って、
コード: |
|
Comparator<BeanSamp> CMP_HEIGHT = new Comparator<BeanSamp>() {
public int compare(BeanSamp o1, BeanSamp o2) {
return o1.getHeight() - o2.getHeight();
}
};
Comparator<BeanSamp> CMP_WEIGHT = new Comparator<BeanSamp>() {
public int compare(BeanSamp o1, BeanSamp o2) {
return o1.getWeight() - o2.getWeight();
}
};
Comparator<BeanSamp> CMP_BLOOD = new Comparator<BeanSamp>() {
public int compare(BeanSamp o1, BeanSamp o2) {
return o1.getBlood().compareTo(o2.getBlood());
}
};
|
こんな風に基本となるComparatorを用意しておけば、
コード: |
|
Comparator<BeanSamp> cmp_hwb = new CompositeComparator<BeanSamp>(CMP_HEIGHT, CMP_WEIGHT, CMP_BLOOD);
|
こんな感じに任意の組み合わせのComparatorを作れます。
|
- OZ
- 常連さん
- 会議室デビュー日: 2006/02/27
- 投稿数: 45
|
投稿日時: 2006-05-12 18:25
びしばしさん、ありがとうございます。
恥ずかしながらリフレクションという言葉は初めて知ったので、少し調べてみます。
についても調べてみます。
(リフレクションについての概念は調べたのですが、取得したフィールドの型をキャストする方法と、それらの値を比較する方法を調べています)
yamasaさん、ありがとうございます。
これまた恥ずかしいのですが、
引用: |
|
コード: |
|
public class CompositeComparator<T> implements Comparator<T> {
private final Comparator<? super T>[] comparators;
・・・
public class CompositeComparator<T> implements Comparator<T> {
・・・
|
|
というのは構文の表し方でしょうか。
申し訳ございません、宜しくお願い致します。
|
- yamasa
- ベテラン
- 会議室デビュー日: 2003/02/15
- 投稿数: 80
|
投稿日時: 2006-05-13 18:47
引用: |
|
コード: |
|
public class CompositeComparator<T> implements Comparator<T> {
private final Comparator<? super T>[] comparators;
・・・
public class CompositeComparator<T> implements Comparator<T> {
・・・
|
というのは構文の表し方でしょうか。
|
Genericsという構文ですね。まあ、ここら辺は本質的じゃないんで、こういう書き方もあるんだ程度の認識でも構いません。
重要なのは、「内部にComparatorの配列を持ち、そのComparatorで順に比較した結果を返す新たなComparator」というのを定義することで、基本的なComparatorから複雑なComparatorを動的に生成することができる、ということです。
|
- OZ
- 常連さん
- 会議室デビュー日: 2006/02/27
- 投稿数: 45
|
投稿日時: 2006-05-14 14:29
引用: |
|
Genericsという構文ですね。まあ、ここら辺は本質的じゃないんで、こういう書き方もあるんだ程度の認識でも構いません。
重要なのは、「内部にComparatorの配列を持ち、そのComparatorで順に比較した結果を返す新たなComparator」というのを定義することで、基本的なComparatorから複雑なComparatorを動的に生成することができる、ということです。
|
yamasaさん、ありがとうございます。
まだ解決はしていないのですが、取り急ぎGenericsというキーワードで調べる事が
できた事をご報告致します。
|
- OZ
- 常連さん
- 会議室デビュー日: 2006/02/27
- 投稿数: 45
|
投稿日時: 2006-05-15 18:00
追加で質問させて下さい。
引用: |
|
yamasaさんの書き込み (2006-05-12 17:18) より:
コード: |
|
1 : public class CompositeComparator<T> implements Comparator<T> {
2 : private final Comparator<? super T>[] comparators;
3 : public CompositeComparator(Comparator<? super T>... comparators) {
4 : this.comparators = comparators;
5 : }
6 : public int compare(T o1, T o2) {
7 : for (Comparator<? super T> comparator : comparators) {
8 : int tmp = comparator.compare(o1, o2);
9 : if (tmp != 0) return tmp;
10: }
11: return 0;
12: }
13: }
14:
15: Comparator<BeanSamp> CMP_HEIGHT = new Comparator<BeanSamp>() {
16: public int compare(BeanSamp o1, BeanSamp o2) {
17: return o1.getHeight() - o2.getHeight();
18: }
19: };
20: Comparator<BeanSamp> CMP_WEIGHT = new Comparator<BeanSamp>() {
21: public int compare(BeanSamp o1, BeanSamp o2) {
22: return o1.getWeight() - o2.getWeight();
23: }
24: };
25: Comparator<BeanSamp> CMP_BLOOD = new Comparator<BeanSamp>() {
26: public int compare(BeanSamp o1, BeanSamp o2) {
27: return o1.getBlood().compareTo(o2.getBlood());
28: }
29: };
30:
31: Comparator<BeanSamp> cmp_hwb = new CompositeComparator<BeanSamp>(CMP_HEIGHT, CMP_WEIGHT, CMP_BLOOD);
32:
|
こんな感じに任意の組み合わせのComparatorを作れます。
|
7〜11までの処理が理解できなかったのですが、これは複数のComaprator実装を組み合わせて
実行するCompositeComparatorが、コンストラクターで受け取ったComparator配列のcompareを
順次実行するという認識で良いでしょうか?
これは意味的に、CMP_HEIGHT、CMP_WEIGHT、CMP_BLOODを個別に順次実行するのと同じなのでしょうか?
コード: |
|
1 : SampBean[] beans;
2 : ・・・
3 : Arrays.sort(beans,CMP_HEIGHT);
4 : Arrays.sort(beans,CMP_WEIGHT);
5 : Arrays.sort(beans,CMP_BLOOD);
|
見当違いな事を言ってるようでしたらご指摘下さい。
宜しくお願い致します。
|
- Kazuki
- ぬし
- 会議室デビュー日: 2004/10/13
- 投稿数: 298
|
投稿日時: 2006-05-15 18:20
違います。
コード: |
|
public class SampComparator implements Comparator<BeanSamp> {
private Comparator<BeanSamp> COMP_HEIGHT = new ...(略);
private Comparator<BeanSamp> COMP_WEIGHT = new ...(略);
private Comparator<BeanSamp> COMP_BLOOD = new ...(略);
public int compare(BeanSamp o1, BeanSamp o2) {
int compHeight = COMP_HEIGHT.compare(o1, o2);
if(compHeight != 0) {
return compHeight;
}
int compWeight = COMP_WEIGHT.compare(o1, o2);
if(compWeight != 0) {
return compWeight;
}
return COMP_BLOOD.compare(o1, o2);
}
}
Arrays.sort(beans, new SampComparator());
|
ベタベタに書くとこんな感じです。
まず、heightで比較。
heightで比較した結果が等しくない場合は、heightの比較結果を返す。
heightが等しい場合は、weightで比較。
weightで比較した結果が等しくない場合は、weightの比較結果を返す。
最後にbloodで比較。
bloodの比較結果を返す。
という動きです。
このComparatorを使うと背の順。背が同じ人は体重の順。体重も同じ人は血液型順で並びます。
OZさんの示した
コード: |
|
1 : SampBean[] beans;
2 : ・・・
3 : Arrays.sort(beans,CMP_HEIGHT);
4 : Arrays.sort(beans,CMP_WEIGHT);
5 : Arrays.sort(beans,CMP_BLOOD);
|
は、結局血液型の順番にしかなりません。
|