2017-10-26 10 views
1

最近、HashMapとLinkedListを引数として取る単純なメソッドを作成しました。のエントリ場合は1000年 リファクタリングしてJavaコードを再利用できるようにする

  • 未満でなければなりません。このエントリのキーの

    1. 合計は、鍵の100
    2. 和で割り切れる必要があります:それは、これらのルールを次のいずれかの2つのエントリを見つけ、HashMapの反復処理しました同じ値が複数回表示されるケースをスキップします。

    これらのルールに従うペアがLinkedListに追加されます。

    private static void compare2(HashMap<Integer,String> values,List<String>results){ 
        if (values.size()>1) { 
         for(HashMap.Entry<Integer,String> entry1:values.entrySet()){ 
          for (HashMap.Entry<Integer,String> entry2:values.entrySet()){ 
           if (entry1.getValue().equals(entry2.getValue()))continue; 
           if ((entry1.getKey() + entry2.getKey())%100 == 0 && (entry1.getKey() + entry2.getKey())<1000){ 
            results.add(entry1.getKey() + "+" + entry2.getKey() + "=" + entry1.getKey() + entry2.getKey()); 
            results.add(entry1.getValue()); 
            results.add(entry2.getValue()); 
           } 
          } 
         } 
        } 
    } 
    

    今、私は同じルールに従う3つのエントリを見つける類似のメソッドを作りたかったのです。問題は、これとmodyfiyngのコピー/貼り付けの代わりに既存のコードを再利用したいと思うことです。その方法を見つけることができないようです。結果が同じである限り私のメソッドを変更する必要があるかどうかは気にしません。

  • +0

    2または3ではなく、「n」(パラメータ)として実装してください。 – Oleg

    +0

    ループを追加する方法はありません。しかし、現在のコードでも問題があります。 2つのエントリが同じ値を持つ場合、それらのエントリが異なる場合でもそのエントリのペアをスキップします。これは間違っています。 –

    +0

    これは、値が等しい場合、値が各エントリで一意であり、ペアをスキップする必要があることを忘れていました。 – Arkadeusz91

    答えて

    1

    あなたは数字の量パラメータ作ることができます:N.

    あなたはループのために使用してとどまることができるが、代替例のアプローチは、あなたの方法をリファクタリングすることができラムダのとストリームに次のように:

    方法 listOfNAccompanyingEntriesThatSatisfyTheConditionsは、再帰的方法である
    List<List<Map.Entry<Integer, String>>> compareN(HashMap<Integer, String> map, int n) { 
        return map.entrySet().stream() 
           .map(entry -> listOfNAccompanyingEntriesThatSatisfyTheConditions(entry, emptyList(), map, n - 1)) 
           .filter(list -> !list.isEmpty()) 
           .collect(toList()); 
    } 
    

    0123すべての nはについては
    private List<Map.Entry<Integer, String>> 
           listOfNAccompanyingEntriesThatSatisfyTheConditions(Map.Entry<Integer, String> newEntry, 
                        List<Map.Entry<Integer, String>> selectedEntries, 
                        HashMap<Integer, String> originalMap, 
                        int n) { 
    
         List<Map.Entry<Integer, String>> newSelectedEntries = join(newEntry, selectedEntries); 
    
         if (n == 0) return satisifiesCondition(newSelectedEntries) ? selectedEntries : emptyList(); 
    
         return originalMap.entrySet().stream() 
              .filter(entry -> !selectedEntries.contains(entry) && !entry.equals(newEntry)) 
              .map(entry -> listOfNAccompanyingEntriesThatSatisfyTheConditions(entry, newSelectedEntries, originalMap, n - 1)) 
              .flatMap(Collection::stream) 
              .collect(toList()); 
        } 
    

    、この方法は、要件を満たす可能性があるサブリストを蓄積するために、元の完全なリストで別のショットを取ります。数字の量は、(n個の== 0)に達した場合、再帰が停止し、停止条件が確認されています

    private static boolean satisifiesCondition(List<Map.Entry<Integer, String>> entries) { 
        int sum = sumOfTheKeysFrom(entries); 
        return sum % 100 == 0 && sum < 1000; 
    } 
    

    しかし、このアプローチは、あなたの実装の正確な翻訳が本当にあるとの、まだ同じカップルを持っています問題。例えば、もしあなたのような、あなたが二回同じエントリをダブル結果と結果が得られます

    HashMap<Integer, String> map = new HashMap<Integer, String>() {{ 
         put(1, "fred"); 
         put(2, "anja"); 
         put(24, "tom"); 
         put(45, "eddy"); 
         put(22, "lenny"); 
         put(77, "tommy"); 
         put(55, "henry"); 
         put(43, "alfred"); 
        }}; 
    

    のためにそれを実行します。

    [1 =フレッド、22 =レニー、1 =フレッド、 77 =トミー] [2 =アニャ、55 =ヘンリー、2 =アニャ、 43 =アルフレッド]

    これらはしかし容易いくつかの小さな微調整することにより解決されます。

    ストリーム、ラムダ、または再帰に精通していない場合は、命令型アプローチでも同様に実装することをお勧めします。私はこの質問を何らかの運動として認識していたので、私のサンプルコードではパフォーマンスについて気にしなかったことに気づくでしょう。

    +0

    それはまさに私が数えていたものです。これはエクササイズではありませんが、家庭での使用であり、データベースは非常に小さく、パフォーマンスはあまり重要ではありません。 – Arkadeusz91

    -1

    このような何かを試してみてください:

    @SafeVarargs 
    private static void check(final List<String> results, 
              final Map.Entry<Integer, String>... vals) 
    { 
        int sum = 0; 
        for (final Map.Entry<Integer, String> val : vals) 
        { 
         final Integer key = val.getKey(); 
         sum += null == key ? 0 : key; 
        } 
        if (sum < 1000 && 0 == (sum % 100)) 
        { 
         final StringBuilder result = new StringBuilder(200); 
         for (final Map.Entry<Integer, String> val : vals) 
         { 
          result.append(" + ").append(val.getKey()); 
         } 
         results.add(result.append(" = ").append(sum).substring(3)); 
         for (final Map.Entry<Integer, String> val : vals) 
         { 
          results.add(val.getValue()); 
         } 
        } 
    } 
    
    private static void compare2(final HashMap<Integer, String> values, 
               final List<String> results) 
    { 
        if (values.size() > 1) 
        { 
         for (final HashMap.Entry<Integer, String> entry1 : values.entrySet()) 
         { 
          for (final HashMap.Entry<Integer, String> entry2 : values.entrySet()) 
          { 
           if (entry1 == entry2) 
            continue; 
           check(results, entry1, entry2); 
          } 
         } 
        } 
    } 
    
    private static void compare3(final HashMap<Integer, String> values, 
               final List<String> results) 
    { 
        if (values.size() > 2) 
        { 
         for (final HashMap.Entry<Integer, String> entry1 : values.entrySet()) 
         { 
          for (final HashMap.Entry<Integer, String> entry2 : values.entrySet()) 
          { 
           for (final HashMap.Entry<Integer, String> entry3 : values.entrySet()) 
           { 
            if (entry1 == entry2 || entry1 == entry3 || entry2 == entry3) 
             continue; 
            check(results, entry1, entry2, entry3); 
           } 
          } 
         } 
        } 
    } 
    
    +0

    これはまさに私が4,5,6などの要素を比較する可能性を追加できるようにしたかったのです。私はそれほど多く描くことができましたが、次のすべての方法がずっと長くなり、より多くのコードを必要とするため、それはまだ厄介です。誰かがこのメソッドをリファクタリングしてスケーラビリティを向上させることができるようになることを願っていました。 – Arkadeusz91

    関連する問題