Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

Collection.sortについて

JDK1.5でGeneric使ってクラスを作ったのですが、
Collection.sortを使おうとすると、
どうもうまくいかなくて質問します。

ソースはこうなります。

class MyList<K> {
 private List<K> lst;
 public MyList() {
  lst = new ArrayList<K>();
 }
 public void add(K val) {
  lst.add(val);
 }
 
 public void sort() {
  ・・・???(ここがうまくいかないです。)
 }
}

このsortメソッドではフィールドのリストをソートさせたいのですが、
最初は「Collections.sort(keys);」としてみました。
しかし、
「バウンドの不一致: 型 Collections の総称メソッド sort(List<T>) は引数(List<Object>) に適用できません。 推測される型 Object は、バウンド・パラメーター <T extends Comparable<? super T>> の置換として有効ではありません。」
とエラーになります。まだGenericに関してあまり詳しくないので、このメッセージの意味すらよくわかりません。
FORでぐるぐる回しながら何とかすれば出来るとは思いますが、あまりいい方法だとは思わないし・・・
Collection.sortをうまく使う方法はないでしょうか。
よろしくお願いします。


20

回答

87291

閲覧

20件の回答

評価

0

>最初は「Collections.sort(keys);」としてみました。
keysなるフィールドがなさそうです。

評価

0

あ・・・。
Collections.sort(keys);ではなく
Collections.sort(lst);です。
掲示する時間違いました。
フィールドの自体が間違ってはいません。
もう一度書き直しますと、

class MyList<K> {
 private List<K> lst;
 public MyList() {
  lst = new ArrayList<K>();
 }
 public void add(K val) {
  lst.add(val);
 }
 
 public void sort() {
  Collections.sort(lst); //ここでエラー
 }
}

です。よろしくお願いします。

評価

0

ArrayListはComparableインタフェースを実装していないのでsortできません。

サブクラスを作って実装するか、Comparableのみ実装したクラスを作って。
sort(lst,compa)のように渡せば大丈夫だと思います。

評価

0

あれ、なんか嘘書いてますね・・
ArrayListに格納する要素がComparableインタフェースを実装していないといけないが正解です。
ソース見るとmergeSortで(Comparable)src[p]).compareTo(src[q])とかやってます。

面倒だからやっぱりsort(lst,compa)を使うということですかね。

評価

0

ありがとうございます。
解決しました。Comparatorを継承したクラスを作って
パラメータに渡すようにしました。

実は、もう一つありまして、
マップの場合もキーをソートしたいと思っています。
HashMapなどは無理だとは思いますが、
LinkedHashMapだと出来るのではないかと・・・

ためしに
Collections.sort(Arrays.asList(this.linkedHashMap.keySet().toArray()), new MyCompara());
(※ linkedHashMapはLinkedHashMapのフィールド、
  MyComparaクラスはComparatorを継承したクラスです。)
でやってみたところ、やはりソートされませんでした。
TreeMapだと最初からソートされてしまうし・・・
マップのキーのソートは出来ないのでしょうか。

評価

0

>Arrays.asList(this.linkedHashMap.keySet().toArray())

この場合結局keySet()の配列をListにして渡しているだけなので
それがソートされるだけですね。

Collections.sortのパラメータがListである以上
マップはそのままではソートできません。
keySet()のソート結果からマップを再編集する手も
あるかも知れませんが・・

MapのソートはやはりSortedMapを実装したTreeMapでしょうか。
ソート基準を変更したい場合comparator()をオーバーライドすればいいのかなと思います。

評価

0

よくみたらTreeMapってコンストラクタで、コンパレータ渡せるんですね、失礼しました。
使ったこと無かったけど便利そう。

評価

0

回答ありがとうございます。
TreeMapのコンストラクタってコンパレータかMapか
どちらかを渡すようになっていますので、
どうしてもループ処理をするしかないようですね。
この方法でいこうと思っています。

Object[] arr = this.map.keySet().toArray();
Arrays.sort(arr, new MyCompara());
for (Object o : arr) {
 ・・・(ここでデータ入れ替え)
}

ありがとうございました。

評価

0

ちゃんと見てないけど・・
TreeMapって、ソートするまでもなく既にソートされているんでは?
sortって基本的にMyCompara()の中にソート条件を書くのであって、外でなんかするとかあるものではないと思うし
本来、
Arrays.sort(lst, new MyCompara());
のような書き方で済むものではないのかなあ?

因みに
>Collections.sort(lst); //ここでエラー

>private List<K> lst;
だからでは?
"List<String>"とかにするとか
Collections#sort(List<T>,Comparator<? super T>)を呼んでないからでは?

何故
>Arrays.sort(arr, new MyCompara());
としたかは理解してます?
Collections#sort(List<T>)ではなく
Collections#sort(List<T>,Comparator<? super T>)を呼んだのと同様のことをしている筈ですけど

>まだGenericに関してあまり詳しくないので
まずもっと知ること
だと思うけど

評価

0

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

> Arrays.sort(lst, new MyCompara());
> のような書き方で済むものではないのかなあ?
ソースを見ると分かりますが、
lstはリストです。
それに配列に変換してものをlstだとしてもArrays.sort(lst, new MyCompara());
したところで元のリストは変換されなかったです。
(上記の質問で書いてあります。)

> >private List<K> lst;
> だからでは?
> "List<String>"とかにするとか
汎用的に作る目的ですので、Genericの形を決めることはしないことでのソースです。
最初から決めていたら私もそう悩んでなかったかも知れません。

