欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > java-必会jdk1.8新特性

java-必会jdk1.8新特性

2024/10/27 14:22:32 来源:https://blog.csdn.net/CSDN_LiMingfly/article/details/142562029  浏览:    关键词:java-必会jdk1.8新特性

1:抽象类的变化


前言:
接口里只能做方法定义不能有方法的实现,抽象类的方法不需要继承类必须去实现的一种方式。
定义一个抽象类TestAbstractclass 如下

package com.lm.jdk8.Abstractclass;/*** 抽象类*/
public abstract class Abstractclass {abstract double calculate(int a);// 求平方double sqrt(int a) {return Math.sqrt(a);}
}

使用的时候如下

package com.lm.jdk8.Abstractclass;import org.junit.jupiter.api.Test;public class TestAbstractclass {@Testpublic void test01() {Abstractclass abstractclass = new Abstractclass() {@Overridedouble calculate(int x) {return x * x;}};double calculate = abstractclass.calculate(10);System.out.println(calculate);double sqrt = abstractclass.sqrt(2);System.out.println(sqrt);}
}

运行如下:
在这里插入图片描述

2:接口中定义方法-jdk1.8之前不支持


在jdk1.8,不仅可以定义接口,还可以在接口中提供默认的实现。这一个小小的改变却让整个抽象设计都随着改变了!

package com.lm.jdk8.interfacePackage;/*** 接口里面定义的方法必须是 default关键字的*/
public interface interfaceExample {double calculate(int x);//平方default double sqrt(int x) {return Math.sqrt(x);}}

使用方式一

package com.lm.jdk8.interfacePackage;import org.junit.jupiter.api.Test;public class TestInterfaceExample {@Testpublic void test01() {InterfaceExample interfaceExample = new InterfaceExample() {@Overridepublic double calculate(int x) {return x + x;}};double calculate = interfaceExample.calculate(4);System.out.println(calculate);System.out.println(interfaceExample.sqrt(25));}
}

高级用法才能体现出他的骚气 如下

 @Testpublic void test02() {InterfaceExample interfaceExample = x -> x * x;System.out.println(interfaceExample.calculate(4));}

3:Lambda 表达式


为什么会有Lambda 表达式的出现 如上的抽象类和接口给了Lambda 表达式的启发 所以你会从各个我们以前的List、Set等等所有接口中看到默认的方法实现。

List<String> list = Arrays.asList("A", "B", "C");@Testpublic void test01() {Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return b.compareTo(a);}});System.out.println(list);}

Collections 工具类提供了静态方法 sort 方法,入参是一个 List 集合,和一个 Comparator 比较器,以便对给定的 List 集合进行排序。上面的示例代码创建了一个匿名内部类作为入参,这种类似的操作在我们日常的工作中随处可见
Java 8 中不再推荐这种写法,而是推荐使用 Lambda 表达: 如下

@Testpublic void Test02() {Collections.sort(list, (String a, String b) -> {return b.compareTo(a);});}

以上还可以更加简短的写法 如下

Collections.sort(names, (String a, String b) -> b.compareTo(a));@Testpublic void Test03() {Collections.sort(list, (String a, String b) -> b.compareTo(a));System.out.println(list);}

为了追求极致,我们还可以让它再短点

@Testpublic void Test04() {list.sort((x,y)->x.compareTo(y));System.out.println(list);}

其实底层使用了类型推断机制 这样,你连入参的类型都可以省略啦

4:函数式接口出现


可以看到通过Lambda可以开发出同样功能的逻辑但是代码却很简单,那么Jvm是如何进行类型推断,并且找到对应的方法呢?所谓函数式接口(Functional Interface)就是只包含一个抽象方法的声明。针对该接口类型的所有 Lambda 表达式都会与这个抽象方法匹配。
总结:为了保证一个接口明确的被定义为一个函数式接口(Functional Interface),我们需要为该接口添加注解:

在这里插入图片描述
@FunctionalInterface。

 @Testpublic void test01() {IConver<String, String> iConver = new IConver<String, String>() {@Overridepublic String convert(String param) {return param;}};System.out.println(iConver);}

4:内置的函数式接口


