Java:Java8新特性

1:Lamda

(1)Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。

2)lambda 表达式的语法格式:

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

3)lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。如果语句块比较复杂,使用 {} 包起来。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

(4)lamda表达式简单示例:

// 1. 不需要参数,返回值为 5  
() -> 5  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

 

2:方法引用

(1)简介:
           方法引用是为了进一步简化lambda表达式,通过类名或者实例名与方法名的组合来直接访问到类或者实例已经存在的方法或者构造方法。

(2)使用:
           方法引用使用::来定义,::的前半部分表示类名或者实例名,后半部分表示方法名,如果是构造方法就使用NEW来表示。

(3)分类:
           方法引用在Java8中使用方式相当灵活,总的来说,一共有以下几种形式:

  • 静态方法引用:ClassName::methodName;
  • 实例上的实例方法引用:instanceName::methodName;
  • 超类上的实例方法引用:supper::methodName;
  • 类的实例方法引用:ClassName:methodName;
  • 构造方法引用:Class:new;
  • 数组构造方法引用:TypeName[]::new

(4)方法引用简单示例:

public class MethodReferenceTest {
    
    public static void main(String[] args) {
        ArrayList<Car> cars = new ArrayList<>();
        for (int i = 0; i < 5; i++) { Car car = Car.create(Car::new); cars.add(car); }
        cars.forEach(Car::showCar);
    }
    
    @FunctionalInterface
    interface Factory<T> { T create(); }

    static class Car {
        public void showCar() { System.out.println(this.toString()); }
        public static Car create(Factory<Car> factory) {  return factory.create(); }
    }
}
// 输出结果:
learn.MethodReferenceTest$Car@769c9116
learn.MethodReferenceTest$Car@6aceb1a5
learn.MethodReferenceTest$Car@2d6d8735
learn.MethodReferenceTest$Car@ba4d54
learn.MethodReferenceTest$Car@12bc6874

 

3:函数式接口

(1)简介:
          函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

(2)说明:
          由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给 java.util.Collection接口添加新方法,如 stream()、parallelStream()、forEach()和removeIf() 等等。

(3)分类:
           java.util.function 目录下可以看到所有默认的函数式接口,大致分为几类(这里只列举部分)

  • Function<T,R> :T 作为输入,返回的 R 作为输出
  • Predicate<T> :T 作为输入 ,返回 boolean 值的输出
  • Consumer<T> :T 作为输入 ,没有输出
  • Supplier<R> :没有输入 , R 作为输出
  • BinaryOperator<T> :两个 T 作为输入 ,T 同样是输出
  • UnaryOperator<T> :是 Function 的变种 ,输入输出者是 T

(4)函数式接口简单示例:

// hello world 示例
Function<String,String> function = (x) -> {return x+"Function";};
System.out.println(function.apply("hello world"));  // hello world Function

UnaryOperator<String> unaryOperator = x -> x + 2;
System.out.println(unaryOperator.apply("9420-"));   // 9420-2

// 判断输入值是否为偶数示例
Predicate<Integer> predicate = (x) ->{return x % 2 == 0 ;};
System.out.println(predicate.test(1));              // false

// 这个没有返回值
Consumer<String> consumer = (x) -> {System.out.println(x);};
consumer.accept("hello world ");                    // hello world

// 这个没有输入 
Supplier<String> supplier = () -> {return "Supplier";};
System.out.println(supplier.get());                 // Supplier

// 找出大数
BinaryOperator<Integer> bina = (x, y) ->{return x > y ? x : y;};
bina.apply(1,2);   

 

4:Stream API(流)

(1)什么式Stream

流(Stream)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

集合讲的是数据,流讲的是计算

注意:

  1. Stream自己不会存储元素
  2. Stream不会改变源对象。相反,他会返回一个持有结果的新Stream
  3. Stream操作是延迟执行的。意味着他会等到需要结果的时候才执行

(2)Stream操作的三个步骤

  • 创建Stream:一个数据源(如:集合、数组),获取一个流
  • 中间操作:一个中间操作链,对数据源的数据进行处理
  • 终止操作(终端操作):一个终止操作,执行中间操作链。并产生结果

(3)流的详细步骤
 

default Stream<E> stream():返回一个顺序流
default Stream<E> parallelStream():返回一个并行流
  • 创建Stream

1.从集合获取流

List<FarmEntity> list = service.getBySql(sql1);
Stream<FarmEntity> stream = list.stream();

2.从数组获取流

String[] arrays = {"你", "我", "她"}; 
Stream<String> stream = Arrays.stream(arrays);

3.从值获取流

// 通过 Stream 类中静态方法 of()获取流 
Stream<String> stream = Stream.of("你", "我", "她"); 
// 通过迭代获取无限流 
Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);

4.从文件获取流

Stream<String> file = Files.lines(Paths.get("D:\\zhangkai\\WorkSpace\\Git\\hexo\\_config.yml")); 
file.forEach(System.out::println);

 

  • Stream的常用中间操作

1.peek()--消费流中的每一个元素

List<Integer> list = Arrays.asList(6, 5, 5, 1, 4); 
list.stream().peek(i -> System.out.println(i)).forEach(i-> System.out.println(i));

2.map() mapToInt() mapToDouble()等等--将流中的每一个元素映射为另一个元素

