プロが教えるわが家の防犯対策術!

多次元配列のソートがうまくいかない

質問失礼します.
以下のような,String型,int型,double型の混在した多次元配列([3][3]の配列)をソートするプログラムを作成しました.
このプログラムでは3番目の項目でソートを行っています.
問題点なのですが, 3番目の項目がdouble型の一桁(例えばarray[1][2]が2.0)ならばうまくソートできるのですが,
一つを2桁(例えばarray[1][2]を10.0)にすると何故か先頭の数(10.0の場合1)を基準にソートされてしまっているようです・・・
配列へのデータの入れ方が間違っているのでしょうか?
原因がはっきりわからず困っているのですが, わかる方いましたらよろしくお願いします.

public class Sort_test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO 自動生成されたメソッド・スタブ
String[][] array = new String[3][3];

array[ 0 ][ 0 ] = "A";
array[ 0 ][ 1 ] = 2001+"";
array[ 0 ][ 2 ] = 9.0+"";

array[ 1 ][ 0 ] = "B";
array[ 1 ][ 1 ] = 1001+"";
array[ 1 ][ 2 ] = 2.0+"";

array[ 2 ][ 0 ] = "C";
array[ 2 ][ 1 ] = 3001+"";
array[ 2 ][ 2 ] = 6.0+"";

TheComparator comparator = new TheComparator();

// 3番目の項目でソートするように設定
comparator.setIndex( 2 );
// ソート実施
Arrays.sort( array, comparator );
dump(array);

}

public static void dump( String[][] array ) {

for ( int i = 0;i < array.length;i++ ) {
for ( int j = 0; j < array[ i ].length;j++ ) {
System.out.print( "\t" + array[ i ][ j ] );
}

System.out.println();
}
}
}
//多次元配列ソート用クラス
class TheComparator implements Comparator {

/** ソート対象のカラムの位置 */
private int index = 0;

/** ソートするためのカラム位置をセット */
public void setIndex( int index ) {
this.index = index;
}

public int compare( Object a, Object b ) {
String[] strA = ( String[] ) a;
String[] strB = ( String[] ) b;

return ( strA[ index ].compareTo( strB[ index ] ) );
}
}

A 回答 (3件)

原因は他の方が述べている通り文字列辞書順で並び替えが行われていることだと思います。



違った観点でのご提案ですが、String、int、doubleを格納するクラスを一つ作るという実装ではだめなのでしょうか?
(多次元)配列はもともと同じ型の要素が入ることを前提だと思いますので、要求の機能とは親和性が低いように思えます。
違った型の要素が動的に増減するとなると話は別ですが...

以下に変更した例を記載致します。

public class Sort_test {
 public static void main(String[] args) {
  StrIntDbl[] array = new StrIntDbl[3];

  array[0] = new StrIntDbl("A", 2001, 9.0);
  array[1] = new StrIntDbl("B", 3001, 2.0);
  array[2] = new StrIntDbl("C", 1001, 6.0);

  StrIntDblComparator comparator = new StrIntDblComparator(StrIntDblComparator.STR);

  Arrays.sort(array, comparator);
  dump(array);
 }
 
 public static void dump(StrIntDbl[] array) {
  for (int i = 0; i < array.length; i++) {
   System.out.print("\t" + array[i].s);
   System.out.print("\t" + array[i].i);
   System.out.print("\t" + array[i].d);
   System.out.println();
  }
 }
}

class StrIntDblComparator implements Comparator<StrIntDbl> {
 private final int key;
 public final static int STR = 0;
 public final static int INT = 1;
 public final static int DBL = 2;

 public StrIntDblComparator(int key) {
  super();
  this.key = key;
 }

 public int compare(StrIntDbl o1, StrIntDbl o2) {
  switch (key) {
   default:
   case STR:
    return o1.s.compareTo(o2.s);
   case INT:
    return o1.i - o2.i;
   case DBL:
    return (int)(o1.d - o2.d);
  }
 }
}

class StrIntDbl{
 String s;
 int i;
 double d;

 public StrIntDbl(String s, int i, double d) {
  super();
  this.s = s;
  this.i = i;
  this.d = d;
 }
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます.
わざわざサンプルまで書いていただいて大変参考になりました.
まさに自分がやりたかった処理が実行できました.

どうもありがとうございます!

お礼日時:2010/11/03 16:03

文字列をソートしているからです。


数値順にソートしたいのならば数値型にしてソートしなければだめです。
もしくは0パディングして桁数を合わせてから比較するようにすればいいです。
    • good
    • 0
この回答へのお礼

回答ありがとうございます.

たしかにソートの際にString型で行っていました.
はずかしながら確認があまかったです.

どうもありがとうございます.

お礼日時:2010/11/03 16:06

「String型,int型,double型の混在した多次元配列([3][3]の配列)をソートするプログラムを作成しました。


とのことですが、比較ハンドラ compare では、String型で比較を行っています。
従って、array[][2] の比較は、String型で行われます。
例えば、"9.0","70.0", "6.0" を StringクラスのcompareToメソッドで比較すると、文字列長は短い方に合わせて
比較しますから、"9.0","70.0", "6.0" の比較は、"9.0","70.", "6.0" の比較となり、
compareToは、辞書式比較ですから、比較結果は、 "6.0" < "70." < "9.0" なります。

比較ハンドラ compare で比較を行う際には、データ型に合わせた比較、array[][2]の比較であれば
String型をdouble型に変換して比較するなどの処置が必要です。

参考URL:http://java.sun.com/javase/ja/6/docs/ja/api/java …
    • good
    • 0
この回答へのお礼

回答ありがとうございます.

ソートがうまくいかない箇所を細かく説明していただいて助かります.
とても参考になり,おかげで原因がわかりました.

どうもありがとうございます.

お礼日時:2010/11/03 16:08

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!