使用具有组合集合的Java流
我正在寻找使用Java流来解决这类问题:
我有一个库对象列表。
库类包含剖面图。 部分包含BookShelf对象的列表。 BookShelf包含一个Book对象的Map。
class Library {
Map<String, Section> sections = new HashMap<String, Section>();
String name;
public String toString() {
return name;
}
}
class Section {
List<BookShelf> bookShelves = new ArrayList<BookShelf>();
}
class BookShelf {
Map<String, Book> books = new HashMap<String, Book>();
}
class Book {
String name;
Book(String name) {
this.name = name;
}
}
我想知道的是所有具有名为“Java 8”的书的库对象。 我认为这是一个可以使用流来回答的查询,然而,编码各种流调用我得到一个Book对象集合,而不是根Library对象。
流适合使用嵌入对象和集合吗? 我将如何实现这一目标?
下面是一个简单的代码,它使用传统的循环来找到答案:
List<Library> libraries = new ArrayList<Library>();
Library lib = new Library();
lib.name = "Houston Central";
libraries.add(lib);
Section section = new Section();
lib.sections.put("Reference", section);
BookShelf shelf = new BookShelf();
section.bookShelves.add(shelf);
Book book = new Book("Java 8");
shelf.books.put("Java 8", book);
book = new Book("Java 7");
shelf.books.put("Java 7", book);
/*
* Search for a Library containing a specific book
* using traditional loops.
*/
for(Library library : libraries) {
for (Section sec : library.sections.values()) {
for (BookShelf bookShelf : sec.bookShelves) {
for (Book b : bookShelf.books.values()) {
if (b.name.equals("Java 8")) {
System.out.println("Book is contained in Library " + library);
}
}
}
}
}
流是否合适可能是品味和可读性偏好的问题。 在我看来,流代码和lambda表达式并不能提供最易读的代码,但也许是你学习的东西。 在任何情况下,基本方法是根据是否存在标题为“Java 8”的书籍过滤库流,并将满足过滤谓词的库作为集合返回。 过滤本身要求将每个库变成书籍流,这需要两个平面映射操作。 然后,我使用anyMatch匹配书名并终止给定库的流。 你可以并行化我所期望的过程,但是我并没有在并行数据流上做很多事情。
下面提供的示例将搜索过程外化。 更合适的面向对象的方法将包括Section和BookShelf类中的图书搜索功能,这将大大提高可读性。
请记住,您正在顺序搜索一本书,顺序搜索速度很慢。 顺序搜索是O(n),而HashMap索引搜索是O(1)。 我会在BookShelf类中包含一个索引。 我提供了一个下面的顺序搜索算法的示例(未测试)。
public Collection<Library> hasBook(Collection<Library> libraries, String title) {
return libraries.stream()
.filter(x->x.sections()
.stream()
.flatMap(y->y.bookShelves()
.stream()
.flatMap(z->z.books().stream()))
.anyMatch(b->b.title().equals(title)))
.collect(Collectors.toList());
}
使用John Morris的解决方案来调整地图可以解决问题:
/*
* Using Streams
*/
public static Collection<Library> hasBook(Collection<Library> libraries, String title) {
return libraries.stream()
.filter(x->x.sections.values()
.stream()
.flatMap(y->y.bookShelves
.stream()
.flatMap(z->z.books.values().stream()))
.anyMatch(b->b.name.equals(title)))
.collect(Collectors.toList());
}
调用代码:
/*
* Search using streams
*/
Collection<Library> libs = hasBook(libraries, "Java 8");
for (Library l : libs) {
System.out.println("Book is contained in Library (via streams) " + l);
}
链接地址: http://www.djcxy.com/p/16345.html