使用额外的细节增加对象的位置

时间:2017-10-15 03:10:43

标签: java algorithm java-8

我有一个场景,我有一个有序对象列表,我希望用另一个组成原始有序对象的对象列表中的信息来扩充它们。例如:

if ("Annual".equalsIgnoreCase(quest)) {
    choice = 1;
} else if ("Quarterly".equalsIgnoreCase(quest)) {
    choice = 4;
} else if ("Monthly".equalsIgnoreCase(quest)) {
    choice = 12;
} else {
    //you need to do something here.
}

所以,给定一个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>,其中包含一个完整的售价书籍集合,该集合尊重{{{{{{ 1}}但是来自相应的(id =相同)PriceLedger

的增强价格信息
List<Ledger>

设计显然不正确(为什么在Ledger中首先拿着书籍+售价书?)但这只是为了说明一个更大的问题。我尝试解决方案也非常低效,因为我正在迭代我试图增加的每本书的所有元数据书籍

1 个答案:

答案 0 :(得分:1)

我在这里假设了很多东西......但最重要的一点是,input.books[i] == pricedBooks[j].book这个PricedBook是错误的,你实际上想要通过他们的Bookid进行比较{1}} s - 这可能是一次变更,这是必须的。

首先我计算我将执行查找的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());