java8流式API

stream流式API

stream 的思想是内部迭代,for-each是外部迭代。
流只能使用一次。

stream 优势:

  • 并行 能充分利用多核
  • 能直观描述数据的操作,代码可读性更高

创建流的方式

//        1、创建stream的方式,通过Collection集合提供的stream或者parallerStream()
        ArrayList<Object> list = new ArrayList<>();
        Stream<Object> stream1 = list.stream();
//        list.parallelStream();

//        2、通过Arrays中的静态方法stram()获取数组流
        Integer[] ints = new Integer[10];
        Stream<Integer> stream2 = Arrays.stream(ints);

//        3、通过Stream中的静态of方法
        Stream<String> stream3 = Stream.of("aa", "bb", "cc");

//        4、创建无限流
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        String xx = stream3.reduce("xx", (x, y) -> {
            return x + y;
        });

流的中间操作和终端操作

中间操作:

  • filter
  • distinct
  • skip
  • limit
  • map
  • flatmap
  • sorted
    终端操作:
  • anyMatch
  • noneMatch
  • allMatch
  • findAny
  • findFirst
  • forEach
  • collect
  • reduce
  • count

原始类型流

  • DoubleStream
    DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
  • IntStream
    IntStream mapToInt(ToIntFunction<? super T> mapper);
  • LongStream
    LongStream mapToLong(ToLongFunction<? super T> mapper);

lambda 表达式

lambda表达式可以作为参数传递给方法或者是存储在变量中
优势:简介,可读性好,正因为有了lambda表达式才有了jdk库里stream等流式API
劣势:个人认为目前存在最大的问题就是,由于lambda表达式没有名字,报错简陋,不方便调试。
ps: 因此,调试起来只能采用打印日志的方式就行调试,stream api 提供了peek方法,可以在元素恢复运行之前插入一段操作。

复合lambda表达式

比较器复合

  transactions.stream().sorted(Comparator.comparing(Transaction::getValue)) 等价于//transactions.stream().sorted(Comparator.comparing((transaction -> transaction.getValue())))

逆序

  transactions.stream().sorted(Comparator.comparing(Transaction::getValue).reversed())

比较器链

// 如果value一样 则比较year
	        transactions.stream()
                .sorted(Comparator.comparing(Transaction::getValue)
                        .thenComparing(Transaction::getValue))
                .forEach(System.out::println);

谓词复合

  • negate() 现有predicate对象的非
  • and()
  • or ()

函数复合

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.andThen(g);
int result = h.apply(1);//数学上等价于 g(f(x))
//Function<Integer, Integer> h = f.compose(g);  // 数学上等价于 g(f(x))

函数式接口

定义:只定义一个抽象方法的接口,即使接口定义了很多默认方法。只要接口只定义了一个抽象方法,它就仍然是一个函数式接口。
常见的函数式接口有:Runnable、Compator、Callable

方法引用

定义:方法引用是lambda的快捷写法,以便于提高可读性
方法应用分类:
1、指向静态方法的方法引用

	Integer::parseInt 等价于 (String str) ->Integer.parseInt(str)

2、指向实例对象的方法引用 (你在引用一个对象的方法,而这个对象本身是Lambda的一个参数)

List<String> list = Arrays.asList("a","b","c");
        list.sort(String::compareTo);   //等价于 (String str1,String str2)->str1.compareTo(str2);

3、指向外部对象的方法引用 (你在lambda中调用一个已经存在外部对象中的方法)

其它特殊的方法引用

构造函数方法引用

ClassName::new
无参构造函数方法引用

Supplier<Apple> c1 = Apple::new;
Apple a1 = c1.get(); 
等价于:
Supplier<Apple> c1 = () -> new Apple();
Apple a1 = c1.get();

一个参数构造方法引用

Function<Integer, Apple> c2 = Apple::new;
Apple a2 = c2.apply(110);

两个参数构造方法引用

BiFunction<String, Integer, Apple> c3 = Apple::new;
Apple c3 = c3.apply("green", 110);

使用流收集数据

筛选

  • filter() 谓词筛选,filter接受一个谓词
  • distinct() 去重
  • limit()截断流
  • skip()跳过流

