Java-jdk1.8新特性

2021/7/6 20:43:59

本文主要是介绍Java-jdk1.8新特性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • Java-jdk1.8新特性
    • 1 Lambda表达式
      • 1.1 概念
      • 1.2 语法
      • 1.3 集合遍历
      • 1.4 集合排序
    • 2 函数式接口
      • 2.1 概述
      • 2.2 特点
      • 2.3 代码实现
      • 2.4 JDK自带的四大常用接口
        • 2.4.1 SUPPLIER\接口
        • 2.4.2 CONSUMER\接口
        • 2.4.3 FUNCTION

Java-jdk1.8新特性

1 Lambda表达式

1.1 概念

​ Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。
​ 本质上是一段匿名内部类,也可以是一段可以传递的代码。

​ 闭包的本质就是将函数内部和函数外部链接起来的桥梁

1.2 语法

1、(parameters) -> expression

2、(parameters) ->{ statements; }

// 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)

1.3 集合遍历

	public static void main(String[] args) {
		String[] arr = { "one", "two", "three" };
		List<String> list = Arrays.asList(arr);

		// jdk1.7-老版写法
		for (String ele : list) {
			System.out.println(ele);
		}
		System.out.println("---");
		// jdk1.8-新版写法
		list.forEach(x -> {
			System.out.println(x);
		});

		// 就类似于这种写法,相当于自己创建了一个方法,然后遍历调用这个方法
		// 把 集合中每个元素作为参数传递进去,并打印参数
		for (String string : list) {
			m1(string);
		}
	}

	public static void m1(String x) {
		System.out.println(x);
}

1.4 集合排序

	public static void main(String[] args) {
		Integer[] arr = { 9, 8, 10, 1, 3, 5 };
		// 把数组转换为list
		List<Integer> list = Arrays.asList(arr);
		// jdk1.7-旧版写法,使用比较器进行排序
		list.sort(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2;
			}
		});
		System.out.println(list);
		
		// jdk1.8-新版写法
		// 把数组转换为list
		list = Arrays.asList(arr);
		list.sort((x, y) -> x - y);
		System.out.println(list);
}

2 函数式接口

2.1 概述

​ 其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
​ 核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。

2.2 特点

​ 函数式接口是仅制定一个抽象方法的接口
​ 可以包含一个或多个静态或默认方法
​ 专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
​ 如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
​ 如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用

​ 简单来说就是回调函数,方法的参数是一个方法,在这个方法中对传递的方法进行调用

2.3 代码实现

//无参情况
public class FunInterface_01 {
	// 自定义静态方法,接收接口对象
	public static void call(MyFunctionInter func) {
		// 调用接口内的成员方法
		func.printMessage();
	}

	public static void main(String[] args) {
		// 第一种调用 : 直接调用自定义call方法,传入函数
		FunInterface_01.call(() -> {
			System.out.println("HelloWorld!!!");
		});

		// 第二种调用 : 先创建函数对象,类似于实现接口的内部类对象
		MyFunctionInter inter = () -> {
			System.out.println("HelloWorld2!!!!");
		};
		// 调用这个实现的方法
		inter.printMessage();
	}
}
// 函数式接口
@FunctionalInterface
interface MyFunctionInter {
	void printMessage();
}

//有参情况
public class FunInterface_02 {
	// 自定义静态方法,接收接口对象
	public static void call(MyFunctionInter_02 func, String message) {
		// 调用接口内的成员方法
		func.printMessage(message);
	}

	public static void main(String[] args) {
		// 调用需要传递的数据
		String message = "有参函数式接口调用!!!";

		// 第一种调用 : 直接调用自定义call方法,传入函数,并传入数据
		FunInterface_02.call((str) -> {
			System.out.println(str);
		}, message);

		// 第二种调用 : 先创建函数对象,类似于实现接口的内部类对象
		MyFunctionInter_02 inter = (str) -> {
			System.out.println(str);
		};
		// 调用这个实现的方法
		inter.printMessage(message);
	}
}

// 函数式接口
@FunctionalInterface
interface MyFunctionInter_02 {
	void printMessage(String message);
}

