Java8中的新特性

一、Lambda表达式

本质是一种匿名函数,是没有方法声明的方法,也没有访问修饰符、返回值声明和名字。

先定义一个接口Fu

package cn.cy.study.lambda;

public interface Fu {
    int add(int a, String b);
}

类的内部实现Fu接口,两种方式,第一种是匿名内部类方式,第二种是Lambda表达式方式

package cn.cy.study.lambda;

public class LambalTest {
    public static void main(String[] args) {
        // 方式一:匿名内部类
        Fu fu = new Fu() {
            @Override
            public int add(int a, String b) {
                System.out.println("add方法" + b);
                return a;
            }
        };
        fu.add(10, "add");

        // 方式二:Lambda表达式
        // ()中的参数类型可省略,只有一个参数时,()也可省略
        Fu fuLambda = (a, b) -> {
            System.out.println("add方法" + b);
            return a;
        };
        fuLambda.add(10, "add");
    }
}

接口中,只能有一个抽象方法(并不是只能有一个方法),这时才能使用Lambda表达式。此接口即下面介绍的函数式接口。

二、函数式接口

2.1 函数式接口定义

  1. 在接口中只能定义一个抽象方法,其他的可以用default,static,Object里继承的方法等。
  2. Java8中专门提供了@FunctionalInterface注解来检验是否为函数式接口。

2.2 内置的函数式接口

JDK提供了大量的函数式接口,使得Lambda表达式运用更加方便、高效。特别介绍四个函数式接口。

  1. Consumer<T>:消费型接口,有参数无返回值。void accept(T t)
  2. Supplier<T>:供给型接口,无参数有返回值。T get()
  3. Function<T, R>:函数型接口,有参数有返回值。R apply(T t)
  4. Predicate<T>:断言型接口。输入一个参数,返回一个boolean值。boolean test(T t)

2.3 Lambda表达式-遍历list集合

package cn.cy.study.functionInterface;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

public class FunctionInterface {

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1,2,3,4,5,6);
        // 遍历list
        // 方式一:匿名内部类
        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println("值为:" + integer + 1);
            }
        };
        list.forEach(consumer);

        // 方式二:Lambda表达式
        Consumer<Integer> consumer2 = i -> System.out.println("值为:" + i + 1);
        list.forEach(consumer2);
    }
}

三、方法引用

  • Lambda体可能仅调用一个已存在方法,而不做任何其它事。对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰。
  • 方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,方法引用操作符是双冒号::
  • 特定使用场景,如果参数传来,不做任何处理,则能用方法引用
package cn.cy.study.functionInterface;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

public class FunctionInterface {

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1,2,3,4,5,6);
        // 遍历list
        Consumer<Integer> consumer3 = System.out::println;
        list.forEach(consumer3);
    }
}

四、Stream流

Stream作为Java8的一大亮点,它与java.io包里的InputStream和OutputStream是完全不同的概念。 它是对容器对象功能的增强,它专注于对容器对象进行各种非常便利、高效的聚合操作或者大批量数据操作。

4.1 Stream流操作

Stream有如下三个操作步骤:

  1. 创建Stream:从一个数据源,如集合、数组中获取流。
  2. 中间操作:一个操作的中间链,对数据源的数据进行操作。
  3. 终止操作:一个终止操作,执行中间操作链,并产生结果。

在这里插入图片描述

4.2 重要的中间操作

  1. filter:过滤
    根据指定的条件过滤流中的元素,只保留满足条件的元素。其中传参是一个断言函数式接口,写过滤条件,若返回true则保留,返回false则过滤掉。

  2. distinct:去重
    对集合的元素,进行去重操作。

  3. sorted:排序
    默认是升序排序,要想降序排序,则可以使用.sorted((x, y) -> Integer.compare(x, y))

  4. limit:限制个数
    传递的参数是int类型的数,意思是输出前n个数据。

  5. skip:跳过
    传递的参数是int类型的数,意思是跳过前n个数据。

  6. map:操作
    可以对流中每一个元素,进行计算或转换,例如想将每一个元素值增加5,则可以使用.map(x -> x + 5)

