Java8 Stream API

java8引入了函数式编程,而Stream API便是函数式编程的一个典型,它使得程序员对集合(List,Set,Map…)类型的处理更加的高效,使得代码更加的简洁、优雅。

在 Stream API 中,最重要的两个操作函数:

  • stream()
    它是一个流式操作,处理数据源。parallelStream()是它的并发处理。
  • collect
    它是一个归约操作,收集stream()的处理结果并按指定形式输出

记一些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=大同}]}

    }

}

性能方面

  • 单核情况下,简单的操作,比如基本类型集合的遍历,Stream性能不如for。
  • 单核情况下,复杂的操作,stream性能和for差不多。
  • 多核情况下,Stream API 的并发操作 parallelStream() 性能强于 for

但是使用parallelStream()并发操作时,要慎重,它的执行结果可能会出乎你的意料。

Stream API 基于Java 8 的函数式编程,使用 lamda ,这对于不精此道的同学而言,代码的可读性并没有么好,代码维护可能更费力。

所以,Stream API 可用,但要酌情使用。


记录成长,热爱生活!

你可能感兴趣的:(java)