2017-10-15 9 views
1

私は、元の順序付けオブジェクトを構成するオブジェクトの別のリストからの情報を補足したい順序付きオブジェクトのリストを持っているシナリオを持っています。例の場合:追加の詳細でオブジェクトを拡張する

だから、
class Ledger { 
    int id; 
    List<Book> books; // ordered collection of books 
    List<PricedBook> pricedBooks; //empty originally 
} 

class PriceLedger { 
    int id; 
    Set<PricedBook> booksWithPrices; 
} 

class Book { 
    int id; 
    String text; 
} 

class PricedBook { 
    Book book; 
    double price; 

    public PricedBook (final Book book, double price) { 
     this.book = book; 
     this.price = price; 
    } 
} 

List<Ledger>List<PriceLedger>与え、私はList<Book>で見つかった図書のが、増補価格情報と元の順序を尊重記入pricedBooksコレクションが含まれているList<Ledger>の出力を持つようにしたいです対応する(ID =同じ)PriceLedger

から
public List<Ledger> augment(List<Ledger> input, List<PriceLedger> metadata) 
{ 
    List<Ledger> result = new ArrayList<>(); 

    for (Ledger l : input) 
    { 
     result.add(augmentLedger(l, metadata)); 
    } 
} 

public Ledger augmentLedger(Ledger input, List<PriceLedger> metadata) 
{ 
    List<PricedBook> result = new ArrayList<>(); 

    List<PricedBook> pricedBooks = metadata.stream().map(PriceLedger::booksWithPrices).flatMap(Collection::stream).collect(Collections.toList()); 
    for (int i = 0; i < input.books.size(); i ++) { 
     for (int j = 0; j < pricedBooks.size(); j++) { 
      if (input.books[i] == pricedBooks[j].book) { 
       result.add(pricedBooks[j]); 
      } 
     } 
    } 

    Ledger l = new Ledger().setPricedBooks(result) 
    return l; 
} 

デザインは明らかに正しくない(なぜ元帳での最初の場所でブック+ pricedBooksを保持?)が、これは単に、より大きな問題を説明することです。私が改善しようとしている各書籍のすべてのメタデータの本を繰り返しているので、非常に効率的ではありませんでした。

+0

PricedBookは、これをパラメータとして使用する代わりに、延長する必要があります。 –

+0

私はここでコンポジションを使用していますが、そのようにすることもできます。ただ、この演習のために、私は明らかな設計ミスを無視し、効率的な解決策を見つけることに集中したいと思います。 –

+0

これまでに何を試しましたか?その 'augment'メソッドがまだ空白なのはなぜですか? *私はアウトプットを持ちたいと思っています。*欲望であり、それを置くための正しい場所ではありません。 – nullpointer

答えて

1

ここではかなり多くのことを想定しています...しかし、主なものはこのinput.books[i] == pricedBooks[j].book実際にPricedBookBookidと比較したいというのは間違っています。これはおそらく一度変更する必要があります。

まず、私はそう一度だけ計算される必要があり、これは、入力のすべての値に対して同じである、私は反対ルックアップを実行しますmapを計算:

// PriceLedger::Id --> [ PricedBook::Id, PricedBook ] 
    Map<Integer, Map<Integer, PricedBook>> map = metadata.stream() 
      .collect(Collectors.toMap(
        PriceLedger::getId, 
        pl -> pl.getBooksWithPrices().stream() 
          .collect(Collectors.toMap(
            pb -> pb.getBook().getId(), 
            Function.identity())))); 

これが配置されると、残りは本当に簡単に実行できます。各Ledgerについては、対応するPriceLedgerのマップを参照してください。各書籍検索に対応するPriceBookを検索します。 Mapを導入すると、ハッシュルックアップのみを実行しているため、処理が高速になるはずです。必要なエントリを見つけるために反復処理する代わりに。

input.stream() 
      .map(l -> { 
       List<Book> withoutPrice = l.getBooks(); 
       List<PricedBook> withPrice = withoutPrice.stream() 
         .map(b -> { 
          return map.get(l.getId()).get(b.getId()); 
         }) 
         .collect(Collectors.toList()); 
       return new Ledger(l.getId(), l.getBooks(), withPrice); 
      }) 
      .collect(Collectors.toList()); 
関連する問題