4.3 重要的结束操作(List转Map)

  1. forEach:结束
    对流中的每个元素执行指定的操作,处理完所有元素后才结束流。
  2. count:计算
    计算流中元素的数量,处理完所有元素后返回数量值。
  3. min:最小
    根据指定的比较器,找到流中的最小元素,处理完所有元素后返回最小元素。例,list.stream().max(Integer::compare)
  4. max:最大
    max: 根据指定的比较器,找到流中的最大元素,处理完所有元素后返回最大元素。例,list.stream().max(Integer::compare)
  5. collect:收集
    根据指定的收集器,将流中的元素进行收集操作,传递一个Collector接口的实现,处理完所有元素后返回一个结果对象。
package cn.cy.study.stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        List<String> list3 = new ArrayList<>();
        Collections.addAll(list1, 1, 20, 6, 55, 190, 9, 1, 40, 6);
        Collections.addAll(list2, 1, 1, 1, 1, 190, 9, 9, 9, 6);
        Collections.addAll(list3, "1a", "a2b", "ab6c","dd3dd");
        
        // toList()
        List<Integer> collectList = list1.stream().filter(x -> x > 10).collect(Collectors.toList());
        System.out.println(collectList);
        
        // toSet()
        Set<Integer> collectSet = list2.stream().map(x -> x * 2).collect(Collectors.toSet());
        System.out.println(collectSet);
        
        // toMap(): List转Map案例,第一个参数为key,第二个参数为value
        Person p1 = new Person(1001L, "张三");
        Person p2 = new Person(1002L, "李四");
        Person p3 = new Person(1002L, "王五");
        List<Person> personList = Arrays.asList(p1, p2);
        List<Person> personList2 = Arrays.asList(p1, p2, p3);
        // key不重复情况
        Map<Long, String> collectMap = personList.stream().collect(Collectors.toMap(Person::getId, Person::getName));
        // key重复情况,则取重复的第一个id
        personList2.stream().collect(Collectors.toMap(Person::getId, Person::getName, (o1, o2) -> o1));
        System.out.println(collectMap);
        
        // toCollection(): 转出的类型可以自定义
        TreeSet<Integer> collectTreeSet = list1.stream().sorted().collect(Collectors.toCollection(TreeSet::new));
        System.out.println(collectTreeSet);
        
        // joining(): 对字符串操作
        String collectJoining = list3.stream().collect(Collectors.joining("-"));
        System.out.println(collectJoining);
    }
}
  1. sorted:排序
    对流中的元素进行排序,需要保持状态来进行排序操作。
  2. findFirst:返回流中的第一个
    返回流中的第一个元素,如果流为空则返回一个空的Optional对象。
  3. findAny:返回流中的任意一个
    返回流中的任意一个元素,如果流为空则返回一个空的Optional对象。
  4. anyMatch:是否存在满足指定条件
    判断流中是否存在满足指定条件的元素,一旦找到满足条件的元素,立即返回true,不再继续处理剩余元素。
  5. allMatch:所有元素是否都满足指定条件
    判断流中的所有元素是否都满足指定条件,一旦发现有不满足条件的元素,立即返回false,不再继续处理剩余元素。
package cn.cy.study.stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        // 创建Stream流的方式1
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3);
        Stream<Integer> stream = list.stream();

        // 创建Stream流的方式2
        Stream<Integer> stream1 = Stream.of(1, 2, 3, 4);

        // 创建Stream流的方式3
        int []arr = {1, 2, 3, 4};
        IntStream stream2 = Arrays.stream(arr);

        // 创建Stream流的方式4
        Stream<Double> generate = Stream.generate(() -> Math.random());

        // 创建Stream流的方式5
        Stream<Integer> iterate = Stream.iterate(6, i -> 2 + i);

        // 创建Stream流的方式6
    }
}

4.4 使用Comparator.comparing进行排序

