java - 使用额外的细节增强对象

标签 java algorithm java-8

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

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<Ledger>其中包含一个已填写的 pricedBooks 集合,这些集合尊重在 List<Book> 中找到的书籍的原始顺序。但使用来自相应(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;
}

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

最佳答案

我在这里假设了很多事情......但最重要的是这个 input.books[i] == pricedBooks[j].book 是你真正想要的错误通过 id 比较 PricedBookBook - 这可能是这里必须进行的一次更改。

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

关于java - 使用额外的细节增强对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46751307/

相关文章:

algorithm - 节点遍历式算法

java - RxJava 访问项目下游

java - 通过 jenkins 成功将 .war 文件部署到 tomcat 8.5.20 服务器不会在浏览器中显示

java - JPA 中的地理空间支持

java - 如何将 log4j 消息路由到唯一的附加程序

algorithm - 最短位序列逻辑

java - Aerospike 箱体长度小于 14

algorithm - 密文窃取算法 - 哪一种是正确的?

java - Java Future 和 RejectionHandler 的查询

java.util.Objects.isNull vs object == null