映射

  • map (对流中的每一个元素应用函数,返回的是Stream)
  • flatMap 流的扁平化
    flatMap作用:
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
    给定一个函数,flatmap会对原先流中的每个元素apply此函数,得到一个新的值,并将所有的新值放到一个新的流中,最后返回该新流即是流的扁平化。
    map和flatMap的本质区别是map是返回一个新的元素,而flatmap是返回一个新的流。
    书上的例子是这样的
                List<String> collect =words.map(w -> w.split(""))
                            .flatMap(Arrays::stream)
                            .distinct()
                            .collect(Collectors.toList());

但是我最初的想法是,先将每个单词全部转换为大写,然后把每个字符切分成char[]数组,很遗憾的是
Steam不能够用char[] 构造,所以间接的用int[]构造流,然后转换为Character[],最后在将Character[]
扁平化到一个流中,然后去重收集起来。


        Stream<String> words = Stream.of("hello", "world", "China");
        List<Character> collect = words.map(String::toUpperCase)
                .map((str) -> {// 这一段代码是为了把char[]流转换为Character[]流,很奇怪,能够根据int[] double[]构造流 却不能根据char[]构造流
                    Character[] characters = str.chars().mapToObj(c -> (char) c).toArray(Character[]::new);
                    return characters;
                })
                .flatMap((chars -> Arrays.stream(chars)))
                .distinct()
                .collect(Collectors.toList());

匹配

  • anyMatch 检查是否至少有一个匹配
  • allMatch 检查是否匹配所有元素
  • noneMatch 确保没有任何元素与给定的谓词匹配

查找元素

  • findAny 返回任意元素
  • findFirst 查找第一个元素

规约

规约:将流中的元素反复结合起来,得到一个值,这样的查询被归类为规约操作。

元素求和
// 0是初始值 首先, 0作为Lambda(a)的第一个参数,从流中获得4作为第二个参数(b)。
0 +4得到4,它成了新的累积值。然后再用累积值和流中下一个元素5调用Lambda,产生新的累积值9int sum = numbers.stream().reduce(0, (a, b) -> a + b)
求最大值最小值
        List<Integer> numbers = Arrays.asList(1, 2, 4);
        Optional<Integer> max = numbers.stream().reduce(Integer::max);

收集器collect

查找最大值最小值
List<Integer> list = new ArrayList<>(Arrays.asList(100, 55, 34, 23, 88));
        Optional<Integer> max = list.stream().collect(Collectors.maxBy(Integer::max));
        System.out.println("最大值:"+max.get());//最大值:100

        Optional<Integer> min = list.stream().collect(Collectors.minBy(Integer::compare));
        System.out.println("最小值:"+min.get());//最小值:23
求和
Integer sum = list.stream().collect(Collectors.summingInt((num)->num));
        System.out.println("总和:"+sum);//总和:300
求平均值
Double avg = list.stream().collect(Collectors.averagingInt((num) -> num));
        System.out.println("平均值:"+avg);//平均值:60.0
连接字符串
//        连接字符串
        String joining1 = list.stream()
                .map((num) -> num.toString())
                .collect(Collectors.joining());
        String joining2 = list.stream()
                .map((num) -> num.toString())
                .collect(Collectors.joining(","));
        System.out.println(joining1);//10055342388
        System.out.println(joining2);//100,55,34,23,88
Collectors.reducing()

上面的收集器都可以用reducing实现,但是可读性降低了。

收集器转换
 List<Integer> collect = list.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<Integer>(Integer::compareTo)), ArrayList::new));
分组

假设有一组学生成绩,按照优秀、一般、差进行分组。

  Map<GradeLevel, List<Integer>> groups = list.stream().collect(Collectors.groupingBy((num) -> {
            if (num < 60)
                return GradeLevel.BAD;
            else if (num < 80)
                return GradeLevel.JUST_SO_SO;
            else if (num > 80 && num <= 100)
                return GradeLevel.GOOD;
            else
                return GradeLevel.ILGEAL;
        }));
        System.out.println(groups);//{BAD=[55, 34, 23], GOOD=[100, 88]}
多级分组

groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
groupingBy的第二个参数接受Collector类型,因此可以传递分组收集器

