JAVA8 新特性详解(一)

 一、前言

Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。

Java8 新增了非常多的特性,我们主要讨论以下几个:

  • Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
  • 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  • 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
  • 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
  • Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
  • Date Time API − 加强对日期与时间的处理。
  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
  • Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

二、Lambda表达式

1、语法:

语法格式一:无参数,无返回值 () -> System.out.println(“Hello Lambda!”);
语法格式二:有一个参数,并且无返回值 (x) -> System.out.println(x);
语法格式三:若只有一个参数,小括号可以省略不写 x -> System.out.println(x);
语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句 Comparator com = (x, y) -> {System.out.println(“函数式接口”); return Integer.compare(x, y); };
语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写 Comparator com = (x, y) -> Integer.compare(x, y);

2、为什么使用lambda表达式

- 避免匿名内部类定义过多
- 可以让你的代码看起来很简洁
- 去掉了一堆没有意义的代码,只留下核心的逻辑

3、lambda.java示例:

public class lambdaTest {
    //2.静态内部类
    static  class Like2 implements ILike {
        @Override
        public void like(int a) {
            System.out.println("I like lambda " + a);
        }
    }
    public static void main(String[] args) {
        ILike like2 = new Like2();
        like2.like(2);

        //3.局部内部类
        class Like3 implements ILike {
            @Override
            public void like(int a) {
                System.out.println("I like lambda " + a);
            }
        }
        ILike like3 = new Like3();
        like3.like(3);

        //4.匿名内部类
        ILike like4 = new ILike() {
            @Override
            public void like(int a) {
                System.out.println("I like lambda " + a);
            }
        };
        like4.like(4);
        //5 lambda
        ILike like5 = (a) -> {

                System.out.println("I like lambda " + a);
            };
        like5.like(5);

        //简化
        ILike like6 = a -> System.out.println("I like lambda " + a);
        like5.like(6);
    }
    //总结:1、lambda表达式的前提必须是函数式接口
    //函数式接口:注解@FunctionalInterface
    //入参或逻辑结构只有一个的话,(),入参的类型和{}都可以省略
}

//定义接口

interface ILike {
    void like(int a);
    //void like(String b);
    default void like2() {
        System.out.println("sssssss");
    }
    @Override
    String toString();
}

//实现类
class Like1 implements ILike {

    @Override
    public void like(int a) {
        System.out.println("I like lambda " + a);
    }
}

三、stream

1、流式操作

不是一个数据结构,不负责任何的数据存储。更像是一个迭代器,有序地获取到数据源中的每一个数据,并且可以对这些数据进行一些操作。流式操作的每一个方法,返回值都是返回的流本身。

2、使用stream的三个步骤

第一步:获取数据源:集合、数组

(1)创建 Person对象

@Data
public class Person {

    private String name;
    private int age;
    private int score;
    public Person(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    public Person(){

    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }

}

(2)创建Data.java

public class Data {

