3

给定 List<Student>每个Student都有的位置List<Book>,按Bookfor分组List<Student>

工作解决方案(使用 Java 9) 我已经有下面提到的工作代码

public class Demo {
    public static void main(String[] args) {

    List<Student> studs = createStudents();

        var data = studs.stream()
                .flatMap(s -> s.getBooks()
                        .stream()
                        .map(b -> Pair.of(b, s))) // <------ is possible without using external class?
                .collect(Collectors.groupingBy(
                        p -> p.getBook(),
                        Collectors.mapping(p -> p.getStud().getFirstName(), Collectors.toList())));
        System.out.println("All books: " + data);
    }

    private static List<Student> createStudents() {
        Book javaCompleteReference = new Book("Java Complete Reference");
        Book ocjp = new Book("Java OCJP");
        Book sql = new Book("SQL");
        Book spring = new Book("SPRING in Action");

        return List.of(
                new Student(1, "A", List.of(javaCompleteReference, spring)),
                new Student(2, "B", List.of(spring, sql, ocjp)),
                new Student(3, "C", List.of(javaCompleteReference, sql))
        );
    }
}

寻找:

  1. 我使用了 flatMap 和一个中间类 Pair。是否可以在不使用 Pair 类的中间转换的情况下实现最终结果

代码库:

public class Book {
    private String title;
    private String id;
    private Integer pages;

    public Book(String title, String id, Integer pages) {
        this.title = title;
        this.id = id;
        this.pages = pages;
    }

    public Book(String title) { this.title = title; }

    public String getTitle() { return title; }

    public String getId() { return id; }

    public Integer getPages() { return pages; }

    @Override
    public String toString() { return title; }
}

class Pair {
    Book book;
    Student stud;

    private Pair(Book book, Student stud) {
        this.book = book;
        this.stud = stud;
    }

    static Pair of(Book book, Student stud) { return new Pair(book, stud); }

    public Book getBook() { return book; }

    public Student getStud() { return stud; }
}

public class Student {
    private Integer id;
    private String firstName;
    private List<Book> books;

    public Student(Integer id, String firstName, List<Book> books) {
        this.id = id;
        this.firstName = firstName;
        this.books = books;
    }

    public Integer getId() { return id; }

    public String getFirstName() { return firstName; }

    public List<Book> getBooks() { return books; }
}

输出:All books: {Java Complete Reference=[A, C], SQL=[B, C], SPRING in Action=[A, B], Java OCJP=[B]}

4

2 回答 2

0

只要您需要在上下文中保留有关学生姓名和每本书的信息以形成输出映射,使用 Stream API不可能做到一点。将平面映射成单个元素(对)是唯一可行的方法。

一个证明和一个替代(我猜不是更好)的解决方案是使用你定义所有,Collectors.flatMapping和. 你可以清楚地看到,你需要所有学生的名字每个书的关系的组合。Collectors.toMapkeyMappervalueMappermergeFunctionCollectors.grouping

var data = studs.stream().collect(Collectors.flatMapping(
    student -> student.getBooks()
                      .stream()
                      .map(book -> new AbstractMap.SimpleEntry<>(
                              student.getFirstName(), book)),
    Collectors.toMap(
        AbstractMap.SimpleEntry::getValue,
        entry -> new ArrayList<>(List.of(entry.getKey())),
        (leftList, rightList) -> { leftList.addAll(rightList); return leftList; })));
于 2021-03-01T10:08:08.937 回答
0

可以不使用外部类吗?

是的,即使在早期版本的 java 中也是可能的。只需使用AbstractMap.SimpleEntry<K, V>

.map(b -> new AbstractMap.SimpleEntry<>(b, s)))

然后您可以通过调用getKey()和访问这些值getValue()

于 2021-02-28T14:18:54.330 回答