Java 8:根据对象属性从列表中迭代和分组对象

时间:2017-02-03 05:21:56

标签: java java-8 java-stream

我有一个列表(GlobalBooks),看起来类似于下面的

SELECT e1.EID,l1.LID,e1.Name,l1.Location,l1.Address 
FROM Employee e1 JOIN
(SELECT MIN(

我正在寻找java 8函数,这些函数可以传输globalBooks响应,并根据BooksContent中的description字段收集Book of Book的地图。

)as Mineid,EID,LID,Location,Address,,即所有具有相同描述的书籍应按说明分组?

我可以通过常规java来做到这一点,但代码变得太杂乱和不整洁。

3 个答案:

答案 0 :(得分:6)

由于每本书都有多个内容和不同的描述,因此您需要将每本书出现在多个地图条目中。所以我会使用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类或任何能够容纳两个对象的集合数据类型。

答案 1 :(得分:1)

另一种解决方案可能是

    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);
        });
    });

答案 2 :(得分:1)

这将完成这项工作:

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简单地替换收集器。