一、对象list转map、list
对象如下:
class User{
String name;
String id;
}
list集合如下:
List<User> userList = List.newArrayList(
new User().setId("1").setName("李雷"),
new User().setId("2").setName("林涛"),
new User().setId("3").setName("汤姆")
);
过去要是用for循环取值并put到map中去,现在使用jdk8新特性,如下:
Map<String , String> map = userList .stream().collect(Collectors.toMap(User::getId, User::getName));
防止key冲突:
Map<String , String> map = userList .stream().collect(Collectors.toMap(User::getId, User::getName, (f1, f2) -> f1));
防止key冲突(分组):
(假设ID不是唯一键)将相同ID的的 name 放在一个集合中。
Map<String, Set<String>> map2 = userList .stream().collect(Collectors.groupingBy(User::getId, Collectors.mapping(User::getName, Collectors.toSet())));
如果参数为对象:
Map<String , User> map = userList .stream().collect(Collectors.toMap(User::getId, t ->t));
取某一属性转list或set:
Set<String> set = userList.stream().map(User::getId).collect(Collectors.toSet());
二、map的用法
取list中对象的某个属性存入新的list在上一节已经使用过了,这里写一个复杂一点的,比如将list中的User对象转为其他对象后返回一个新List:
List<User2> userList2 = userList.stream.map(
a -> {
User2 user2 = 处理方法(a);
return user2;
}
)
.collect(Collectors.toList());
三、“::”的用法
如上【对象list转map】的示例中所示,双冒号的用法,就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。
如1.8之前list转map:
for(User user : userList ){
map.put(user.getId , user.getName());
}
四、并行流
并行流 parallelStream \ IntStream.parallel()
使用方法与stream一样,是一种多线程异步任务。
如 parallelStream() 分段查询结果集:
public Set<String> getAllDto(){
List<Dto1> allDto = new ArrayList<>();
List<Runnable> taskList = new ArrayList<Runnable>() {
{
for (int i = 1; i < 5; i++) {
final int a = i;
add(() -> allDto.addAll(getDto1(a)));
}
}
};
taskList.parallelStream().forEach(v -> v.run());
}
private List<Dto1> getDto1(int a){
RequestClass query = new RequestClass() ;
query.setPage(a);
List<Dto1>> pageResult = service1.queryDto1(query);
return pageResult;
}
可替换为 IntStream.parallel():
private List<Dto1> getDto1(int a){
//总页数
int page = 9;
List<Dto1> allList = IntStream.range(1,page + 1)
.boxed()
.parallel()
.map(page -> {
RequestClass query = new RequestClass() ;
query.setPage(page);
return Optional.ofNullable(service1.queryDto1(query))
.orElse(Collections.emptyList());
})
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
flatMap()的用法(如根据ID集合批量查询):
//所有ID集合
List<String> allIdList = new ArrayList<>(Arrays.asList("1","2","3"));
//集合切片
List<List<String>> idList = Lists.partition(allIdList , 10);
//设置默认线程池并发数
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "4");
/* //或者使用此方法修改默认线程池参数
ForkJoinPool forkJoinPool = new ForkJoinPool(8);
try{
//查询用户
List<User> userList = forkJoinPool.submit(() -> idList.parallelStream()
.map(p -> getUserListByIds(p))
.flatMap(Collection::stream)
.collect(Collectors.toList())
).get();
}catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}finally {
forkJoinPool.shutdown();
}
*/
//查询用户
List<User> userList = idList.parallelStream()
.map(p -> getUserListByIds(p))
.flatMap(Collection::stream)
.collect(Collectors.toList());
这段代码中,flatMap() 的作用就是将 map返回的集合扁平化,更直观的展示如下代码:
public static void main(String[] args) {
List<String> strList = new ArrayList<>(Arrays.asList("Hello","World"));
List<String> streamList = strList.parallelStream().map(word -> word.split(""))
.flatMap(t -> Arrays.stream(t))
.collect(toList());
System.out.println("streamList = " + JSONObject.toJSONString(streamList));
}
执行结果:
streamList = ["H","e","l","l","o","W","o","r","l","d"]
注意事项:并行流使用的默认线程池是 ForkJoinPool,当服务器核心数大于2时使用线程池,若不大于2,则不使用线程池,直接创建线程执行多线程任务,ArrayList会有线程安全问题,所以在处理复杂业务时要注意线程数量及线程安全问题。