JDK 1.8 API 包含了很多内置的函数式接口。其中就包括我们在老版本中经常见到的 Comparator 和 Runnable,Java 8 为他们都添加了 @FunctionalInterface 注解,以用来支持 Lambda 表达式。
Predicate 断言

 @Testpublic void test01() {Predicate<String> s=a->a.length()>0;System.out.println(s.test("o"));System.out.println(s.negate().test("o"));boolean foo0 = s.test("foo");           // trueboolean foo1 = s.negate().test("foo");  // negate否定相当于!truePredicate<Boolean> nonNull = Objects::nonNull;Predicate<Boolean> isNull = Objects::isNull;System.out.println(nonNull.test(null));Predicate<String> isEmpty = String::isEmpty;Predicate<String> isNotEmpty = isEmpty.negate();}

Functions 函数
Function 函数式接口的作用是,我们可以为其提供一个原料,他给生产一个最终的产品。通过它提供的默认方法,组合,链行处理(compose, andThen):

 @Testpublic void test12() {Function<String, Integer> toInteger = Integer::valueOf;                                         //转IntegerFunction<String, String> backToString = toInteger.andThen(String::valueOf);                     //转StringFunction<String, String> afterToStartsWith = backToString.andThen(new Something()::startsWith); //截取第一位String apply = afterToStartsWith.apply("123");// "123"System.out.println(apply);}

Suppliers
Supplier 与 Function 不同,它不接受入参,直接为我们生产一个指定的结果,有点像生产者模式:

   @Testpublic void test13() {Supplier<Person> personSupplier0 = Person::new;personSupplier0.get();Supplier<String> personSupplier1 = Something::test01;personSupplier1.get();Supplier<String> personSupplier2 = new Something()::test02;System.out.println(personSupplier2);}

Consumers
Consumer,我们需要提供入参,用来被消费

@Testpublic void test14() {// 参照物,方便知道下面的Lamdba表达式写法Consumer<Person> greeter01 = new Consumer<Person>() {@Overridepublic void accept(Person p) {System.out.println("Hello, " + p.firstName);}};Consumer<Person> greeter02 = (p) -> System.out.println("Hello, " + p.firstName);greeter02.accept(new Person("Luke", "Skywalker"));  //Hello, LukeConsumer<Person> greeter03 = new MyConsumer<Person>()::accept;    // 也可以通过定义类和方法的方式去调用,这样才是实际开发的姿势greeter03.accept(new Person("Luke", "Skywalker"));  //Hello, Luke}

5:Optionals


Optional 它不是一个函数式接口,设计它的目的是为了防止空指针异常(NullPointerException),要知道在 Java 编程中,空指针异常可是臭名昭著的。

@Testpublic void test1() {Optional<String> optional = Optional.of("bam");optional.isPresent();                  // trueoptional.get();                        // "bam"optional.orElse("回调");    // "bam"optional.ifPresent((s) -> System.out.println(s.charAt(0)));Optional<Person> optionalPerson = Optional.of(new Person());optionalPerson.ifPresent(s -> System.out.println(s.firstName));}

6:Stream 流


简单来说,我们可以使用 java.util.Stream 对一个包含一个或多个元素的集合做各种操作。这些操作可能是 中间操作 亦或是 终端操作。 终端操作会返回一个结果,而中间操作会返回一个 Stream 流。
初始化数据

   List<String> list = new ArrayList<>();StreamTest() {list.add("ddd2");list.add("aaa2");list.add("bbb1");list.add("aaa1");list.add("bbb3");list.add("ccc");list.add("bbb2");list.add("ddd1");}

Filter 过滤
Filter 的入参是一个 Predicate, 上面已经说到,Predicate 是一个断言的中间操作,它能够帮我们筛选出我们需要的集合元素。

  @Testpublic void test17() {list.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);System.out.println(list);}

Sorted 排序

@Test
public void test18() {stringCollection.stream().sorted().filter((s) -> s.startsWith("a")).forEach(System.out::println);
}

对象属性排序

tCjpoolSecurityReportList = tCjpoolSecurityReportList.stream().sorted(Comparator.comparing(TCjpoolSecurityReport::getPubdate).reversed()).collect(Collectors.toList());

过滤指定属性

 public static String convertO32Market(String secuMarket) {if (StringUtils.isNotEmpty(secuMarket)) {List<O32SecuMarketEnum> filters = Arrays.stream(values()).filter((item) -> {return StringUtils.equals(secuMarket, item.getIssMktCode());}).collect(Collectors.toList());return CollectionUtils.isNotEmpty(filters) ? filters.get(0).getO32MktCode() : secuMarket;} else {return null;}}

7:Parallel-Streams 并行流


流可以是顺序的,也可以是并行的。顺序流上的操作在单个线程上执行,而并行流上的操作在多个线程上并发执行。

下面的示例演示了使用并行流来提高性能是多么的容易。亲测提升了1倍性能!
顺序流处理 比较慢

@Testpublic void test01() {int max = 1000000;List<String> values = new ArrayList<>(max);for (int i = 0; i < max; i++) {UUID uuid = UUID.randomUUID();values.add(uuid.toString());}// 纳秒long t0 = System.nanoTime();long count = values.stream().sorted().count();System.out.println(count);long t1 = System.nanoTime();long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);System.out.println(String.format("顺序流排序耗时: %d ms", millis));}

并行流处理 嘎嘎快

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com