![](/img/trans.png)
[英]Filter objects by matching it with another list by its nested list elements with a condition
[英]How to filter a list of objects by matching properties with objects from another list
我是 Java II 的編程學生。 我有一個對象出版物,它有兩個屬性......書籍列表和作者列表
public class Publication {
public final List<Book> bookList;
public final List<Author> authorList;
}
public class Author {
private final String id;
private final String firstName;
private final String lastName;
private final int age;
}
public class Book {
private final String title;
private final String authorId; //this is equal to person's id who wrote the book
}
我的任務是創建一個方法
public List<Book> getBooksByAuthorAge(int age){}
在接受 int 年齡的 Publication 類中,然后返回由該年齡的作者編寫的所有書籍。 Book 屬性“authorId”與 Author 屬性“id”相關。 所以我需要計算年齡,找到那個年齡的人,找到他們的 id,然后按那個年齡的作者列表中的 authorId 過濾書籍列表。
相比之下,我在 Java 中仍然有點弱,並試圖用流來做到這一點,但在每一步我都受阻了。 我已經開始將它分解成多個語句,首先返回具有給定年齡的人員列表,然后使用它來映射 ID 列表,然后我可以用它來與 authorIds 進行比較,但我在流中掙扎我不想回到 Java I 的舊 for 循環! 我知道在這個小方法中捆綁一堆變量太愚蠢了。 能制造出美麗溪流的人給我一點推動嗎? 非常感謝提前,真的!
以下只是部分完成並且太愚蠢了,但包括在內只是為了證明我的思想陷入困境:
//a List of authors who are of that age
List<Author> agedResults = authorList.stream()
.filter(p -> p.getAge() == age)
.collect(Collectors.toList());
//a list of IDs that belong to authors of that age
List<String> agedIds = agedResults.stream()
.map(Author::getId)
.collect(Collectors.toList());
我建議您添加一個Author
字段,而不是在Book
中維護authorId
。 無論如何,按原樣,首先流式傳輸authorList
以收集匹配的 authorId,然后流式傳輸bookList
以查找匹配的書籍。 喜歡,
public List<Book> getBooksByAuthorAge(int age) {
List<String> authorIds = authorList.stream()
.filter(a -> a.age == age).map(a -> a.id)
.collect(Collectors.toList());
return bookList.stream()
.filter(book -> authorIds.contains(book.authorId))
.collect(Collectors.toList());
}
可以是這樣:
public List<Book> getBooksByAuthorAge(int age) {
return bookList.stream()
.filter(book -> authorList.stream()
.filter(author -> author.getAge() == age)
.anyMatch(author -> Objects.equals(author.getId(), book.getAuthorId())))
.collect(Collectors.toList());
}
但我不確定它比幾個變量更好。 代碼應該是可讀的,並且流並不總是符合這個要求。
為了方便查找作者 ID,作者應按年齡過濾並收集到Set
,允許在Set::contains
進行 O(1) 查找,然后按 id 過濾書籍流:
public List<Book> getBooksByAuthorAge(int age) {
Set<String> authorIds = authorList
.stream()
.filter(author -> author.getAge() == age)
.map(Author::getId)
.collect(Collectors.toSet());
return bookList
.stream()
.filter(book -> authorIds.contains(book.getAuthorId()))
.collect(Collectors.toList());
}
但是,在“現實世界”中,一本書可能由多個人創作,因此如果Book
類更改為支持List<String> authorIds
而不是單個String authorId
,則可以應用以下操作:
public List<Book> getBooksWithSeveralAuthorsByAuthorAge(int age) {
Set<String> authorIds = authorList
.stream()
.filter(author -> author.getAge() == age)
.map(Author::getId)
.collect(Collectors.toSet());
return bookList
.stream()
.filter(book -> book
.getAuthorIds() // assuming List<String> is returned here
.stream() // Stream<String>
.anyMatch(authorIds::contains)
)
.collect(Collectors.toList());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.