jdk8新特性

JDK8相对之前升级,个人理解主要是代码简洁度的提升,对JVM性能和其他的优化感觉不是很大,至少一般项目区别不大,对于多数开发人员而言,还是代码风格更简洁了,但如果不熟悉,阅读难度也加大了,不管自己用不用,还是学习下比较好,不然同事写的代码,可能你就看不懂啦。

一、 Lambda 表达式

lambda表达式,个人来理解,基本就是匿名内部类简化了,不需要写那么多了,也减少了命名,啊,做开发的都很烦对各种类、方法命名吧,脑壳痛。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用Lambda 表达式可以使代码变的更加简洁紧凑。

1.1 语法

lambda 表达式的语法格式如下:

(parameters) -> expression或(parameters) ->{statements; }

以下是lambda表达式的重要特征:

· 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

· 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

· 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

· 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

1.2 Lambda 表达式实例
以线程的Runnable接口和Thread类为例

@Test
	public void lambdaTest() {
		Runnable run1 = new Runnable() {
			public void run() {
				System.out.println("线程1");
			}
		};
		
		Runnable run2 = () ->{
			System.out.println("线程2");
		};
		
		
		new Thread( () ->  {
			System.out.println("线程3");
		} ).start(); ;
		
		run1.run();
		run2.run();
	}

注意
1、对于接口,只能有一个方法,否则会识别不到了,Runnable接口有@FunctionalInterface注解,这个注解就是限制只能有一个方法的,再加方就报错;但是你自己定义的接口,不写这个注解,只有一个方法,用lambda表达式是完全没问题的,如果你怕别人瞎改,你加上这个注解,更为保险。
2、lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在lambda 内部修改定义在域外的局部变量,否则会编译错误。

完整的匿名内部类推导到lambda表达式,可以参考狂神的多线程里面有一章,链接:https://www.bilibili.com/video/BV1V4411p7EF?p=10

二、方法引用

方法引用通过方法的名字来指向一个方法。

方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用使用一对冒号 :: 。
我觉得没啥用,抄的别人家的示例:

class Car {
    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }
 
    //Supplier是jdk1.8的接口,这里和lamda一起使用了
    public static Car create(final Supplier<Car> supplier) {
        return supplier.get();
    }
 
    public static void collide(final Car car) {
        System.out.println("Collided " + car.toString());
    }
 
    public void follow(final Car another) {
        System.out.println("Following the " + another.toString());
    }
 
    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
 
    public static void main(String[] args) {
        //构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
         Car car  = Car.create(Car::new);
         Car car1 = Car.create(Car::new);
         Car car2 = Car.create(Car::new);
         Car car3 = new Car();
        List<Car> cars = Arrays.asList(car,car1,car2,car3);
        System.out.println("===================构造器引用========================");
        //静态方法引用:它的语法是Class::static_method,实例如下:
        cars.forEach(Car::collide);
        System.out.println("===================静态方法引用========================");
        //特定类的任意对象的方法引用:它的语法是Class::method实例如下:
        cars.forEach(Car::repair);
        System.out.println("==============特定类的任意对象的方法引用================");
        //特定对象的方法引用:它的语法是instance::method实例如下:
        final Car police = Car.create(Car::new);
        cars.forEach(police::follow);
        System.out.println("===================特定对象的方法引用===================");
 
    }
}

三、重头,Stream流处理

流处理,针对的主要是集合和数组进行筛选和处理,可以类比为集合和数组变成了一个数据库表,然后JDK8提供了一些方法,进行类似sql的查询、筛选、反馈的处理。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

1、获取流

总共好像五种还是多少种,我个人认为常用的就是两种
Collection.stream() 集合创建顺序流
Collection.parallelStream() 集合创建并行流
Arrays.stream()数组获取流 数组我个人开发用的很少,太不灵活了,基本都是集合

如果数据量小,直接用顺序流就行了;如果数据量比较大,用并行流比较好,类似多线程,处理快,而且不需要考虑并发编程可能出现的问题,JDK8自己帮我们处理好了。

2、对流进行处理

