Java 8特性学习 --- Lambda表达式

文章内容

1.匿名类
2.函数式接口
3.lambda表达式
4.lambda表达式、函数接口和Stream接口在数据处理上的运用

1.匿名类

匿名类,即没有名字的类,只能使用一次,匿名类的实现主要通过两种方式:继承和接口,需要注意的是匿名类由于没有类类型,对外可见的属性和方法必须是在父类或接口中定义;
①继承方式实现
继承父类病重写父类方法,本应该是新的类,如果只是临时使用不需要创建新的类类型,直接在实例化时重写父类方法;

public class Parent {
    public void print(){
        System.out.println("parent");
    }
}

Parent p1 = new Parent(){
    @Override
    public void print(){
        System.out.println("extends:AnysMain");
    }
};

②接口方式实现
接口的实现根据具体的调用上下实现决定,没有固定的实现;在使用时,定义接口类型并实现接口方法;也就成了匿名的实现类;

public interface IParent {
    public void print();
}

IParent p2 = new IParent(){
    @Override
    public void print() {
        System.out.println("interface:AnysMain");
    }   
};
p2.print();

2.函数式接口

只有一个特有抽象方法的接口(不包括继承来的接口),@FunctionalInterface,简称FI;

@FunctionalInterface
public interface IFuncInterface {
    public void print();
}

在Java8中与lambda表达式相关的函数式接口:

①Predicate接口(逻辑判断)
虽然Predicate接口有5个方法,但是除了test方法,其他方法都属于默认方法(default修饰的抽象方法,有默认实现),则在创建接口相关的实例时只需要实现test方法;

//Returns a predicate which evaluates to true only if this predicate
//and the provided predicate both evaluate to true.
and(Predicate<? super T> p) 

//Returns a predicate which negates the result of this predicate.
negate() 

//Returns a predicate which evaluates to true if either
//this predicate or the provided predicate evaluates to true
or(Predicate<? super T> p) 

//Returns true if the input object matches some criteria
test(T t) 

//Returns a predicate that evaluates to true if both or neither
//of the component predicates evaluate to true
xor(Predicate<? super T> p)

②Consumer接口(附加操作)
Consumer接口有两个方法,同样的只有一个抽象方法accept,用于接收参数并对参数进行操作;

 /**
  * Performs this operation on the given argument.
  */
 void accept(T t);

/**
 * 完成链式操作
 */
default Consumer<T> andThen(Consumer<? super T> after) {
   Objects.requireNonNull(after);
   return (T t) -> { accept(t); after.accept(t); };
 }

③Function接口(对象操作)
对对象T进行处理并返回独享R,唯一的抽象方法为apply,除此之外还有附属的操作,比如andThen、compose、identity;

default Function andThen(Function after)Returns a composed function that first applies this function to its input, and then applies the after function to the result.
R apply(T t)Applies this function to the given argument.
default Function compose(Function before)Returns a composed function that first applies the before function to its input, and then applies this function to the result.
static Function identity()Returns a function that always returns its input argument.

④Supplier 接口(提供对象)
用于返回一个泛型T对象;

T get()Gets a result.

⑤Comparator 接口(比较规则)
Comparator接口是一个经典的接口,一般自定义的比较规则都是通过Comparator接口来实现的;除了一个compare(T o1, T o2)方法,Java8中实现了大量的默认方法;

int compare(T o1, T o2)Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
default Comparator reversed()Returns a comparator that imposes the reverse ordering of this comparator.
default Comparator thenComparing(Comparator other)Returns a lexicographic-order(字典序) comparator with another comparator.
default Comparator thenComparing(Function keyExtractor,Comparator keyComparator)Returns a lexicographic-order comparator with a function that extracts a key to be compared with the given Comparator.
default Comparator thenComparing(Function keyExtractor, Comparator keyComparator)Returns a lexicographic-order comparator with a function that extracts a key to be compared with the given Comparator.
default Comparator thenComparingDouble(ToDoubleFunction keyExtractor)Returns a lexicographic-order comparator with a function that extracts a double sort key.
default Comparator thenComparingInt(ToIntFunction keyExtractor)Returns a lexicographic-order comparator with a function that extracts a int sort key.
default Comparator thenComparingLong(ToLongFunction keyExtractor)Returns a lexicographic-order comparator with a function that extracts a long sort key.