2.4 JDK自带的四大常用接口

2.4.1 SUPPLIER<T>接口

​ 无输入只返回值

public class _03_JdkOwn_01 {
	private static String getResult(Supplier<String> function) {
		return function.get();
	}

	public static void main(String[] args) {
		// 1
		String before = "张三";
		String after = "你好";
		// 把两个字符串拼接起来
		System.out.println(getResult(() -> before + after));

		// 2 //创建Supplier容器,声明为_03_JdkOwn类型
		// 此时并不会调用对象的构造方法,即不会创建对象
		Supplier<_03_JdkOwn_01> sup = _03_JdkOwn_01::new;
		_03_JdkOwn_01 jo1 = sup.get();
		_03_JdkOwn_01 jo2 = sup.get();

	}

	public _03_JdkOwn_01() {
		System.out.println("构造方法执行了");
	}
}

2.4.2 CONSUMER<T>接口

​ 只有输入无返回

public class _04_JdkOwn_02 {
	private static void consumeResult(Consumer<String> function, String message) {
		function.accept(message);
	}

	public static void main(String[] args) {
		// 传递的参数
		String message = "消费一些内容!!!";
		// 调用方法
		consumeResult(result -> {
			System.out.println(result);
		}, message);
	}
}

2.4.3 FUNCTION<T,R>接口

​ 既有输入也有输出

public class _05_JdkOwn_03 {
	// Function<参数, 返回值>
	public static void convertType(Function<String, Integer> function,
			String str) {
		int num = function.apply(str);
		System.out.println(num);
	}

	public static void main(String[] args) {
		// 传递的参数
		String str = "123";
		// s是说明需要传递参数, 也可以写 (s)
		convertType(s -> {
			int sInt = Integer.parseInt(s);
			return sInt;
		}, str);
	}
}

2.4.4 PREDICATE<T>接口

​ 断言,有输入,但输出只能是布尔类型。

public class _06_JdkOwn_04 {
	// 自定义方法,并且 Predicate 接收String字符串类型
	public static void call(Predicate<String> predicate, String isOKMessage) {
		boolean isOK = predicate.test(isOKMessage);
		System.out.println("isOK吗:" + isOK);
	}

	public static void main(String[] args) {
		// 传入的参数
		String input = "ok";
		call((String message) -> {
			// 不区分大小写比较,是ok就返回true,否则返回false
			if (message.equalsIgnoreCase("ok")) {
				return true;
			}
			return false;
		}, input);
	}
}

3 方法引用

3.1 对象的引用::实例方法名

public static void main(String[] args) {
		Integer intObj = new Integer(123456);
		// 常规lambda写法
		Supplier<String> su = () -> intObj.toString();
		System.out.println(su.get());

		// 方法引用写法
		Supplier<String> su1 = intObj::toString;
		System.out.println(su1.get());
	}

3.2 类名 :: 静态方法名

public static void main(String[] args) {
		// 常规lambda写法
// 前两个泛型是参数类型,第三个是返回值类型
		BiFunction<Integer, Integer, Integer> bi = (x, y) -> Integer.max(x, y);
		int apply = bi.apply(10, 11);
		System.out.println(apply);
		
		// 方法引用写法
		BiFunction<Integer, Integer, Integer> bif = Integer::max;
		int apply2 = bif.apply(10, 11);
		System.out.println(apply2);
}

3.3 类名 :: 实例方法名

public static void main(String[] args) {
		// 常规lambda写法
// 两个泛型都是参数类型
		BiPredicate<String, String> predicate = (x, y) -> x.equals(y);
		System.out.println(predicate.test("a", "a"));
		// 方法引用写法
// 使用第一个参数调用成员方法把第二个参数传入
// ::前面的类型 要和 第一个参数的类型一致
		BiPredicate<String, String> predicate2 = String::equals;
		System.out.println(predicate2.test("a", "b"));
}

4 构造器调用

