JAVA 8部分新特性内容

JAVA 8 (jdk 1.8)

部分新特性

  • Lambda表达式
  • 默认方法
  • Stream API

Lambda的介绍

lambda的语法表达式:
(parameters)-> expression
(parameters) ->{ statements; }
看使用场景来决定使用哪种。类似于if要不要加{}
parameters:请求参数不需要声明参数类型,编译器可以统一识别参数值【可以写上参数类型方便阅读】。
可选参数圆括号:一个参数无需定义圆括号【也可以写】,但是多个参数一定需要定义圆括号。
可选大括号:大括号为代码块,如果只包含一条语句,可以不使用。
可选的返回关键字:如果主体只有一个表达式返回值,编译器会自动返回值,大括号只需指明表达式返回了一个数值。

一般lambda函数式接口一起使用
**函数式接口:**类由interface修饰,仅仅只包含一个抽象方法的接口。但是java8引入了接口的默认方法。
因为interface修饰的类仅仅包含一个抽象方法,所以,使用lambda表达式,可以自动定位到方法,可以自动匹配到函数参数
比如:下面这个接口类,只有一个函数void accept(T t);

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
	......
}

官方的案例:
@FunctionalInterface只是一个单纯的标签,标注该类仅仅只包含一个抽象方法的接口

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
	......
}

Stream流的介绍与Lambda的使用

lambda表达式与Stream连用比较多,顺便了解stream
流的数据来源:集合,数组,I/O,产生器generator等。
聚合操作:类似于SQL一样的操作,比如fifter,map,reduce,find,match,sorted和forEach
生成流

  • stream() − 为集合创建串行流。
  • parallelStream() − 为集合创建并行流

forEach
forEach是stream提供的新方法,来迭代每个流中的数据。
我们查看forEach的源码发现:

void forEach(Consumer<? super T> action);

参数为Consumer对象,查看Consumer源码:

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
    ......

该类由@FunctionalInterface可知,我们可以使用lambda表达式声明一个Consumer对象

Consumer<Integer> consumer = integer ->
        System.out.println("当前流的数据:"+integer);

遍历一个Integer的list使用Stream 和 Lambda表达式可如下:

List<Integer> list = Arrays.asList(10,52,15,32,45,01,20);
        Consumer<Integer> consumer = integer ->
                System.out.println("当前流的数据:"+integer);
        list.stream().forEach(consumer);

也可以写为:

 list.stream().forEach(integer -> System.out.println("当前流的数据:"+integer));
运行结果如下:
当前流的数据:10
当前流的数据:52
当前流的数据:15
当前流的数据:32
当前流的数据:45
当前流的数据:1
当前流的数据:20

如果使用parallelStream()创建流,打印顺序并不是预先设定好的,得知parallelStream为并行。【以前看到过一个帖子说是开启线程,俺没有验证】
filter
filter通过设置条件过滤元素,定义一个Student实体类,找出叫张三的学生
查看filter源码以及filter的参数源码如下:

//filter源码
Stream<T> filter(Predicate<? super T> predicate);
//filter需要的函数接口源码  该源码返回boolean类型,得知,我们如果返回true则保留
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    ......
}

完成代码如下:

       List<Student> students = Arrays.asList(
            new Student("王五",1),
            new Student("张三",2),
            new Student("李四",3),
            new Student("张三",4),
            new Student("田六",5),
            new Student("王五",6),
            new Student("赵七",7)
    );
    
students.stream()//开启流
        .filter(item->"张三".equals(item.getName()))//过滤张三
        .collect(Collectors.toList())//设置为新的list【需要设置新对象使用,这里用不用都可以】
        .forEach(zs-> System.out.println("name:"+zs.getName()+",ID:"+zs.getId()));//打印

执行结果如下:

name:张三,ID:2
name:张三,ID:4

上面介绍了如何使用lambda ,可以将lambda当做一个特殊的参数【实现了代码块参数】
**

Stream下的函数:

**



filter

//strean下的函数
Stream<T> filter(Predicate<? super T> predicate);

//该函数需要的参数对应的参数类型
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

代码应用

 System.out.println("----------------------------------------------------------");
 List<Integer> ints = Arrays.asList(1,20,40,33,5,2,2,40);
 ints.stream().filter(a->a>=20)
.forEach(item-> System.out.println(item));
 System.out.println("----------------------------------------------------------");

执行结果如下
------------------------------------------------------------------------
20
40
33
40
------------------------------------------------------------------------


map(我将这个理解为类型转换)

//strean下的函数
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

//该函数需要的参数对应的参数类型
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

代码应用(注意到apply是有返回值的,如果一行代码可以省略,如果写的{}就不能省略)

List<Integer> ints = Arrays.asList(1,20,40,33,5,2,2,40);
System.out.println("---------------------------------------------------------");
 ints.stream().map(integer -> String.valueOf(integer+1))
.forEach(item-> System.out.println(item+1));
 System.out.println("---------------------------------------------------------");

运行结果(map将Integer类型转换为String类型)

-----------------------------------------------
21
211
411
341
61
31
31
411
-----------------------------------------------


mapToInt 将数据类型转换为int类型。下面的代码没有省略 return,没有省略声明lambda表达式的声明

        System.out.println("-----------------------------------------------");
        //声明一个String类型数组,为了省事,就cp上面的代码了。
        List<String> sint = ints.stream().map(integer -> String.valueOf(integer+1)).collect(Collectors.toList());
        //声明ToIntFunction实例,并且实现接口里的唯一一个抽象方法
        ToIntFunction<String> stringToIntFunction = intString ->{
          return Integer.parseInt(intString);
        };
        //实现IntStream.forEach()需要的IntConsumer 实例,并且实现接口抽象方法
        IntConsumer intConsumer = item-> System.out.println(item+50);
        sint.stream().mapToInt(stringToIntFunction).forEach(intConsumer);
        System.out.println("-----------------------------------------------");

运行结果:

-----------------------------------------------
52
71
91
84
56
53
53
91
-----------------------------------------------


mapToLong
mapToDouble
Stream下的这两个函数,与mapToInt类似。就不一一举例了。



该图来源:https://blog.csdn.net/Mark_Chao/article/details/80810030
该图引用于:https://blog.csdn.net/Mark_Chao/article/details/80810030
stream还有排序等等等等都可以用查看源码,来得到是如何使用以及它的功能。
看了源码哪怕不了解原理,知道怎么用还是能达到的。
其他细节参考各种学习网站都可以,这里只是记录本人学习过程,以及使用后记录下来的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值