int[] nums={1,2,3,5,6}; 
int sum = IntStream.of(nums).map(i->i*2).sum();

3.filter()--将流中满足要求的元素过滤出来

List<Integer> list = Arrays.asList(6, 5, 5, 1, 4); 
list.stream().filter(integer -> integer>1).forEach(System.out::println);

4.sort()--将流中的元素按一定的规则排序

List<Integer> list = Arrays.asList(6, 5, 5, 1, 4); 
List<Integer> collect = list.stream().sorted((o1, o2) -> o1 - o2).collect(Collectors.toList());

5.distinct()--去重

List<Integer> list = Arrays.asList(6, 5, 5, 1, 4);
list.stream().dinstinct().forEach(System.out::println)

6.limit()--截断流只保留指定个数的元素

List<Integer> list = Arrays.asList(6, 5, 5, 1, 4);
list.stream().limit(1).forEach(System.out::println);
  • Stream的常用的终止操作

1.count()-获取流中元素的个数

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
long count = list.stream().count();

2.reduce()-将流中所有的元素合并为一个元素,可用于累加求和,求乘积等等

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
Integer reduce = list.stream().reduce((integer, integer2) -> integer + integer2).get();

3.forEach()-遍历流中的所有元素

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
list.stream().forEach(System.out::println);

4.max()-求出流中元素的最大值

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
​​​​​​​Integer max = list.stream().max((s1, s2) -> s1 - s2).get();

5.min()-求出流中元素的最小值

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
​​​​​​​Integer min = list.stream().max((o1, o2) -> o2 - o1).get();

6.anyMaych()/allMatch()/noneMatch()--匹配元素中的值,返回boolean类型

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
boolean b = list.stream().noneMatch((x) -> x.intValue() == 1); 
boolean b = list.stream().allMatch((x) -> x.intValue() == 1); 
boolean b = list.stream().anyMatch((x) -> x.intValue() == 1);

7.collect()--收集流中的元素通过Collectors这个工具类处理

List<Integer> list = Arrays.asList(1, 2, 3, 5, 6); 
//求平均数
Double average= list.stream().collect(Collectors.averagingInt(x -> x.intValue())); 
//求分组 
Double average= list.stream().collect(Collectors.groupinngby(x -> x.intValue()));
//收集成一个List
List<Integer> collect = list.stream().sorted((o1, o2) -> o1 - o2).collect(Collectors.toList());

8.summerizing() summerizing中封装了很多计算的方法,例如 求和,求平均数等等

Double sum_= list.stream().collect(Collectors.summarizingInt(value -> value.intValue())).getAve

 

5:Optional

  • 什么是Optional类?

Optional类是Java8为了解决null值判断问题,借鉴google guava类库的Optional类而引入的一个同名Optional类,使用Optional类可以避免显式的null值判断(null的防御性检查),避免null导致的NPE(NullPointerException)。

  • Optional类详情

(1)Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例

(2)isPresent():判断是否包含值,包含值则为true否则为false

(3)get() :主要用于返回包装对象的实际值,但是如果包装对象值为null,会抛出NoSuchElementException异常

public static String getGender(Student student) { 
    Optional<Student> stuOpt = Optional.ofNullable(student); 
    if(stuOpt.isPresent()) { return stuOpt.get().getGender(); } return "Unkown"; 
}

(4)orElse(T t) :如果调用对象包含值,返回该值,否则返回t

public static String getGender(Student student) { 
    return Optional.ofNullable(student).map(u -> u.getGender()).orElse("Unkown"); 
}

(5)orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则用Supplier对象的get()方法的返回值作为默认返回值。

public static String getGender(Student student) { 
    return Optional.ofNullable(student).map(u -> u.getGender()).orElseGet(() -> "Unkown"); 
}

(6)ifPresent() :接受一个Consumer对象(消费函数),如果包装对象的值非空,运行Consumer对象的accept()方法。

public static void printName(Student student) { 
    Optional.ofNullable(student) .ifPresent(u -> System.out.println("The student name is : " + u.getName()));
}

(7)filter() :接受参数为Predicate对象,用于对Optional对象进行过滤,如果符合Predicate的条件,返回Optional对象本身,否则返回一个空的Optional对象。

public static void filterAge(Student student) { 
    Optional.ofNullable(student).filter( u -> u.getAge() > 18) 
        .ifPresent(u -> System.out.println("The student age is more than 18."));
}

(8)map() :如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()。参数为Function(函数式接口)对象,map()方法将Optional中的包装对象用Function函数进行运算,并包装成新的Optional对象(包装对象的类型可能改变)。

public static Optional<Integer> getAge(Student student) { 
    return Optional.ofNullable(student).map(u -> u.getAge()); 
}

(9)flatMap() :跟map()方法不同的是,入参Function函数的返回值类型为Optional<U>类型,而不是U类型,这样flatMap()能将一个二维的Optional对象映射成一个一维的对象。

public static Optional<Integer> getAge(Student student) { 
    return Optional.ofNullable(student).flatMap(u -> Optional.ofNullable(u.getAge())); 
}

(10)orElseThrow():其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常。

public static String getGender1(Student student) { 
    return Optional.ofNullable(student).map(u -> u.getGender()) 
                .orElseThrow(() -> new RuntimeException("Unkown")); 
}

 

 

 

-----------------------------------------------------------------底线-----------------------------------------------------------------

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值