java8引入了函数式编程,而Stream API便是函数式编程的一个典型,它使得程序员对集合(List,Set,Map…)类型的处理更加的高效,使得代码更加的简洁、优雅。
在 Stream API 中,最重要的两个操作函数:
记一些Stream常用的api:
public class StreamAPITest {
/**
* stream() 单线程处理
* parallelStream() 多线程处理
*/
//---------------------------------------------流的转换---------------------------------------------------
//filter map forEach
@Test
public void streamTest1(){
List<Integer> list = new ArrayList();
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
//filter-过滤 筛选出符合条件的元素组成新的集合
List<Integer> filterList = list.stream().filter(num -> num>5).collect(Collectors.toList());
System.out.println(filterList);//[6, 7]
//map-遍历处理每一个元素 组成新的集合
List mapList = list.stream().map(num -> ++num).collect(Collectors.toList());
System.out.println(mapList);//[3, 4, 5, 6, 7, 8]
//forEach 遍历元素,没有返回值,只是遍历。与map的区别是map可以修改并且有返回值,会生成新的集合。
list.stream().forEach(num -> System.out.println(num)); //2 3 4 5 6 7
}
//flatMap
@Test
public void streamTest2(){
List<Integer> list1 = new ArrayList();
list1.add(1);
list1.add(11);
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(22);
Map<String ,List<Integer>> map = new HashMap();
map.put("list1",list1);
map.put("list2",list2);
//flatMap - 如果返回值是stream,则将stram合并。适用于嵌套集合的处理
List<Integer> result = map.values().stream().flatMap(list -> list.stream()).collect(Collectors.toList());
System.out.println(result);//[1, 11, 2, 22]
}
//limit skip
@Test
public void streamTest3(){
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//limit 只要元数组中前n个元素,其他的丢弃
List<Integer> list1 = list.stream().limit(3).collect(Collectors.toList());
System.out.println(list1);//[1, 2, 3]
//skip 与limit相反 丢弃前n个元素,留下后面的
List<Integer> list2 = list.stream().skip(3).collect(Collectors.toList());
System.out.println(list2);//[4,5]
}
//distinct sorted
@Test
public void streamTest4(){
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(4);
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
//distinct-去重,当然是equals
List<Integer> list1 = list.stream().distinct().collect(Collectors.toList());
System.out.println(list1);//[1, 2, 3, 4, 5]
//sorted-排序 当然是Comparable
List<Integer> list2 = list.stream().sorted().collect(Collectors.toList());
System.out.println(list2);
}
//max min findFirst anyMatch allMatch reduce
@Test
public void streamTest5(){
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
//max - 获取最大值 min-获取最小值
String max = list.stream().max(String::compareTo).get();
System.out.println(max);//c
//findFirst-获取stream中第一个元素 findAny-返回任何一个线程拿到的第一个元素
String first = list.parallelStream().findFirst().get();
System.out.println(first);//a
//anyMatch 是否存在满足条件的元素,存在true,不存在false allMatch-是否所有元素都满足条件 noneMatch-是否所有元素都不满足条件
boolean b1 = list.stream().anyMatch(i -> i.equals("a"));
System.out.println(b1);//true
//reduce - 计算元素
Integer sum = list.stream().map(i->i.length()).reduce(Integer::sum).get();
System.out.println(sum); //3
}
//---------------------------------------------归约结果---------------------------------------------------
//toList toSet joining
@Test
public void collectTest1(){
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
//Collectors.toList() - 结果归约为list
List<String> collectList = list.stream().collect(Collectors.toList());
System.out.println(collectList); //[a, b, b, c]
//Collectors.toSet() - 结果归约为set
Set<String> collectSet = list.stream().collect(Collectors.toSet());
System.out.println(collectSet); //[a, b, c]
//joining = 集合中元素拼接,并指定拼接符、开头、结尾
String collectJoining = list.stream().collect(Collectors.joining("]-[", "[", "]"));
System.out.println(collectJoining); //[a]-[b]-[b]-[c]
}
//summingInt averagingInt maxBy minBy toMap
@Test
public void collectTest2(){
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(2);
list.add(4);
list.add(1);
//求和
Integer sum = list.stream().collect(Collectors.summingInt(Integer::intValue));
System.out.println(sum);
//求平均值
Double averag = list.stream().collect(Collectors.averagingInt(Integer::intValue));
System.out.println(averag);
//求最大值
int max = list.stream().collect(Collectors.maxBy(Integer::compareTo)).get();
System.out.println(max);
//求最小值
int min = list.stream().collect(Collectors.minBy(Integer::compareTo)).get();
System.out.println(min);
//toMap 自定义转map
Map<String, String> map = list.stream().collect(Collectors.toMap(i -> i + "-key", i -> i + "-value"));
System.out.println(map);
}
//groupingBy partitioningBy
@Test
public void collectTest3() {
List<Map<String, String>> mapList = new ArrayList<>();
HashMap<String, String> map1 = new HashMap<>();
map1.put("province", "山西");
map1.put("city", "太原");
mapList.add(map1);
HashMap<String, String> map2 = new HashMap<>();
map2.put("province", "山西");
map2.put("city", "大同");
mapList.add(map2);
HashMap<String, String> map3 = new HashMap<>();
map3.put("province", "云南");
map3.put("city", "昆明");
mapList.add(map3);
HashMap<String, String> map4 = new HashMap<>();
map4.put("province", "浙江");
map4.put("city", "杭州");
mapList.add(map4);
//groupingBy - 分组 根据省份分组:
Map<String, List<Map<String, String>>> newMap = mapList.stream().collect(Collectors.groupingBy(map -> map.get("province")));
System.out.println(newMap); //{山西=[{province=山西, city=太原}, {province=山西, city=大同}], 浙江=[{province=浙江, city=杭州}], 云南=[{province=云南, city=昆明}]}
//分组时获取每组数量
Map<String, Long> countMap = mapList.stream().collect(Collectors.groupingBy(map -> map.get("province"), Collectors.counting()));
System.out.println(countMap);
//partitioningBy - 分片 是山西省的分为一片,不是山西省的分为另一片
Map<Boolean, List<Map<String, String>>> newMap2 = mapList.stream().collect(Collectors.partitioningBy(map -> map.get("province").equals("山西")));
System.out.println(newMap2); // {false=[{province=云南, city=昆明}, {province=浙江, city=杭州}], true=[{province=山西, city=太原}, {province=山西, city=大同}]}
}
}
性能方面
但是使用parallelStream()并发操作时,要慎重,它的执行结果可能会出乎你的意料。
Stream API 基于Java 8 的函数式编程,使用 lamda ,这对于不精此道的同学而言,代码的可读性并没有么好,代码维护可能更费力。
所以,Stream API 可用,但要酌情使用。