java:java8新特性(Lambda 表达式、方法引用、构造器引用、数组引用、Stream API)

 

  • 速度更快

    • 对 HashMap 、ConcurrentHashMap低层的数据结构(数组+链表+二叉树)

    • 低层的内存结构(将永久区更新为元空间,元空间使用的是物理内存)

  • 代码更少(增加了新的语法 Lambda 表达式)

  • 强大 Stream API

  • 便于并行

  • 最大化减少空指针异常 Optional

  • 关于时间日期的 API


目录

一、Lambda 表达式

为什么使用 Lambda 表达式

Lambda 表达式的基础语法

函数式接口

Java8内置四大核心函数式接口

其他接口

二、方法引用、构造器引用、数组引用

方法引用

构造器引用

数组引用

三、Stream API

Stream 操作的三个步骤:

创建 Stream

中间操作

终止操作


 

 

一、Lambda 表达式

为什么使用 Lambda 表达式

	//原来将匿名内部类作为参数进行传递
	@Test
	public void test1(){
		TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.compareTo(o2);
			}
		});
	}
	
	//java8中的 Lambda 表达式
	@Test
	public void test2(){
		TreeSet<String> ts = new TreeSet<>((x, y) -> x.compareTo(y));
	}

代码简洁。方便,快速的完成了接口实例和内部类的功能。

 

Lambda 表达式的基础语法

Lambda 提供了一个全新的操作符,该操作符为“ -> ”, 该操作符称为箭头操作或Lambda操作符。

箭头操作符将 Lambda 表达式分为两部分:

左侧:对应函数式接口中抽象方法的参数列表

右侧:对函数式接口中抽象方法的实现,即 Lambda 体

  • 语法格式一:无参,无返回值
Runnable r1 = () -> System.out.println("Hello Lambda!");
  • 语法格式二:有一个参数,无返回值
Cusumer<String> cus = (x) -> System.out.println(x);
  • 语法格式三:若Lambda表达式左侧只有一个参数
Cusumer<String> cus = x -> System.out.println(x);
  • 语法格式四:有两个以上参数,Lambda体中有多个条语句,有返回值
Comparator<Integer> com = (x, y) -> {
  	System.out.println("Lambda体中多条语句");
        return Integer.compare(x, y);
};
  • 语法格式五:若 Lambda 体中只有一条语句,return 和 大括号可以省略不写
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  • 语法格式六:Lambda 左侧参数列表可以省略不写,因为 Java 编译器可以通过上下文推断出数据类型,即“类型推断
Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);

注意:Lambda 表达式需要函数式接口的支持

 

函数式接口

若一个接口中只有一个抽象方法,该接口为函数式接口。可以使用 @FunctionalInterface 修饰,说明该接口必须是函数式接口

@FunctionalInterface
public interface MyFunction<T>{
    T apply(T t);
}

 

Java8内置四大核心函数式接口

函数式接口

参数类型

返回类型

用途

Consumer<T>

消费型接口

T

void

对类型为T的对象应用操作,包含方法:

void accept(T t)

Supplier<T>

供给型接口

T

返回类型为T的对象,包含方法:T get();

Function<T, R>

函数型接口

T

R

对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t);

Predicate<T>

断定型接口

T

boolean

确定类型为T的对象是否满足某约束,并返回 boolean 值。包含方法

boolean test(T t);

 

其他接口

函数式接口

参数类型

返回类型

用途

BiFunction<T, U, R>

T, U

R

对类型为 T, U 参数应用操作,返回 R 类型的结果。包含方法为

R apply(T t, U u);

UnaryOperator<T>

(Function子接口)

T

T

对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为

T apply(T t);

BinaryOperator<T>

(BiFunction 子接口)

T, T

T

对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为

T apply(T t1, T t2);

BiConsumer<T, U>

T, U

void

对类型为T, U 参数应用操作。包含方法为

void accept(T t, U u)

ToIntFunction<T>

ToLongFunction<T>

ToDoubleFunction<T>

T

int

long

double

分别计算int、long、double、值的函数

IntFunction<R>

LongFunction<R>

DoubleFunction<R>

int

long

double

R

参数分别为int、long、double 类型的函数

 

二、方法引用、构造器引用、数组引用

方法引用

若 Lambda 体中需要完成的功能,已经有现成的方法,提供了实现,可以选择使用方法引用替代Lambda表达式。(方法引用是 Lambda 表达式的另外一种表现形式

格式:

对象::实例方法名

Consumer<String> con = (x) -> System.out.println(x);
Consumer<String> con2 = System.out::println;

注意:接口中抽象方法的参数列表必须与Lambda体中调用方法的参数列表保持一致!

类::静态方法名

Compartor<Integer> com = Integer::compare;

类::实例方法名

BiPredicate<String, String> bp = (x, y) -> x.equals(y);
BiPredicate<String, String> bp2 = String::equals;

注意:若Lambda参数列表中第一个参数,是 Lambda体中方法的调用者,第二个参数是Lambda体中方法的参数

 

构造器引用

格式:   ClassName::new

函数式接口相结合,自动与函数式接口中方法兼容

可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

 

数组引用

格式: type[ ] :: new

 

三、Stream API

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API(java.util.stream.*)

Stream Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式

Stream 操作的三个步骤:

  • 创建 Stream

	//1. 创建 Stream 的四种方式
	@Test
	public void test1(){
		//1. 通过 Collection 系列集合提供两个 stream() 和 parallelStream()
		List<String> list = new ArrayList<>();
		Stream<String> stream1 = list.stream();
		
		//2. 通过 Arrays 中的 stream() 获取一个数组流
		Integer[] nums = new Integer[10];
		Stream<Integer> stream2 = Arrays.stream(nums);
		
		//3. 通过 Stream 类中静态方法 of
		Stream stream3 = Stream.of("aaa", "bb", "cc");
		
		//4. 创建无限流
		//迭代
		/*Stream stream4 = Stream.iterate(0, (x) -> x + 2);
		stream4.forEach(System.out::println);*/

		//生成
		Stream stream5 = Stream.generate(Math::random).limit(2);
		stream5.forEach(System.out::println);
	}
  • 中间操作

中间操作流不会进行任何操作,只有做了终止操作后,流一次性的执行全部,“惰性求值”

筛选与切片 filter——接收 Lambda , 从流中排除某些元素。 limit——截断流,使其元素不超过给定数量。 skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素

映射 map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。 flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

  • 终止操作

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章