繁体   English   中英

Java流,获取对象列表的映射

[英]Java stream, get map of lists of objects

尝试使用 java 8 获取列表地图。我有一组预定义的标题:

String[] myStringArray = {"TITLE1", "TITLE2", "TITLE3"};

以及一些 Pages 对象的List<String>List<String> )。

如果在页面上找到了该数组中的值,我需要使用预定义数组中的键创建对象列表的映射。 结果应该是这样的:

{TITLE1=[page1, page2, page3], TITLE2=[page3, page4, page5]} 

(假设在页面列表中未找到 TITLE3)

我的代码:

Arrays.stream(myStringArray)
        .map(title -> page
                .stream()
                .filter(p -> isPageContainsTitle(p, title))
                .collect(Collectors.toList()))
        .filter(Objects::nonNull)
        .collect(Collectors.toMap(e->e, Function.identity()));

结果,我从 myStringArray 中得到了键为列表而不是值的列表映射:

{[page1, page2, page3]=[page1, page2, page3], [page3, page4, page5]=[page3, page4, page5]} 

只需确保数组具有唯一的标题,然后使用Collectors.toMap

Map<String, List<String>> result = Arrays.stream(myStringArray)
            .map(title -> new AbstractMap.SimpleEntry<>(title,
                    pages.stream().filter(page -> isPageContainsTitle(page,title)).collect(Collectors.toList())))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

正如@Naman 建议的那样,您可以避免中间map操作

Map<String, List<String>> result = Arrays.stream(myStringArray) 
                     .collect(Collectors.toMap(Function.identity() 
                                        ,title -> pages.stream()
                                                       .filter(page -> isPageContainsTitle(page, title))
                                                       .collect(Collectors.toList())));

下面的代码应该适合你:

package com.shree.test;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StreamTest {
    public static void main(String[] args) {
        String[] myStringArray = {"TITLE1", "TITLE2", "TITLE3"};
        List<String> pages = new ArrayList<>();
        pages.add("TEXT,TITLE2,TEXT,ONE,TWO");
        pages.add("TEXT,TITLE1,TEXT,ONE,TWO");
        pages.add("TEXT,TITLE2,TEXT,ONE,TWO");
        pages.add("TEXT,TITLE2,TEXT,TITLE3,TWO");
        pages.add("TEXT,TITLE3,TEXT,ONE,TWO");



         Map<Object, Object> titleMap = getTitleMap(myStringArray, pages);

         titleMap.entrySet().forEach(System.out::println);
    }

    private static Map<Object, Object> getTitleMap(String[] myStringArray, List<String> pages) {
        Map<Object, Object> titleMap = Arrays.asList(myStringArray).stream()
            .map(
                    (title)->{
                        return new AbstractMap.SimpleEntry<>(title, pages.stream()
                                .filter((page)->page.contains(title))
                                .collect(Collectors.toList()));
                    }
                )
            .collect(Collectors.toMap(entry->entry.getKey(), entry->entry.getValue()));
        return titleMap;
    }
}

所以

 e->e

  Function.identity()

是并且应该是等价的。

你真正想要的是一个 flatMap:

  Arrays.stream(myStringArray)
                .flatMap(title -> pages
                        .stream()
                        .filter(p -> isPageContainsTitle(p, title))
                        .map( p -> new Tuple(t, p)) 
                 )
                 .collect(Collectors.groupingBy( t -> t._1, t -> t._2));

我们想要 flatMap 因为我们可能会得到 0、1 或许多 (title, page) 的元组

这假设您有一个 Tuple 类,我正在基于 Scala 的 Tuple2 建模一个。

请注意,我尚未测试此代码。

我可以看到使用单独的对象执行此操作的唯一方法是将它们映射到StringList<Page>类型的两个元素数组到一个数组,然后使用这些条目来构建映射。

Object[]{}数组将包含标题和列表。 这是跨嵌套流保留两个值的唯一方法。

后来我将它们转换为创建Map<String,List<Page>>

这不需要修改您现有的数据结构。

 Map<String, List<Page>> map = Arrays.stream(myStringArray)
            .map((String title) -> new Object[] {title,
                                       page.stream().filter(
                                   (Page p) -> isPageContainsTitle(p, title)).collect(
                                    Collectors.toList())})
            .filter(arr->arr[1] != null)
            .collect(Collectors.toMap(arr -> (String)arr[0], arr -> (List<Page>)arr[1]));

最终的 List 演员中有一个类型安全警告,但应该没问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM