Java 8流图自定义函数并转换为Map

Java 8 stream map custom function and convert it to Map

我有以下对象:

public class Book {

    private Long id;
    private Long bookId;
    private String bookName;
    private String owner;
}

来自以下 table 的代表:

基本上,一本书可以由多个所有者拥有,即所有者“a”拥有书 1 和 2。

我有一个基本功能,当传递一个书籍对象时,将在一个列表中给出它的所有者。

private List<String> getBookToOwner(Book book) {
        List<String> a = new ArrayList<>();
        if (book.getOwner() != null && !book.getOwner().isEmpty()) {
            a.addAll(Arrays.asList(book.getOwner().split("/")));
        }
        return a;
}

我想用它来应用于每本书,检索它们的所有者并创建以下地图。

Map<String, List<Long>> ownerToBookMap;

像这样:

如何在这里使用流?

//books is List<Book>
Map<String, List<Long>> ownerToBookMap = books.stream().map( 
// apply the above function to get its owners, flatten it and finally collect it to get the above Map object
// Need some help here..
);

我使用 reduce 而不是 map

Map<String, List<Long>> ownerToBookMap = books.stream().reduce(
    HashMap::new,
    (acc,b) -> {
        getBookToOwner(b).stream().forEach( o -> {
            if (!acc.containsKey(o))
                acc.put(o, new ArrayList<Long>());
            acc.get(o).put(b.bookId);
        });
        return acc;
    }
).get();

将所有者平面映射为一个,创建条目,键为 单个 owner,值为 bookId。然后按键 (owner) 对结构进行分组。最后使用 Collectors::mapping 获取 bookIdList 而不是实际条目:

List<Book> books = ...

Map<String, List<Long>> booksByOwner = books.stream()
    .flatMap(book -> Arrays.stream(book.getOwner().split("/"))
             .map(owner -> new AbstractMap.SimpleEntry<>(owner, book.getBookId())))
    .collect(Collectors.groupingBy(
             AbstractMap.SimpleEntry::getKey, 
             Collectors.mapping(AbstractMap.SimpleEntry::getValue, Collectors.toList())));

您可以从书中获取所有者列表,然后使用 flatMap 将所有者和地图拼合为 bookIdowner 对。然后使用 groupingByowner 分组并收集 ownerbookId 列表。

Map<String, List<Long>> ownerToBookMap = 
     books.stream()
          .flatMap(b -> getBookToOwner(b)
                         .stream()
                         .map(o -> new AbstractMap.SimpleEntry<>(o, b.getBookId())))
          .collect(Collectors.groupingBy(Map.Entry::getKey,
                     Collectors.mapping(Map.Entry::getValue, Collectors.toList())));