    public static List<Person> getData() {

        List<Person> list = new ArrayList<>();
        list.add(new Person("小李",15,80));
        list.add(new Person("小王",16,90));
        list.add(new Person("小明",13,100));
        list.add(new Person("小赵",12,70));
        list.add(new Person("小许",11,60));
        list.add(new Person("小张",14,59));
        list.add(new Person("小刘",10,95));
        return list;
    }
}

(3)获取数据源

//1.获取数据源:
Stream<Person> s = Data.getData().stream();

第二步:对数据进行处理的过程:过滤、排序、映射……(中间操作)

//中间操作1:filter
//filter:是一个过滤器,定义一个条件,把符合条件的数据留下来
//需求:保留集合中成绩大于80的人的信息
s.filter(ele -> ele.getScore() >80).forEach(System.out::println);

//中间操作2:distinct
//distinct:去重,去除集合中重复的数据
//去重规则:
// (1)先判断hashCode()
// (2)hashCode相同时才去判断equal()
s.distinct().forEach(System.out::println);


//中间操作3:sorted
//sorted:排序,对流中的元素进行排序
//sorted():要求流中的元素对应的类需要实现Comparable 接口
//public class Person implements  Comparable<Person>
s.sorted().forEach(System.out::println);
//Data.getData().stream().sorted(Comparator<T> c):使用自定义的规则来进行排序
//需求:将集合中的人按照年龄升序的规则排序
s.sorted((ele1,ele2) -> ele1.getAge() - ele2.getAge()).forEach(System.out::println);

//中间操作4:limit
//limit:限制,只取流中指定位的元素
s.limit(3).forEach(System.out::println);

//中间操作5:skip
//skip:跳过
s.skip(3).forEach(System.out::println);
//需求:已知集合中有七个元素,取出第2~5个元素
s.skip(1).limit(4).forEach(System.out::println);

//中间操作6:map
//map:映射
//需求:将流中的Person对象替换成他们的名字
//s.map(ele -> ele.getName()).forEach(System.out::println);
s.map(ele -> ele.getScore() >80 ? ele : ele.getName()).forEach(System.out::println);

第三步:对流中数据的整合:转成集合、数组……(最终操作)

//最终操作1:collect
// 转成List
List<Person> list = s.collect(Collectors.toList());
//转成Set
Set<Person> collect = s.collect(Collectors.toSet());
//转成Map
Map<Integer, Integer> map = s.collect(Collectors.toMap(ele1 -> ele1.getScore(), ele2 -> ele2.getAge()));
System.out.println(map);
//Map<String, Integer> map = s.collect(Collectors.toMap(Person::getName, Person::getScore)); 

//最终操作2:reduce
//将Stream中的值计算得到一个最终结果
//需求:求若干个数字的和
Stream<Integer> stream = Stream.of(1,2,3,4,5);
Optional<Integer> reduce = stream.reduce((n1, n2) -> n1 + n2);
System.out.println(reduce.get());
//需求:求集合中存储的若干Person的成绩和
Person tmp = new Person();
Optional<Person> reduce = Data.getData().stream().reduce((ele1, ele2) -> tmp.setScore(ele1.getScore() + ele2.getScore()));
System.out.println(reduce.get().getScore());

//最终操作3:max,min
//需求:找到集合中成绩最高的人的信息
Person max = s.max((ele1, ele2) -> ele1.getScore() - ele2.getScore()).get();
System.out.println(max);
//需求:找到集合中年龄最小的人的信息
Person min = s.min((ele1, ele2) -> ele1.getAge() - ele2.getAge()).get();
System.out.println(min);

//最终操作4:anyMatch、allMatch、noneMatch
//需求1:判断集合中是否有成绩大于80的人
boolean any = s.anyMatch(ele -> ele.getScore() > 80);
System.out.println(any);
//需求2:判断集合中的人是否全部及格
boolean all = s.allMatch(ele -> ele.getScore() >= 60);
System.out.println(all);
boolean none = s.noneMatch(ele -> ele.getScore() < 60);
System.out.println(none);


//最终操作5:count
long count = s.count();
System.out.println(count);

//最终操作6:foreach
//s.forEach(ele -> System.out.println(ele));
s.forEach(System.out::println);

Collector 工具类:提供若干个方法,返回一个Collector接口的实现类对象

//toList,toSet,toMap
//maxBy:通过指定的规则,获取流中最大的元素
//minBy:通过指定的规则,获取流中最小的元素
System.out.println(Data.getData().stream().collect(Collectors.maxBy((ele1,ele2) -> ele1.getScore() - ele2.getScore())));
System.out.println(Data.getData().stream().collect(Collectors.minBy((ele1,ele2) -> ele1.getScore() - ele2.getScore())));


//joining:合并,将流中的元素以字符串的形式拼接起来
//需求:将集合中所有的Person对象的姓名拼接成一个字符串
String res1 = Data.getData().stream().map(Person::getName).collect(Collectors.joining());
System.out.println(res1);
String res2 = Data.getData().stream().map(Person::getName).collect(Collectors.joining("-"));
System.out.println(res2);
String res3 = Data.getData().stream().map(Person::getName).collect(Collectors.joining("-","@","@"));
System.out.println(res3);


//summingInt:将流中的元素映射成一个int类型的元素,最后进行求和
//需求:将集合中所有的人的成绩求和
System.out.println(Data.getData().stream().collect(Collectors.summingInt(Person::getScore)));

//averagingInt:将流中的元素映射成一个int类型的元素,最后求平均值
System.out.println(Data.getData().stream().collect(Collectors.averagingInt(Person::getScore)));


//summarizingInt:将流中的元素映射成一个int类型的元素,最后获取这些元素的描述信息
IntSummaryStatistics intSummaryStatistics = Data.getData().stream().collect(Collectors.summarizingInt(Person::getScore));
System.out.println(intSummaryStatistics.getMax());
System.out.println(intSummaryStatistics.getAverage());
System.out.println(intSummaryStatistics.getCount());
System.out.println(intSummaryStatistics.getMin());
System.out.println(intSummaryStatistics.geSum());

并行流:把一个内容分成多个数据块,使用不用的线程分别处理每个数据块的流。

//写法一:
Data.getData().stream().parallel();
//写法二: 
Data.getData().parallelStream();

//例子:计算0~500亿的总和
long start = System.currentTimeMillis();
LongStream.rangeClosed(0L, 50000000000L).reduce(Long::sum);
long end = System.currentTimeMillis();
System.out.println(end - start);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值