JDK8经典特性回顾

一、Lambda

Lambda表达式体现的是函数式编程思想,只需要把执行的代码放到函数中(函数就是类中的方法),Lambda是一个匿名含函数,秩序将要执行的代码放到Lambda表达式中即可。一般看到方法的参数是接口的优先考虑用Lambda,可以想象成Lambda表达式是对接口中抽象方法的重写。
好处:可以简化匿名内部类,减少代码冗余,让代码更加精简。

public class LambdaTest {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable内部处理");
            }
        }).start();
        
        new Thread(() -> System.out.println("Lambda内部处理")).start();
    }
}

实现原理:
运行时会发现并没有产生一个新的class文件,可以使用jdk自带的工具javap,进行对字节码的反汇编,来进行查看实现原理。如下:

cmd-> javap -c -p 文件名.class
注:-c:表示对代码进行反汇编;-p:显示所有类的成员

private static void lambda$main$0();
    Code:
       0: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #9                  // String Lambda内部处理
       5: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

还可以通过:

java -Djdk.internal.lambda.dumpProxyClasses.包名.class类名。生成运行时class文件

匿名内部类在编译的时候会生成一个class文件,可以看到Lambda其实也是生成了一个匿名内部类,这个类也会实现这个接口,并实现接口的抽象方法。

final class LambdaTest$$Lambda$1
	implements Runnable
{

	public void run()
	{
		LambdaTest.lambda$main$0();
	}

	private LambdaTest$$Lambda$1()
	{
	}

Lambda在程序运行的时候形成一个类
1.会在类中新增一个方法,这个方法体就是一个Lambda表达式中的代码
2.形成一个匿名内部类,实现接口重写抽象方法
3.在接口的重写方法中会调用新生成的方法
4.方法的参数或局部变量类型必须为接口才能使用Lambda
5.接口中有且只能有一个抽象方法,否则Lambda不知道重写哪个方法。jdk8推出检测接口方法个数的注解,可避免开发中的疏忽:
在这里插入图片描述

常见引用方式
对象::方法名
类名::静态方法
类名::普通方法
类名::new调用的构造器
String[]::new调用数组构造器

小结:
当接口中只有一个抽象方法时,建议使用Lambda表达式,其他情况还是需要使用匿名内部类。

二、Stream

1.Stream获取方式

方式一:根据Conllection获取流(Conllection接口中有一个默认方法:stream())

List<String> list = new ArrayList<>();
        //List方式
        List<String> list = new ArrayList<>();
        Stream<String> stream3 = list.stream();
        Set<String> set = new HashSet<>();
        Stream<String> stream4 = set.stream();
        //Map方式
        Map<String,String> map = new HashMap<>();
        Stream<String> stream = map.keySet().stream();
        Stream<String> stream1 = map.values().stream();
        Stream<Map.Entry<String, String>> stream2 = map.entrySet().stream();

方式二:Stream中的静态of方法获取流

Stream<String> stringStream = Stream.of("a", "b", "c");
2.Stream常用方法
方法名方法作用返回值类型
count统计个数long
forEach循环void
filter过滤Stream
limit取前几个Stream
skip取后几个Stream
map映射Stream
concat组合Stream
3.常用方法实例Demo

①生成流

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

②forEach

//遍历10个随机数
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

③filter

//按条件遍历不为空的字符串:[abc, bc, efg, abcd, jkl]
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
strings.stream().filter(s -> StringUtils.isNotEmpty(s)).collect(Collectors.toList());

④map

//输出数字的平方:[1, 4, 9, 16, 25, 36, 49, 64, 81]
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
list.stream().map(i -> i * i).collect(Collectors.toList());

⑤limit

//获取指定数量的流
Random random1 = new Random();
random1.ints().limit(2).forEach(System.out::println);

⑥sorted

//将指定数量流排序
Random random2 = new Random();
random2.ints().limit(10).sorted().forEach(System.out::println);

⑦collectors

//流转换集合和聚合元素,也可以返回列表/字符串
List<String> strings1 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings1.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings1.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

注意:
①Stream只能操作一次
②Stream方法返回的是新流
③Stream不调用终结方法,中间的操作不会执行

三、Optional

1.使用方法

①定义Optional两种方式

Optional<String> str = Optional.of("cx");
Optional<String> empty = Optional.empty();

②配合Lambda应用场景(如:获取bean中姓名,并转换大写操作输出)

public static void main(String[] args) {
        User user = new User("Hello", 12);
        Optional<User> hello = Optional.of(user);
        System.out.println(getUpp(hello));

    }
	/**
	 * 先遍历出姓名字段,将姓名字段转换大写,最后添加判断否则为null操作。
	 */
    public static String getUpp(Optional<User> user) {
        return user.map(User::getUserName).map(String::toUpperCase).orElse("null");
    }

    public static class User {
        private String userName;
        private Integer age;
        public User(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值