Java 使用额外的细节在适当的位置扩充对象
我有一个场景,其中我有一个有序对象列表,我希望用组成原始有序对象的另一个对象列表中的信息来补充它。例如:Java 使用额外的细节在适当的位置扩充对象,java,algorithm,java-8,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&
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;
}
}
分类账{
int-id;
列出书籍;//有序收集书籍
列出pricedBooks;//原为空
}
类别价格分类帐{
int-id;
定价;
}
课堂用书{
int-id;
字符串文本;
}
类定价书{
书籍;
双倍价格;
公共定价书(最终图书,双倍价格){
这本书;
这个价格=价格;
}
}
因此,给定一个列表
和一个列表
,我希望有一个列表
的输出,其中包含一个已填写的pricedBooks集合,该集合与列表
中找到的书籍的原始顺序有关,但包含相应(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;
}
公共列表扩充(列表输入、列表元数据)
{
列表结果=新建ArrayList();
对于(分类账l:输入)
{
结果.添加(增加分类账(l,元数据));
}
}
公共分类账(分类账输入、列表元数据)
{
列表结果=新建ArrayList();
List pricedBooks=metadata.stream().map(PriceLedger::booksWithPrices).flatMap(Collection::stream).collect(Collections.toList());
for(int i=0;i
这种设计显然是不正确的(为什么在分类账中首先要保留图书+价格图书?),但这只是为了说明一个更大的问题。我试图在中找到一个解决方案也是非常低效的,因为我正在迭代我试图扩充的每本书的所有元数据书我假设这里有很多东西。。。但是最重要的一点是,这个
输入。books[i]==pricedBooks[j]。book
是错误的,你实际上想通过它们的id
s来比较PricedBook
和book
——这可能是一次必须进行的更改
首先,我计算将对其执行查找的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()))));
PricedBook应该扩展Book,而不是一开始就把它作为参数。我在这里使用的是合成,但是的,它也可以这样做。不过,就为了这个练习,我想忽略任何明显的设计错误,集中精力寻找一个有效的解决方案。到目前为止,您尝试了什么?为什么
augment
方法仍然是空的?我想要一个输出是一种欲望,所以不是放置它的正确位置。@nullpointer我尝试了我试图描述的暴力解决方案above@JohnBaum我仍然没有看到问题中的尝试。我希望你能理解
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());