[英]Java 8: Iterate and group objects from list based on object attributes
我有一个列表(GlobalBooks),看起来类似于下面
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
GlobalBooks globalBooks = new GlobalBooks();
List<Book> bookList = new ArrayList<Book>();
Book book = new Book();
List<BookContent> bookContents = new ArrayList<BookContent>();
book.setBookName("A");
BookContent content = new BookContent();
content.setDescription("December 2016");
content.setComponentID(20l);
bookContents.add(content);
content = new BookContent();
content.setDescription("January 2016");
content.setComponentID(30l);
bookContents.add(content);
content = new BookContent();
content.setDescription("Febuary 2016");
content.setComponentID(40l);
bookContents.add(content);
book.setContents(bookContents);
bookList.add(book);
book = new Book();
bookContents = new ArrayList<BookContent>();
book.setBookName("B");
content = new BookContent();
content.setDescription("December 2016");
content.setComponentID(20l);
bookContents.add(content);
content = new BookContent();
content.setDescription("January 2016");
content.setComponentID(30l);
bookContents.add(content);
content = new BookContent();
content.setDescription("Febuary 2016");
content.setComponentID(40l);
bookContents.add(content);
book.setContents(bookContents);
bookList.add(book);
globalBooks.setBooks(bookList);
System.out.println(globalBooks);
}
}
我正在寻找java 8函数,它们可以流式传输globalBooks响应,并根据BooksContent中的description字段收集Book of Book的地图。
Map<String,List<Books>>
即所有具有相同描述的书籍应按描述分组?
我可以通过常规java来做到这一点,但代码变得太杂乱和不整洁。
由于每本书都有多个内容和不同的描述,因此您需要将每本书出现在多个地图条目中。 所以我会使用flatMap
为每个BookContent创建一个流元素,特别是Description + Book对。 然后像往常一样用Collectors.groupingBy
收集到地图中:
Map<String,List<Book>> result = globalBooks.getBooks().stream().flatMap(
(Book b) -> b.getContents().stream().map(
(BookContent bc) -> new Pair<>(bc.getDescription(), b)
)
).collect(Collectors.groupingBy(
Pair::getKey,
Collectors.mapping(Pair::getValue, Collectors.toList())
));
注意:
我上面使用的Pair类来自javafx.util.Pair
。 但是,您可以轻松地使用AbstractMap.SimpleEntry
,您自己的Pair类或任何能够容纳两个对象的集合数据类型。
另一个解决方案可能是
Map<String,List<Book>> result = new HashMap<String, List<Book>>();
globalBooks.getBooks().stream().forEach(book->{
book.getContents().stream().forEach(bookContent->{
result.computeIfAbsent(bookContent.getDescription(),(list)->new ArrayList<Book>()).add(book);
});
});
这将完成工作:
Map<String, List<String>> result = bookList.stream().flatMap(b -> b.getContents().stream())
.collect(Collectors.toMap(str -> str, str -> bookList.stream()
.filter(b -> b.getContents().contains(str))
.collect(Collectors.toList()), (a, b) -> {a.addAll(b);return a;}));
如果要并行执行此操作,只需使用Collectors.toConcurrentMap
替换收集Collectors.toConcurrentMap
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.