- - PR -
Map系でEntryをValueの値でソートするには?
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-04-27 03:14
Keyの値の大小でソートするのではなく、Valueの値でソートしたいと思います。どのような方法がありますでしょうか?Keyはすべてuniqueであり、Valueの値には重複したものがあり、KeyとValueをひっくり返して使用できないことが条件です。
KeyとValueがStringですので以前は(Value + Key)したものをTreeSetに入れてソートし、StringTokenizerで分割して結果を得ていました。スマートな方法を模索しています。返信お願い致します。 | ||||
|
投稿日時: 2005-04-27 03:39
Comparatorインターフェイスを実装したクラスを作成して、java.util.Collectionsクラスのsort(List list, Comparator c) メソッドを実行してはいかがでしょうか。
| ||||
|
投稿日時: 2005-04-27 09:19
これだけだと、MapはListインターフェースをもってないのにどーすんの? って思ってしまいます。 もし、java.util.Collections#sort(List list, Comparator c)を使用するのであれば、 1. Map#valuesで値のシーケンスを取り出す。 2. ArrayListのコンストラクタに値のシーケンスを渡し、Listに変換する。 3-a. java.util.Collections#sort(List list, Comparator c)でソートする。 という手順になるでしょう。 別解としては、Map.Valuesでソートした値を返すMapのサブクラスを作るという方法もあります。 | ||||
|
投稿日時: 2005-04-28 09:29
書き込みありがとうございます。多分こういうことなんだと思います。
HashMap h = new HashMap(); h.put("1", "hoge"); h.put("2", "oge"); h.put("3", "hoge"); h.put("4", "ge"); h.put("5", "e"); Collection l = h.values(); ArrayList al = new ArrayList(); al.addAll(l); Collections.sort(al); int i = Collections.binarySearch(al, "e"); System.out.println("position of 'e': " + i);//値は0 i = Collections.binarySearch(al, "ge"); System.out.println("position of 'ge': " + i);//値は1 言葉足らずで申し訳ないと思っていますが、最終的にはEntryをValueの値でソートし、ソートされたKeyをArrayListにするということをやってみたいのです。自分では分かったような気分になっているのですが、手持ちにJava環境がないのでまだ実証できてません。何かスマートな方法がありましたら宜しくお願いします。 | ||||
|
投稿日時: 2005-04-28 10:17
これで、entriesにはMapのvalueの値でソートされたMap.Entry が入っていますので、イテレートしてMap.Entry#getKey()していけ ば、望みどうりになるかと思います。 equals()のオーバーライドは不要だったので削除。 [ メッセージ編集済み 編集者: シュン 編集日時 2005-04-28 17:25 ] | ||||
|
投稿日時: 2005-04-28 16:15
返信ありがとうございます。
ValueがStringである、という場合ならば下記のようになりますね。 HashMap m = new HashMap(); m.put("1", "hoge"); m.put("2", "oge"); m.put("3", "hoge"); m.put("4", "ge"); m.put("5", "e"); ArrayList entries = new ArrayList(m.entrySet()); Collections.sort( entries, new Comparator(){ public int compare(Object o1, Object o2){ Map.Entry e1 =(Map.Entry)o1; Map.Entry e2 =(Map.Entry)o2; String e1Value = (String) e1.getValue(); String e2Value = (String) e2.getValue(); return (e1Value.compareTo(e2Value)); } public boolean equals(Object obj){ return super.equals(obj); } } ); ArrayList keys = new ArrayList(); for(int i = 0; i < entries.size(); i ++){ Map.Entry me = (Map.Entry) entries.get(i); keys.add((String)me.getValue()); } ただしIteratorを使うとパフォーマンスが落ちるので、Listを使ってみました。自分が欲しいものは出来上がりましたので満足しています。書き込みありがとうございました。 | ||||
|
投稿日時: 2005-04-28 16:37
ランダムアクセスをしないで順次アクセスのみの用途なら、ArrayList#get( int index ) よりも LinkedList からIterator を取り出して Iterator#next() を使った方が速いですよ。 | ||||
|
投稿日時: 2005-04-28 16:53
想馬さん、返信ありがとうございます。
自分はこちらをみて発言したつもりなんですけど、何か間違っているのでしょうか? http://www.asahi-net.or.jp/~dp8t-asm/java/articles/notes/02/article.html#id_1079_ ちなみに使用したソースはちと古いです(2000年のもの)。興味がありますので、是非勉強してみたいと思います。返信お願いします。 [ メッセージ編集済み 編集者: A.K.渡邉 編集日時 2005-04-28 16:55 ] |