bugfix> java > 投稿

forループを使用する代わりに、次のコードをある種のストリームに単純に入れて操作する方法があるかどうか疑問に思っています。

私は基本的に、特定のスイマーのグループを除外することを検討していますが、これらのスイマーがまだ「AttendingList」に含まれていないことも確認しようとしています。

List<Swimmer> swimmingList = //List generated from db;
List<SwimmerAttending> attendingList = //List generated from db;
for(SwimmerAttending s : attendinglist)
   {
     swimmingList = swimmingList.stream()
                                  .filter(i-> i.getSwimerNumber() > 1000 && !s.getSwimmerNumber().equals(i.getSwimmerNumber()))
                                  .collect(Collectors.toList());   
   }

だから私はストリームを使用するだけでこれを行うためのより簡単な方法があるかどうか興味がありますか?ありがとうございます。

回答 2 件
  • コードを単純化することができ、さらに重要なことに、ループ内にループがあるため、現在、2次時間O(n ^ 2)ではなく線形時間O(n)で実行することができます(ストリームの反復は、隠されたものではありますが、ループのままです)。

    線形時間を取得するには、出席リストをセットに変換して、一定時間でチェックできるようにする必要があります。など:

    swimmingList = //List generated from db;
    attendingList = //List generated from db;
    Set<Integer> attendingSet = 
       attendingList.stream()
                    .map(s -> s.getSwimmerNumber())
                    .collect(Collectors.toCollection(HashSet::new));
    swimmingList = swimmingList.stream()
                               .filter(i -> i.getSwimmerNumber() > 1000 
                                        && !attendingSet.contains(i.getSwimmerNumber()))
                               .collect(Collectors.toList());
    
    

    セットへの変換は線形(1ループ)であり、フィルターも線形であるため、完全な線形アルゴリズムが作成されます。

    水泳リストに1000エントリがあり、出席リストに1000エントリがある場合、元のコードは各出席リストエントリで反復し、各出席者について1000の水泳リストエントリを反復して、合計1,000,000回の反復を行います。新しいコードは、参加リストを1回(1000回の反復のオーダーで)繰り返し、次に水泳リストを1回(1000回の反復)繰り返し、HashSetで一定時間のセットでメンバーシップチェックを実行して、合計を作成します。操作数は2000のみ。

  • あなたはマップすることができます attendinglist 最初に彼らのスイマー番号に:

    List<Integer> attendingSwimmerNumbers = 
        attendingList.stream()
            .map(SwimmerAttending::getSwimmerNumber)
            .collect(Collectors.toList());
    
    

    次に、を使用して、各スイマーの番号が上記のリストに含まれているかどうかを確認できます。 contains

    swimmingList = swimmingList.stream()
                                  .filter(i-> i.getSwimmerNumber() > 1000 && attendingSwimmerNumbers.contains(i.getSwimerNumber()))
                                  .collect(Collectors.toList()); 
    
    

    これはすべて、 swimmingList そして attendingList さまざまなタイプのオブジェクトを格納します。それらが同じタイプを格納する場合、オーバーライドするのが理にかなっているかもしれません equalsSwimmerAttending スイマー番号の同等性を確認します。その後、あなたは使用することができます contains 直接 attendingList

    swimmingList = swimmingList.stream()
                                  .filter(i-> i.getSwimmerNumber() > 1000 && attendingList.contains(i))
                                  .collect(Collectors.toList());
    
    

あなたの答え