2.1filter
直接理解为if判断就行了

@Test
	public void filterTest() {
		List<Integer> numberList = Arrays.asList(1,2,3,4,5);
		List<Integer> collect = numberList.stream()
		.filter(number -> number % 2 == 0 && number != 4)//相当于if判断,进行筛选
		.collect(Collectors.toList());
		
		for (Integer number : collect) {
			System.out.println(number);
		}
		
	}

2.2map
map 方法用于映射每个元素到对应的结果,理解为对元素进行处理,然后取到元素

@Test
	public void mapTest() {
		List<Integer> numberList = Arrays.asList(1,2,3,4,5);
		//映射成两倍数值
		List<Integer> collect = numberList.stream()
		.map(number -> number*2)
		.collect(Collectors.toList());
		
		System.out.println(collect);
		
		numberList.stream()
		.map(number -> "数值"+number+",")
		.forEach(number -> System.out.println(number));
		
	}

2.3 sorted排序
默认升序

@Test
	 public void sortedTest(){
		List<Integer> numberList = Arrays.asList(1,2,3,4,5,4,5);
		Stream<Integer> sortedList = numberList.stream()
		.sorted();
		
		sortedList.forEach(number -> System.out.println(number));
	 }

2.4max min sum average等操作

List<Integer> numberList = Arrays.asList(1,2,3,4,5,4,5);
		
		numberList.forEach(number -> System.out.println(number));
		Optional<Integer> max = numberList.stream()
		.max((p1, p2) -> Integer.compare(p1, p2));
		System.out.println(max);

还有其他方法,具体查阅api文档,这里列出常用的
方法 作用
filter() 接收lambda,从流中排除某些操作
limit() 截断流,使其元素不超过给定对象
skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
distinct 筛选,通过流所生成元素的hashCode()和equals去除重复元素
map 接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
sorted() 自然排序(Comparable)
sorted(Comparator com) 定制排序(Comparator)
allMatch 检查是否匹配所有元素
anyMatch 检查是否至少匹配一个元素
noneMatch 检查是否没有匹配所有元素
findFirst 返回第一个元素
findAny 返回当前流中的任意元素
count 返回流中元素的总个数
max 返回流中最大值
min 返回流中最小值
reduce 归约操作可以将流中元素反复结合起来,得到一个值
collect 将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法

3.汇聚流

collect 将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法

:顺序流、并行流、for循环操作效率比较

@Test
	public void parallelStreamTest() {
		//
		init(1000000);
		System.out.println("原始数据个数:"+perList.size());
		
		long t1 = System.currentTimeMillis();
		List<Person> streamList = perList.stream()
		.filter(person -> person.getAge() > 20)
		.collect(Collectors.toList());
		long t2 = System.currentTimeMillis();
		System.out.println("顺序流花费时间:"+(t2-t1)+",长度:"+streamList.size());
		
		
		long t3 = System.currentTimeMillis();
		List<Person> parallelStreamList = perList.parallelStream()
		.filter(person -> person.getAge() > 20)
		.collect(Collectors.toList());
		long t4 = System.currentTimeMillis();
		System.out.println("并行流花费时间:"+(t4-t3)+",长度:"+parallelStreamList.size());
		
		long t5 = System.currentTimeMillis();
		List<Person> forAddList = new ArrayList<>();
		for (Person person : perList) {
			if (person.getAge() > 20) {
				forAddList.add(person);
			}
		}
		long t6 = System.currentTimeMillis();
		System.out.println("for循环添加花费时间:"+(t6-t5)+",长度:"+forAddList.size());
		
		
	}

这里进行很简单的筛选汇聚操作,经过实测,如果小于10W数量级,for循环最快;100W左右,并行流和for循环差不多;1000W及以上,就是并行流最快啦。当然,这里处理非常非常简单,如果处理负责度上去了,这个量级肯定会降低的,所以,如果有一定的数据量,用并行流会加快处理速度。

还有一些其他新特性,但说真的,我感觉意义不大,就记录上面这些吧,其他的可以去百度看看其他大佬写的,我这个菜鸡就写这么多啦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值