除了以上常用函数接口,还有一些其他有用的Java8提供的新特性;

⑥Optional 接口
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
在大量数据处理的过程中,会不可避免的出现null的问题,使用Optional接口可以很好的简化对null的判断;

一般通过Optional提供的静态方法of/ofNullable封装实例对象;

//java.util.Optional<T> 类的声明
public final class Optional<T> extends Object
方法描述
static Optional empty()返回空的 Optional 实例。
boolean equals(Object obj)判断其他对象是否等于 Optional。
Optional filter(Predicate predicate)如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
Optional flatMap(Function> mapper)如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
T get()如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
int hashCode()返回存在值的哈希码,如果值不存在 返回 0。
void ifPresent(Consumer consumer)如果值存在则使用该值调用 consumer , 否则不做任何事情。
boolean isPresent()如果值存在则方法会返回true,否则返回 false。
Optional map(Function mapper)如果存在该值,提供的映射方法,如果返回非null,返回一个Optional描述结果。
static Optional of(T value)返回一个指定非null值的Optional。
static Optional ofNullable(T value)如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
T orElse(T other)如果存在该值,返回值, 否则返回 other。
T orElseGet(Supplier other)如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
T orElseThrow(Supplier exceptionSupplier)如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常

⑦Stream 接口

java.util.Stream 表示能应用在一组元素上一次执行的操作序列,用于对集合类型完成一系列操作,包括过滤、遍历;重点是可以由集合生成stream和parallelStream两种类型的流,parallelStream支持并行计算分而治之,将多个中间操作划分到不同的线程来完成

Filter过滤:过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作;

Sort排序:排序是一个中间操作,返回的是排序好后的Stream。如果你不指定一个自定义的Comparator则会使用默认排序(需要集合类型实现Comparable接口);

Map映射:中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象;

Match匹配:Stream提供了多种匹配操作(allMatch/anyMatch),所有的匹配操作都是最终操作,并返回一个boolean类型的值。

Count计数:计数是一个最终操作,返回Stream中元素的个数,返回值类型是long。

Reduce规约:这是一个最终操作,允许通过指定的函数来讲stream中的多个元素规约为一个元素,规越后的结果是通过Optional接口表示的;

//stream相关操作
List<Example> list = new ArrayList<Example>();
list.add(new Example(3, "alice"));
list.add(new Example(4, "eric"));
list.add(new Example(5, "luice"));
list.add(new Example(1, "tom"));
list.add(new Example(2, "bob"));

//count
System.out.println(list.stream().count());

//match
System.out.println(list.stream().allMatch((e)->e.index > 0));

//reduce
System.out.println(list.stream().reduce((before,next)->{
before.name = before.name+"/"+next.name;
return before;
}).get().name);
System.out.println(list.stream().reduce(new Example(-1,""),(before,next)->{
before.name = before.name+"/"+next.name;
return before;
}).name);

//sorted
list
.stream()
.sorted((e1,e2)->{return e1.index - e2.index;})
.forEach((e) -> {System.out.println(e.name);});

3.lambda表达式

lambda表达式是匿名方法,它提供了轻量级的语法,从而解决了匿名内部类带来的“高度问题”,是Java8提供的一种很轻量的语法规则;

(int x, int y) -> x + y
() -> 42
(String s) -> { System.out.println(s); }

第一个lambda表达式接收x和y这两个整形参数并返回它们的和;第二个lambda表达式不接收参数,返回整数’42’;第三个lambda表达式接收一个字符串并把它打印到控制台,不返回值。

lambda表达式的语法由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块:

表达式:表达式会被执行然后返回执行结果。
语句块:语句块中的语句会被依次执行,就像方法中的语句一样——
return语句会把控制权交给匿名方法的调用者
break和continue只能在循环中使用
如果函数体有返回值,那么函数体内部的每一条路径都必须返回值
表达式函数体适合小型lambda表达式,它消除了return关键字,使得语法更加简洁。

4.lambda表达式、函数接口和Stream接口在数据处理上的运用

借助lambda表达式在语法上简洁、以及函数接口的设计,可以完成复杂的数据处理逻辑;特别的,对于集合类数据(目前大部分数据来源为集合),Java8提供了Stream接口,并且定义了Sorted、Match、Filter等中间操作实现对数据的过滤;以及Count、Map、Reduce等最终操作完成对数据的聚合处理;


参考文章

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值