//返回 对象集合以类属性一升序排序
list.stream().sorted(Comparator.comparing(::属性一));
 
//返回 对象集合以类属性一降序排序 注意两种写法
list.stream().sorted(Comparator.comparing(::属性一).reversed());//先以属性一升序,结果进行属性一降序
list.stream().sorted(Comparator.comparing(::属性一,Comparator.reverseOrder()));//以属性一降序
 
//返回 对象集合以类属性一升序 属性二升序
list.stream().sorted(Comparator.comparing(::属性一).thenComparing(::属性二));
 
//返回 对象集合以类属性一降序 属性二升序 注意两种写法
list.stream().sorted(Comparator.comparing(::属性一).reversed().thenComparing(::属性二));//先以属性一升序,升序结果进行属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(::属性一,Comparator.reverseOrder()).thenComparing(::属性二));//先以属性一降序,再进行属性二升序
 
//返回 对象集合以类属性一降序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(::属性一).reversed().thenComparing(::属性二,Comparator.reverseOrder()));//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(::属性一,Comparator.reverseOrder()).thenComparing(::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
 
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(::属性一).reversed().thenComparing(::属性二).reversed());//先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
list.stream().sorted(Comparator.comparing(::属性一).thenComparing(::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序
 
//空/Null数据排序
list.stream().sorted(Comparator.comparing(::属性一).thenComparing(item -> item.属性二, Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());
 
//空/Null数据分组
Map<String, List<>> map = list.stream().collect(Collectors.groupingBy(item -> {
  if (item.属性一 == null || item.属性一.equals("")) {
    return "";
  }
  return DateFormat.getDateInstance().format(item.属性一);
}))

项目中的应用: 数量降序,顺序升序来排序:

list = list.stream().sorted(Comparator.comparing(CountItem::getQuantity, Comparator.reverseOrder()).thenComparing(CountItem::getPriority)).collect(Collectors.toList());  

五、Optional对象

5.1 Optional介绍

Optional存在的意义是简化为了防止空指针而进行的if-else判断的代码,提供了全局的value属性存储值。

5.2 Optional方法介绍

package cn.cy.study.stream;

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        Person person = null;
        getPer(person);
    }

    public static void getPer(Person person) {
        // of()
        Optional<Person> optional1 = Optional.of(person);
        // ofNullable()
        Optional<Person> optional2 = Optional.ofNullable(person);
        // orElse()和orElseGet()
		// 若person为空,则创建一个Person对象
        Person person1 = Optional.ofNullable(person).orElse(new Person());
        Person person2 = Optional.ofNullable(person).orElseGet(Person::new);
        // ifPresent()
        // 若person不为空,则做ifPresent中的操作
        Optional.ofNullable(person).ifPresent(x -> {
            System.out.println("person对象不为null");
            x.setId(111L);
        });
        // map()
        Optional<Boolean> f = Optional.ofNullable(person).map(x -> {
            x.setId(112L);
            return true;
        });
        // 判断是否有返回值
        boolean present = f.isPresent();
        // 得到返回值
        boolean res = f.get();
        
        // filter()
        Optional<Person> person3 = Optional.ofNullable(person).filter(x -> x.getId() > 200);
    }
}
  • of():如果对象为null,直接报空指针异常
  • ofNullable():如果对象为null,返回Optional.empty,不会报错
  • orElse():如果传递的对象为null,则执行orElse()操作;如果传递的对象不为null,则orElse方法仍然会执行
  • orElseGet():如果传递的对象为null, 则执行orElseGet()操作;如果传递的对象不为null,则orElseGet()操作不再执行
  • ifPresent():如果传递的对象不为null,则进入ifPresent方法执行操作,这个方法无返回值
  • map():如果传递的对象不为null,则进入map方法执行,并可以得到一个返回值
  • isPresent():返回值是否为null,为null返回false,不为null返回true
  • get():map方法的返回值获取
  • filter():如果返回值不为null,则执行filter中的操作,并返回
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值