> Collections#sort(List<T>,Comparator<? super T>)を呼んでないからでは?
確かにこのやり方はやっていなかったので、今回の皆さんの回答のおかげで解決しました。
それでですが、

>Collections#sort(List<T>)ではなく
>Collections#sort(List<T>,Comparator<? super T>)を呼んだのと同様のことをしている筈ですけど
何で同じですか。



評価

0

class MyList<K extends Comparable<? super K>>{

こうして

public void sort() {
  Collections.sort(lst);
}

これでどうでしょうか。

評価

0

>何で同じですか。
Collections#sort(List<T>)とCollections#sort(List<T>,Comparator<? super T>)のソースをよく見てみれば解らないながらも何か気付くかもしれないとか思ったりします

そして
>>まだGenericに関してあまり詳しくないので
>まずもっと知ること
>だと思うけど

そして、たぶん、その気付いたことがもっと知ることを必要とするものだったりするだろうと思う


簡単に言っちゃえば
Collections#sort(List<T>)はArrays#sort(List<T>)を
Collections#sort(List<T>,Comparator<? super T>)はArrays#sort(List<T>, Comparator<? super T>)を呼ぶ

>Collections.sort(lst); //ここでエラー

>Object[] arr = this.map.keySet().toArray();
>Arrays.sort(arr, new MyCompara());
>for (Object o : arr) {
> ・・・(ここでデータ入れ替え)
>}
なんてするくらいなら、Collections#sort(List<T>,Comparator<? super T>)を呼んどけばよかったんじゃないの?
というとこ

質問で挙げられたものは、ポイントとなりそうなところだけをピックアップしたもので、他にも色々実装されているのだろうと思うけど・・
実は挙げられたものしかないのだと仮定すれば、

List<なんだかクラス> lst;
...
Collections.sort(lst);
とかしたりする方がよっぽどよさそうな気がするけど

(Arrays#sort(Object[])とか使いたいのならArrays.sort(lst.toArray());とかでもいいだろうけど・・
lst.toArray()が返したものは別に参照を取っとかないとね
>for (Object o : arr) {
> ・・・(ここでデータ入れ替え)
>}
は何したいのかよく解らん・・
lstに戻したいのだろうと思うけど・・足りないような気もするし
>public MyList() {
>  lst = new ArrayList<K>();
> }
としているんだし、もっと簡単に扱えそうにも思えるけど、Arraysを使ってしまった時点で破綻?)

評価

0

えっと多少誤解もあるようなので補足をば・・

>まあさん
「リスト」に関して言えばまあさんの言われる通りCollections#sort(List<T>,Comparator<? super T>)でOKです。
これは2006-09-27 18:12で解決して、青森さんはそのようにされたようです。
同じく2006-09-27 18:12で次の問題として「マップ」も同様にソートしたいという議題に変わりました。

「マップ」の場合Collections#sort(List<T>,Comparator<? super T>)出来ないので、どうしようかということで2006-09-28 10:00に至っています。

>mioさん
>class MyList<K extends Comparable<? super K>>{
そうですね、これでMyListのコンパイルは通りますね。
実際に使うときにMyList<Hoge> myList = new MyList<Hoge>();したときに
HogeクラスがComparableを実装していなければここでエラーになるので分かりやすいですね。
Comparableを実装していない物を入れたり、ソート基準が違う場合青森さんのやり方でOKということでしょう。

2006-09-28 10:00で「マップ」用の方針も決まっているようですが、もっと簡単な方法があれば良いんですけどね。

評価

0

Comparableを使う場合は、

void sort(Comparator)

も実装してあげれば、もう少し汎用性が広がるかなと。


しかし、やはりGenericsは「シンプルな言語」Javaとは、方向性が違ったようにも思う…。

評価

0

え〜?
MapをそのままComparatorに渡して扱ったんじゃダメなの?・・は受け取れるものもがなきゃダメか。。
(別件で、今は深いとこまでちと考えたくないけど・・)

Javaでは不適当なのかもだけど、Cとかではよくやってることだろうと思うけど。。

というか
>TreeMapって、ソートするまでもなく既にソートされているんでは?
は・・ならない、或いは役不足だったということなのかな

評価

0

あ いや
TreeMapの部分はそんなもの使わずに自分で書きたいというところなのね?

評価

0

そもそも順序が必要なら、なんで最初からTreeMapを使わないんでしょうか…。

評価

0

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

> そもそも順序が必要なら、なんで最初からTreeMapを使わないんでしょうか…。
最初に設計をうまくやっておけば、こういう問題は無かったはずですけど、色んなところで使っているクラスでして…
殆どのところではソートされていてはだめで、
その中の何ヶ所だけソートが必要なところが
発生したのです。
そこだけ別クラスをつくるのも手ですが、
結構大きい修正なるので今回のような小細工をすることになったのです。

今回色んな方々からの回答を頂いて、本当嬉しかったです。
今後もよろしくお願いします。


評価

0

>色んなところで使っているクラスでして…
>殆どのところではソートされていてはだめで、
>その中の何ヶ所だけソートが必要なところが
>発生したのです。
>そこだけ別クラスをつくるのも手ですが、
>結構大きい修正なるので今回のような小細工をすることになったのです。

結構重要なことが最後になって出てきているような気もするけど・・
まあいいか

評価

0

ソート「されていてはだめ」というのが分かりませんね…。
本来マップは、あるモノに対する別のモノを検索する手段で、順序なんてない(考えない)ものなんですが。
その派生として、順序付けされたものができただけで。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。