2017-10-15 3 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

그리고 지금까지 어떤 시도를 했습니까? 왜 그 보강 방법은 여전히 ​​공백입니까? * 나는 결과물을 원한다. * 욕망이고 그래서 그것을 올려 놓을 정확한 위치가 아니다. – 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()); 
관련 문제