0

私は製品サイズを表す文字列のグループを持っていますが、それらのほとんどは意味が重複していますが、名前は重複していません。(つまり、Large というサイズには、少なくとも 14 の異なるスペルがあり、それぞれを保持する必要があります。) これらが表すサイズに基づいて、これらを並べ替える必要があります。考えられる Small 値は、考えられる Medium 値などの前に来る必要があります。

これが可能であることがわかる唯一の方法は、それが表す基本サイズに基づいて各サイズをグループ化するさまざまなセットを含む特定の Comparator を実装することです。次に、特定のサイズがどのセットに該当するかを判断することで、-1,0,1 の関係を実装できます。

これを達成するためのより堅牢な方法はありますか? 具体的には、今から 2 週間後に誰かが Large のさらに別の綴り方を思いついたときが心配です。

編集:明確にするために、私が質問している実際のコンパレーターではなく、各グループを含むセットのセットアップです。これは、この状況を処理する通常の方法ですか? 新しいサイズを追加するたびに完全な再コンパイル/展開を必要としないように、将来的にはどのように証明すればよいですか?

4

3 に答える 3

1

カスタムコンパレータソリューションです。これが十分に堅牢ではないことをなぜ心配するのかわかりません。

于 2012-12-12T19:40:22.580 に答える
1

簡単な方法は、リソースバンドルからサイズ エイリアスをロードすることです。コード例 (すべてのファイルを同じパッケージに入れる):

size プロパティをカプセル化するインターフェース

public interface Sized {
    public String getSize();
}

製品クラス

public class Product implements Sized {

    private final String size;

    public Product(String size) {
        this.size = size;
    }

    public String getSize() {
        return size;
    }

    @Override
    public String toString() {
        return size;
    }
}

魔法を行うコンパレータ:

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

public class SizedComparator implements Comparator<Sized> {

    // maps size aliases to canonical sizes
    private static final Map<String, String> sizes = new HashMap<String, String>();

    static {
        // create the lookup map from a resourcebundle
        ResourceBundle sizesBundle = ResourceBundle
                .getBundle(SizedComparator.class.getName());
        for (String canonicalSize : sizesBundle.keySet()) {
            String[] aliases = sizesBundle.getString(canonicalSize).split(",");
            for (String alias : aliases) {
                sizes.put(alias, canonicalSize);
            }
        }
    }

    @Override
    public int compare(Sized s1, Sized s2) {
        int result;
        String c1 = getCanonicalSize(s1);
        String c2 = getCanonicalSize(s2);
        if (c1 == null && c2 == null) {
            result = 0;
        } else if (c1 == null) {
            result = -1;
        } else if (c2 == null) {
            result = 1;
        } else {
            result = c1.compareTo(c2);
        }
        return result;
    }

    private String getCanonicalSize(Sized s1) {
        String result = null;
        if (s1 != null && s1.getSize() != null) {
            result = sizes.get(s1.getSize());
        }
        return result;
    }

}

SizedComparator.properties:

1 = Small,tiny
2 = medium,Average
3 = Large,big,HUGE

単体テスト (ハッピー フロー用):

import org.junit.Before;
import org.junit.Test;

public class FieldSortTest {

    private static final String SMALL = "tiny";
    private static final String LARGE = "Large";
    private static final String MEDIUM = "medium";

    private Comparator<Sized> instance;

    @Before
    public void setup() {
        instance = new SizedComparator();
    }

    @Test
    public void testHappy() {
        List<Product> products = new ArrayList<Product>();
        products.add(new Product(MEDIUM));
        products.add(new Product(LARGE));
        products.add(new Product(SMALL));

        Collections.sort(products, instance);

        Assert.assertSame(SMALL, products.get(0).getSize());
        Assert.assertSame(MEDIUM, products.get(1).getSize());
        Assert.assertSame(LARGE, products.get(2).getSize());
    }
}

ResourceBundles は自動的にキャッシュされることに注意してください。以下を使用して、プログラムで ResourceBundle をリロードできます。

ResourceBundle.clearCache();

(Java 1.6 以降)。または、 Spring マジックを使用して、自動リロード メッセージ リソースを作成することもできます。

ガタガタのプロパティ ファイルから読み取るだけでは不十分な場合は、データベースにサイズ エイリアスを簡単に保持することもできます。

于 2012-12-12T23:26:30.443 に答える
0

文字列(または一般的なオブジェクト)のコレクションに任意の順序を課すための標準的な手段は、提案したようにコンパレータを実装することです。

提案する「手動」ソリューションとは別に、文字列の相対的な編集距離を標準的な例と比較することを検討できます。これは、あなたが考えていなかった代替案で機能するという意味で、より柔軟になります。ただし、関連する作業に関しては、アプリケーションにとってはやり過ぎかもしれません。

于 2012-12-12T20:02:32.347 に答える