尝试使用Java 8获取列表的地图。我有一组预定义的标题:
String[] myStringArray = {"TITLE1", "TITLE2", "TITLE3"};
以及一些Pages对象(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]}
答案 0 :(得分:3)
只需确保数组具有唯一的标题,然后使用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())));
答案 1 :(得分:2)
下面的代码应该对您有用:
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;
}
}
答案 2 :(得分:0)
所以
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或许多元组的(标题,页面)
这假设您有一个Tuple类,我正在基于Scala的Tuple2建模一个类。
注意,我尚未测试此代码。
答案 3 :(得分:0)
我看到的唯一方法是使用单独的对象将其映射到类型为String
和List<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强制转换中有类型安全警告,但应该没问题。