欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA 8 新特性

程序员文章站 2024-03-14 17:40:16
...

一、Lambda 表达式

四个内置的接口
函数式接口 只有一个方法的接口

Consumer

属于函数式接口,只有一个accept 方法
接收一个参数无返回值
JAVA 8 新特性

Predicate

接收一个泛型,返回 boolean
JAVA 8 新特性

Function

接收两个,一个是入参,一个是返回值
JAVA 8 新特性

Supplier

传入一个参数,返回一个对象
JAVA 8 新特性

二、stream 流

1. 获取流

1)集合类 xxx.stream()

2)Arrays
Object[] objects={1,2,3,4,5,6};
Stream stream = Arrays.stream(objects);

2. 中间操作

1.1)map 把对应的操作应用到 流里面的每一个对象上

/*
给定一个数字列表,返回平方列表
 */

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);

List<Integer> collectList = integerList.stream()
        .map(x -> x = x * x)
        .collect(Collectors.toList());

System.out.println(collectList);

1.2)map 提取对象里面的信息

示例
数据


Trader raoul = new Trader("Raoul", "Cambridge");
Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");

List<Transaction> transactionList = Arrays.asList(
        new Transaction(brian, 2011, 300),
        new Transaction(raoul, 2012, 1000),
        new Transaction(raoul, 2011, 400),
        new Transaction(mario, 2012, 710),
        new Transaction(mario, 2012, 700),
        new Transaction(alan, 2012, 950)
);

测试示例

@Test
public void test08() {
    //提取所有交易员的名字,去除重复
    transactionList.stream()
            .map(Transaction::getTrader)
            .map(Trader::getName)
            .distinct()
            .forEach(System.out::println);
}

解析

JAVA 8 新特性

第一次 stream 之后,流里面是一个个的Transaction 对象,map 之后,流里面是一个个的Trader对象,再次map之后,是一个个的String ,可能有重复的,所以使用 去重
最终得到所有的交易员的姓名

2)filter 过滤

示例 过滤,只留下 大于 3 的数字

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);

integerList.stream()
        .filter(x->x>3)
        .forEach(System.out::println);

3)skip()

跳过前面的几个

4)distinct() 去重

5)sorted(),默认是自然排序,可以定义排序规则

3. 终止操作

1)分组,根据条件,把流中的数据,拆分成不同的组

数据如下

List<Employee> employeeList = Arrays.asList(
        new Employee(101, "张三", 10, "1111.0", Status.FREE),
        new Employee(102, "李四", 20, "2222.0", Status.FREE),
        new Employee(104, "田七", 30, "4444.0", Status.VOCATION),
        new Employee(103, "王五", 30, "3333.0", Status.FREE),
        new Employee(105, "天珩", 50, "5555.0", Status.FREE),
        new Employee(106, "珩媛", 60, "6666.0", Status.VOCATION),
        new Employee(105, "天珩", 40, "9999.0", Status.BUSY),
        new Employee(105, "天珩", 40, "7777.0", Status.BUSY)

);

测试代码

逻辑:根据年龄把员工分三个组 青年,中年,老年

@Test
public void test08() {

    //分组
    ConcurrentMap<Status, Map<String, List<Employee>>> groups = employeeList.stream()
            .collect(Collectors.groupingByConcurrent(Employee::getStatus, Collectors.groupingBy(employee -> {
                if (employee.getAge() <= 35) {
                    return "青年";
                } else if (employee.getAge() <= 50) {
                    return "中年";
                } else {
                    return "老年";
                }

            })));

    groups.forEach((key,value)->{

        System.out.println("key is "+key+"\nvalue is "+value);
    });
}

输出的结果

2)分区

可以分true false 两个区

@Test
public void test09() {
    //分区
    Map<Boolean, List<Employee>> partitioningByAge = employeeList.stream()
            .collect(Collectors.partitioningBy(employee -> employee.getAge() > 35));
    partitioningByAge.forEach((key,value)-> System.out.println("key is "+key+"\nvalue is "+value));


}

3) count()

返回一个 Long 类型数据,流的对象个数

4)收集

ArrayList collect1 = employeeList.stream() .collect(Collectors.toCollection(ArrayList::new));

5)reduce

4)max

5)min

全部匹配 allMatch

至少一个匹配 anyMatch

没有匹配的元素,返回true,否则false noneMatch


三、ForkJoin

工作窃取模式

原理

会划分多个工作线程,每个线程独立的并行工作,当某线程已经完成,还有别的线程没有完成时,会取得其余线程的末尾工作,继续执行,这样中分的利用 CPU 的每个核的资源

传统的线程会等待最慢的线程执行完成之后,整个工作才结束,ForkJoin会利用工作窃取,分担最慢的工作。

示例 累加器 加到10亿

第一个模块,拆分工作的算法

继承 RecursiveTask 实现compute()方法,有返回值
继承 RecursiveAction实现compute()方法,无返回值

public class ForkJoinCal extends RecursiveTask<Long> {
    /**
     * RecursiveAction
     * protected abstract void compute(); 没有返回值
     *
     */

    private Long start;
    private Long end;
    private static final Long THRESODLD=10000L;

    public ForkJoinCal(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        Long length=end-start;

        if (length<=THRESODLD){
            Long sum=0L;

            for (Long i=start;i<=end;i++){
                sum+=i;
            }
            return sum;
        }else {
            Long middle = (start + end) / 2;
            ForkJoinCal left=new ForkJoinCal(start ,middle);
            //拆分子任务,压入栈
            left.fork();
            ForkJoinCal right = new ForkJoinCal(middle + 1, end);
            //拆分子任务,压入栈
            right.fork();

            return left.join()+right.join();

        }

    }

}

第二个模块,使用

@Test
public void test01(){

    Instant start=Instant.now();
    ForkJoinPool forkJoinPool = new ForkJoinPool();
    ForkJoinTask<Long> forkJoinTask=new ForkJoinCal(0L,1000000000L);
    Long sum = forkJoinPool.invoke(forkJoinTask);

    System.out.println("this is sum : "+sum);
    }

运行时,可以查看 CPU 状态,可以看到 利用率非常高

并行流。实现累加

//并行流
Long reduceSum = LongStream.range(0, 100000001L)
        //并行流
        .parallel()
        .reduce(0, Long::sum);
底层使用的也是 fork join 机制,效率更高

四、Optional

提供了新的接口,确保快速定位到null

  1. empty() 创建一个空对象,对象不是null 只是对象的属性都是null
  2. of()创建一个可以为null 的对象
  3. ofNullable()创建对象,调用的是empty()和 of()
  4. isPresent()判断对象是否为null ,null 返回false orElse(T t)如果对象为null,则创建一个默认的对象 t
  5. orElseGet 可以 自己定义构造一个默认的对象

五、新的时间API

Instant
LocalDateTime
Duration
Period