3

私は現在マップを使用していますが、プログラムを効果的に機能させる方法に困惑しています。マップを反復処理してキーと値を取得し、アルファベット順と逆アルファベット順で非常に簡単に並べ替えることができます。これにはカスタムコンパレータを使用しました。ただし、現在、値が最も多いキーに基づいてマップを並べ替えようとしています。値は私が作成したオブジェクトのリストであり、このシナリオと考えることができます。

たくさんの町(文字列型のキー)があるアトラス(カタログのような)があります。Shops(List)が含まれています。これを並べ替えて、最も多くの店舗がある町が最初に表示され、降順で並べ替えられ、2番目の並べ替えが町に基づいてアルファベット順になり、これを表す文字列が返されるようにします。

私はこれまで、アルファベット順と逆アルファベット順のクラスごとに別々のクラスでComparatorインターフェースを使用してきましたが、学習目的で同じパターンに従いたいと思っていますが、これは完全に困惑しています。

例:

class Atlas {

       Map<String, List<Shop> atlas = new HashMap<String, List<Shop>();

       void addShop(Shop shop){
            //if(Atlas already contains){
              get the town and add the shop to it.
            }
            else{
                 add the town as the key and the shop as the value in the list
            }
       }

       List<Shop> getAllShopsFromTheGivenTown(String givenTown){
            //if(Atlas contains givenTown){
            return the givenTown from the List. 
            }
            else{
                 //Return an ArrayList emptyList
            }
       }

       public String returnAllTownsAndShopsAlphbetically(){
       String tmpString = "";   

    List<String> keys = new LinkedList<String>(atlas.keySet());
    TownComparatorAtoZ tc = new TownComparatorAtoZ();
    Collections.sort(keys, tc);

    for(String town : keys){
         List<Shop> shops = new LinkedList<Dealer>(atlas.get(town));
         ShopComparatorAtoZ sc = new ShopComparatorAtoZ();
          Collections.sort(shop, sc);

        for(Shop shop : shops){
            if(tmpString.isEmpty()){
            tmpString = tmpString + town + ": " + shop.getName();
            }
            else if(tmpString.contains(town)){
            tmpString = tmpString + ", " + shop.getName();
            }
            else{
            tmpString = tmpString + " | " + town + ": " + shop.getName();               }   
        }
    }       
    return tmpString;   
    }
}

上からわかるように(最もクリーンで効率的ではありませんが)、アルファベット順に戻り、文字列ビルダーに再フォーマットされます。しかし、コンパレータを使用して自分が求めていることを達成するにはどうすればよいのか疑問に思っています。誰かが実際に何をしているのかを説明したコードスニペットを提供できれば、それを取得するだけでなく、その方法を理解することができれば幸いです。コードの塊をコピーして貼り付けましたが、それを理解するには、コード内で視覚的に確認する必要があります。

SO出力私は次のようなものになりたい

マンチェスター:m&s、h&m、schuch | バーミンガム:ゲーム、ボディショップ| リバプール:スポーツ

4

2 に答える 2

2

あなたはこのようなことを試すことができます:

public static Map<String, List<Shop>> mySortedMap(final Map<String, List<Shop>> orig)
{
    final Comparator<String> c = new Comparator<String>()
    {
        @Override
        public int compare(final String o1, final String o2)
        {
            // Compare the size of the lists. If they are the same, compare
            // the keys themsevles.
            final int sizeCompare = orig.get(o1).size() - orig.get(o2).size();
            return sizeCompare != 0 ? sizeCompare : o1.compareTo(o2);
        }
    }

    final Map<String, List<Shop>> ret = new TreeMap<String, List<Shop>>(c);
    ret.putAll(orig);
    return ret;
}

説明:はのTreeMap基本的な実装でありSortedMap、キー値のコンパレーターを引数として取ることができます(コンパレーターが引数として渡されない場合は、キーの自然な順序が優先されます)。ここでは、引数として渡された元のマップのリストサイズを比較するアドホックコンパレータを作成し、サイズが等しい場合は、キー自体を比較します。最後に、原点マップからすべての要素をその中に挿入し、それを返します。

于 2012-12-21T16:49:17.147 に答える
0

次のようなことを試してみるとどうなりますか。

private static final Comparator<Map.Entry<String, List<Shop>>> CountThenAtoZ =
    new Comparator<Map.Entry<String, List<Shop>>>() {
        @Override
        public int compare(Map.Entry<String, List<Shop>> x, Map.Entry<String, List<Shop>> y) {
            // Compare shop count first. If equal, compare keys alphabetically.
            int cmp = ((Integer)x.getValue().size()).compareTo(y.getValue().size());
            return cmp != 0 ? cmp : x.getKey().compareTo(y.getKey());
        }
    };

...

public String returnAllTownsAndShopsAlphbetically() {

    List<Map.Entry<String, List<Shop>>> entries = new ArrayList<>(atlas.entrySet());
    Collections.sort(entries, CountThenAtoZ);

    String result = "";
    boolean firstTown = true;
    for (Map.Entry<String, List<Shop>> entry : entries) {
        if (!firstTown) result += " | "; else firstTown = false;
        result += entry.getKey() + ": ";

        boolean firstShop = true;
        TreeSet<Shop> sortedShops = new TreeSet<>(new ShopComparatorAtoZ());
        sortedShops.addAll(entry.getValue());
        for (Shop shop : sortedShops) {
            if (!firstShop) result += ", "; else firstShop = false;
            result += shop.getName();
        }
    }

    return result;
}

これが機能する方法は、最初にアトラスエントリのリストを希望する順序で正確に作成することです。正しい順序を作成するには、キーとそれに関連する値の両方にアクセスする必要があるためListMap.Entryインスタンスの並べ替えが最も便利です。

次に、並べ替えられたリストを調べて結果Stringを作成します。ショップをに追加する前に、必ずアルファベット順に並べ替えてくださいString

于 2012-12-21T18:12:35.967 に答える