// 男女生的成绩进行分组
        Map<Character, Map<GradeLevel, List<Stuent>>> map = list.stream().collect(Collectors.groupingBy(Stuent::getSex, Collectors.groupingBy((stu) -> {
            if (stu.getGrade() < 60)
                return GradeLevel.BAD;
            else if (stu.getGrade() < 80)
                return GradeLevel.JUST_SO_SO;
            else if (stu.getGrade() > 80 && stu.getGrade() <= 100)
                return GradeLevel.GOOD;
            else
                return GradeLevel.ILGEAL;
        })));
        System.out.println(map);
分区

分区只是分组的特例而已
partitioningBy() 接受一个谓词,返回true 或者false

   Map<Boolean, List<Stuent>> collect = list.stream().collect(Collectors.partitioningBy((stu) -> {
            return '女' == (stu.getSex());
        }));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java流式编程常用API包括:java.util.stream.Stream、java.util.stream.IntStream、java.util.stream.LongStream、java.util.stream.DoubleStream等。 ### 回答2: Java流式编程常用的API有: 1. Stream APIJava 8引入的新特性,用于处理集合数据的功能。可以对集合进行筛选、排序、映射等操作,具有较高的灵活性和性能。 2. Collectors API:用于对Stream中的元素进行汇总的API。可以将元素收集到List、Set、Map等数据结构中,也可以进行分组、分区等操作。 3. Predicate API:用于筛选Stream中的元素。可以根据指定的条件,对元素进行过滤,返回满足条件的元素流。 4. Function API:用于对Stream中的元素进行转换的API。可以对元素进行映射、提取等操作,返回转换后的元素流。 5. Optional API:用于处理可能为空的数据的API。可以对可能为空的值进行安全处理,避免出现空指针异常。 6. Comparator API:用于比较对象的API。可以用于对集合中的元素进行排序,定义自定义的排序规则。 7. Iterator/Iterable API:用于遍历集合元素的API。可以使用Iterator对集合中的元素进行迭代访问,也可以通过实现Iterable接口实现自定义集合的遍历。 8. BufferedReader/BufferedWriter API:用于处理文本文件的输入输出的API。可以提高文件读写的效率,减少I/O操作的次数。 9. Files API:用于处理文件和目录的API。可以创建、复制、移动、删除文件及目录,以及判断文件是否存在等操作。 10. DateTime API:用于处理日期和时间的API。可以对日期和时间进行格式化、计算、比较等操作,提供了更加灵活和简便的操作方式。 ### 回答3: 以下是 Java 流式编程常用的 API: 1. Stream 类:Stream 类是 Java 8 引入的一个新特性,它提供了一种链式编程的方式来对集合进行操作。可以使用 Stream 类的各种方法来进行过滤、映射、排序、归约等操作,比如 filter、map、sorted、reduce 等。 2. Collectors 类:Collectors 类提供了一系列用于收集 Stream 中元素的静态方法。可以使用 Collectors 类提供的方法将 Stream 中的元素收集到一个集合中,比如 toList、toSet、toMap 等。 3. Optional 类:Optional 类是用来处理可能为空的值的。可以使用 Optional 类的方法来判断一个值是否存在,如果不存在,则可以使用默认值来替代。 4. forEach 方法:forEach 方法是 Stream 类的一个方法,可以对 Stream 中的每个元素进行遍历操作。可以使用 forEach 方法来遍历集合中的所有元素,并对每个元素执行指定的操作。 5. filter 方法:filter 方法用于对 Stream 中的元素进行过滤操作。可以使用 filter 方法来筛选出符合条件的元素,从而得到一个新的 Stream。 6. map 方法:map 方法用于对 Stream 中的元素进行映射操作。可以使用 map 方法将一个 Stream 中的元素转换为另一种类型,并得到一个新的 Stream。 7. sorted 方法:sorted 方法用于对 Stream 中的元素进行排序操作。可以使用 sorted 方法对 Stream 中的元素进行升序或者降序排序。 8. limit 方法:limit 方法用于对 Stream 进行截断操作。可以使用 limit 方法来限制 Stream 中元素的数量,从而得到一个新的 Stream。 这些都是 Java 流式编程常用的 API,它们提供了丰富的功能和灵活的操作方式,可以帮助开发者更方便地处理集合中的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值