1

Java コレクションを使用している場合、特にジェネリックを使用してユーティリティ メソッドを記述している場合、私のコードは見苦しく肥大化しており、null チェック、ネストされたループ、および繰り返しでいっぱいです。この一例を中心に、改善案をお願いします。

EnumMap値が評価のリストである があるとします。たとえば、enum自体が果物を表し、各値がさまざまな人によって付けられたリストの評価を表しているとします。

APPLE  -> [1,   3,   4] 
ORANGE -> [2,   0,   5]

John rated apple 1, Mary rated apple 3, Steve rated apple 4
John rated orange 2, Mary rated orange 0, Steve rated orange 5
Note the specific names are irrelevant and provided only to clarify the setup

ここで、上記のようなデータ構造を受け取り、各人の好きな果物のリストを返すユーティリティ メソッドを書きたいと思います。したがって、上記のサンプル データの期待される結果は次のようになり[ORANGE, APPLE, ORANGEます。2 > 13 > 05 > 4

以下は、これを行うための現在の方法です。同じアルゴリズムを書くための同等の (またはそれ以上の) 効率的で、よりクリーンな方法が必要です。

ありがとう!

public class MyListUtil {

    public static <K extends Enum<K>, T extends Object & Comparable<? super T>> List<K> maxKeysByIndex(EnumMap<K, List<T>> enumMap) {
        Iterator<K> keysIter = enumMap.keySet().iterator();
        int sizeOfAllLists = enumMap.get(keysIter.next()).size();
        List<K> ret = new ArrayList<K>();

        for (int i=0; i<sizeOfAllLists; i++) {
            keysIter = enumMap.keySet().iterator();
            K maxIndexKey = null;
            T maxIndexVal = null;

            while (keysIter.hasNext()){
                K curKey = keysIter.next();
                T curVal = enumMap.get(curKey).get(i);
                if (maxIndexVal == null || curVal.compareTo(maxIndexVal) > 0) {
                    maxIndexVal = curVal;
                    maxIndexKey = curKey;
                }
            }
            ret.add(maxIndexKey);
        }

        return ret;
    }
}
4

4 に答える 4

2

これは本当に醜いです。

ここで列挙型を使用するIMOは間違っています。列挙型は、人々の好みではなく、プログラミング定数であるべきです。

マップを使用して PersonFruitPreference クラスを作成し、Person がフルーツの好みを設定できるようにする必要があります。メソッド getFavoriteFruit() も追加します

于 2012-05-09T20:51:56.153 に答える
1

最初に sortedlist を使用します。

次に、次のように呼び出します。

リスト結果; for(T in enummap) { result.add(enummap.get(t).get(0)); //降順でソートしたと仮定します }

結果を返します。

于 2012-05-09T20:52:49.827 に答える
1

Scala を宣伝する絶好の機会です。ご存じかもしれませんが、Scala は JVM 上で実行され、Java バイトコードと完全に互換性があります。それ自体が JVM バイトコードにコンパイルされます。

このリーンで機能するコードから明らかでないこと:

val apple  = List (1, 3, 4)
val orange = List (2, 0, 5)
val persons = List ("John", "Mary", "Steve") 
val prefs = apple.zip (orange) .zip (persons) 
//  List[((Int, Int), java.lang.String)] = List(((1,2),John), ((3,0),Mary), ((4,5),Steve))
prefs.map (e => e._2 + ": " + (if (e._1._1 > e._1._2) "apple" else "orange"))
// List[java.lang.String] = List(John: orange, Mary: apple, Steve: orange)

つまり、完全な静的コンパイル時の安全性があります。ただし、可能な場合は型が推論されるため、ボイラープレートははるかに少なくなります。

最初の 3 行で 3 つのリストが生成されます。次に、それらは圧縮されます-あなたが見るコメントで、型推論者が彼が見つけたと言ったもの。

この部分は少し不可解です。

 (e => e._2 + ": " + (if (e._1._1 

Prefs は ((Int のペア), String) のリストであり、e はリスト内の 1 つの要素です。e._2 は文字列部分です (何らかの理由で、このようなタプルでは 0 からカウントしませんが、1 からカウントします。タプルの起源から、この習慣があったためだと思います) リストや配列などは 0 からカウントしますJavaのように。

e._1 は要素の最初の部分であり、果物の設定である Int のペアです。最初の果物は e._1._1、2 番目の果物は e._1._2 です。

しばらく Scala コレクションを使用した後、私はもう Java が好きではありません。:) しかし、もちろん、すべての企業が変更を許可しているわけではなく、それを習得するにはしばらく時間がかかります。

于 2012-05-09T22:47:57.997 に答える
1

Kすべてが同じジェネリック型で動作する多くのメソッドが必要な場合は、ヘルパー メソッドをおよびTクラスに配置し、クラス全体の完全なジェネリック型のみを指定できると思います。それらを使用するには、そのクラスのオブジェクトを作成し、そこからメソッドを呼び出します。

オブジェクトはステートレスになりますが、すべての冗長性を 1 つの場所に配置する構文上の方法が得られます。

public class <K extends Enum<K>, T extends Object & Comparable<? super T>> MyListUtil {

    public List<K> maxKeysByIndex(EnumMap<K, List<T>> enumMap) {
        ...
    //other methods
}

内部ループを別のメソッドに入れてみることができます。たとえば、次のようにします。

public K getMaxKeyFromPos(EnumMap<K, List<T>> enumMap, int pos)
{
    K maxIndexKey = null;
    T maxIndexVal = null;

    for (K curKey : enumMap.keySet()) {
         T curVal = enumMap.get(curKey).get(pos);
         if (maxIndexVal == null || curVal.compareTo(maxIndexVal) > 0) {
             maxIndexVal = curVal;
             maxIndexKey = curKey;
         }
    }
    return maxIndexKey;
}

for-eachまた、イテレータのクラフトの一部を削除して、構文に変更しました。

于 2012-05-09T21:03:10.450 に答える