public static void main(String[] args) {
		// 无参构造器
		// 常规lambda写法
		Supplier<Object> objSup = () -> new Object();
		System.out.println(objSup.get());
		
		// 方法引用写法
		Supplier<Object> s1 = Object::new;
		System.out.println(s1.get());

		// 有参构造器
		// 常规lambda写法
		Function<String, Integer> func = (x) -> new Integer(x);
		System.out.println(func.apply("123456"));
		
		// 方法引用写法
		Function<String, Integer> func2 = Integer::new;
		System.out.println(func2.apply("123456"));
}

5 数组调用

public static void main(String[] args) {
		// lambda传统写法
		Function<Integer, Integer[]> fun = (n) -> new Integer[n];
		Integer[] intArray1 = fun.apply(5);
		intArray1[0] = 100;
		System.out.println(intArray1[0]);
		
		// 数组引用新写法
		Function<Integer, Integer[]> fun1 = Integer[]::new;
		Integer[] intArray = fun1.apply(5);
		intArray[0] = 100;
		System.out.println(intArray[0]);
}

6 Stream API

6.1 概念

​ 数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。
​ 集合讲的是数据,流讲的是计算
​ 即一组用来处理数组,集合的API。

6.2 特点

​ Stream 不是数据结构,没有内部存储,自己不会存储元素。
​ Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
​ Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
​ 不支持索引访问。
​ 延迟计算
​ 支持并行
​ 很容易生成数据或集合
​ 支持过滤,查找,转换,汇总,聚合等操作。

6.3 运行机制

​ Stream分为源source,中间操作,终止操作。
​ 流的源可以是一个数组,集合,生成器方法,I/O通道等等。
​ 一个流可以有零个或多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用,一个流只会有一个终止操作。
​ 中间操作也称为转换算子-transformation

​ Stream只有遇到终止操作,它的数据源会开始执行遍历操作。
​ 终止操作也称为动作算子-action
​ 因为动作算子的返回值不再是 stream,所以这个计算就终止了
​ 只有碰到动作算子的时候,才会真正的计算

6.4 代码实现

6.4.1 生成Stream的五种方式

 	public static void main(String[] args) {
		// 1 通过数组,Stream.of()
		String[] str = { "a", "b", "c" };
		Stream<String> str1 = Stream.of(str);
		// System.out.println(str1);

		// 2 通过集合
		List<String> strings = Arrays.asList("a", "b", "c");
		Stream<String> stream = strings.stream();
		System.out.println(stream);

		// 3 通过Stream.generate方法来创建
		// 这是一个无限流,通过这种方法创建在操作的时候最好加上limit进行限制
		Stream<Integer> generate = Stream.generate(() -> 1);
		generate.limit(10).forEach(x -> System.out.println(x));

		// 4 通过Stream iterate
		Stream<Integer> iterate = Stream.iterate(1, x -> x + 2);
		iterate.limit(100).forEach(x -> System.out.println(x));

		// 5 通过集合等数据源生成
		String string = "ABCD";
		IntStream intStream5 = string.chars();
		intStream5.forEach(x -> System.out.println(x));
}

6.4.2 常用转换算子

	常用转换算子 filter,distinct,map,limit,skip,flatMap等

filter : 对元素进行过滤筛选,不符合的就不要了

distinct : 去掉重复的元素

skip : 跳过多少元素

limit : 取一个集合的前几条数据

map :
可以理解是在遍历集合的过程中,对元素进行操作,比如判断集合元素是否是a 返回boolean
因为 map的返回值,就是新集合中的元素,所以也可以在遍历的时候对集合的数据进行更改,比如都加 –

flatMap :

​ 解决一个字符串数组 返回单一的字符串使用flatMap
​ 本来集合中有两个数组,可以通过flatMap 把数组中的每一个元素都放到集合中,然后把数组去掉

	**注意只用此算子是不会真正进行计算的,只有后边调用动作算子才会真正计算。**

6.4.3 常用动作算子

循环 forEach

计算 min、max、count、average

匹配 anyMatch、allMatch、noneMatch、findFirst、findAny

汇聚 reduce

收集器 collect



这篇关于Java-jdk1.8新特性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程