文章目录
-
- JDK8
-
-
- Lambda表达式
- 函数式接口
- 方法引用
- Stream API
- 接口中的默认方法和静态方法
- Optional
-
- JDK9
-
-
- 收集工厂方法
-
- JDK10
- JDK 10 && JDK 11
- JDK 12
- JDK 13
- JDK14
- JDK15
JDK8
-
Lambda表达式
最直接作用就是减少代码,代码直接减少50%+,显得非常简洁
//使用java匿名内部类Comparator<Integer> cpt = new Comparator<Integer>() {
@Overridepublic int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);}};TreeSet<Integer> set = new TreeSet<>(cpt);System.out.println("=========================");//使用JDK8 lambda表达式Comparator<Integer> cpt2 = (x,y) -> Integer.compare(x,y);TreeSet<Integer> set2 = new TreeSet<>(cpt2);
// java7中 筛选产品为nike的
public List<Product> filterProductByColor(List<Product> list){
List<Product> prods = new ArrayList<>();for (Product product : list){
if ("nike".equals(product.getName())){
prods.add(product);}}return prods;}// 使用 lambda
public List<Product> filterProductByPrice(List<Product> list){
return list.stream().filter(p->"nike".equals(p.getName())).collect(Collectors.toList()); }
-
函数式接口
位于java.util.function包下,下面介绍最常用的几个
- Predicate
接收一个值返回boolean
Predicate p = t->true;
- Supplier
无接受参数返回一个值
Supplier<T> s = () -> new T();
- Consumer
接受一个参数无返回值
Consumer<String> c = c -> System.out.println(s);
- Function<T,R>
接受参数T 返回参数R
Function<Long,String> f = c -> String.valueof(c);
其他还有一些 BiFunction,BiConsumer,DoubleSupplier等
-
方法引用
- 静态引用:
格式:Class::static_method
List<String> list = Arrays.asList("a","b","c");
list.forEach(str -> System.out.print(str));
list.forEach(System.out::print);
- 构造器调用
构造器方法引用格式:Class::new,调用默认构造器
List<String> list = Arrays.asList("a","b","c");
List<Test> list.stream().map(Test::new).collect(Collectors.toList());public class Test{
private final String desc;public Test(String desc){
this.desc=desc;}}
- 方法调用
格式:instance::method
List<String> list = Arrays.asList("a","b","c");
Test test = new Test();
List<String> list.stream().map(test::toAdd).collect(Collectors.toList());public class Test{
private final String desc;public Test(String desc){
this.desc=desc;}public String toAdd(String desc){
return desc+"add";}
}
-
Stream API
// 使用jdk1.8中的Stream API进行集合的操作
@Test
public void test(){
// 循环过滤元素 proList.stream().fliter((p) -> "红色".equals(p.getColor())).forEach(System.out::println);// map处理元素然后再循环遍历proList.stream().map(Product::getName).forEach(System.out::println);// map处理元素转换成一个ListproList.stream().map(Product::getName).collect(Collectors.toList());
}
-
接口中的默认方法和静态方法
public interface ProtocolAdaptor {
ProtocolAdaptor INSTANCE = DynamicLoader.findFirst(ProtocolAdaptor.class).orElse(null);default ProtocolAdaptor proxy() {
return (ProtocolAdaptor) Proxy.newProxyInstance(ProtocolAdaptor.class.getClassLoader(),new Class[]{
ProtocolAdaptor.class},(proxy, method, args) -> intercept(method, args));}}
-
Optional
用于处理对象空指针异常:
public String getDesc(Test test){
return Optional.ofNullable(test).map(Test::getDesc).else("");}
JDK9
-
收集工厂方法
借助Java 9的一项新功能,即集合工厂方法,您可以轻松地使用预定义的数据创建不可变的集合。您只需要在特定集合类型上使用of方法。
List<String> fruits = List.of("apple", "banana", "orange");
Map<Integer, String> numbers = Map.of(1, "one", 2,"two", 3, "three");
在Java 9之前,您可以使用Collections,但这绝对是一种更复杂的方法。
public List<String> fruits() {
List<String> fruitsTmp = new ArrayList<>();fruitsTmp.add("apple");fruitsTmp.add("banana");fruitsTmp.add("orange");return Collections.unmodifiableList(fruitsTmp);
}public Map<Integer, String> numbers() {
Map<Integer, String> numbersTmp = new HashMap<>();numbersTmp.put(1, "one");numbersTmp.put(2, "two");numbersTmp.put(3, "three");return Collections.unmodifiableMap(numbersTmp);
}
同样,仅从ArrayList对象表创建即可使用Arrays.asList(…)method。
public List<String> fruitsFromArray() {
String[] fruitsArray = {
"apple", "banana", "orange"};return Arrays.asList(fruitsArray);
}
接口中的私有方法
从Java 8开始,您可以在接口内部使用公共默认方法。但是仅从Java 9开始,由于接口中的私有方法,您将能够充分利用此功能。
public interface ExampleInterface {
private void printMsg(String methodName) {
System.out.println("Calling interface");System.out.println("Interface method: " + methodName);}default void method1() {
printMsg("method1");}default void method2() {
printMsg("method2");}}
JDK10
从Java 9和Java 10开始,有几种用于Optional的有用方法。其中最有趣的两个是orElseThrow和ifPresentOrElse。如果没有值,则使用该orElseThrow方法抛出NoSuchElementException。否则,它返回一个值。
public Person getPersonById(Long id) {
Optional<Person> personOpt = repository.findById(id);return personOpt.orElseThrow();
}
因此,您可以避免将带参数的if语句与isPresentmethod一起使用。
public Person getPersonByIdOldWay(Long id) {
Optional<Person> personOpt = repository.findById(id);if (personOpt.isPresent())return personOpt.get();elsethrow new NoSuchElementException();
}
第二种有趣的方法是ifPresentOrElse。如果存在一个值,它将使用该值执行给定的操作。否则,它将执行给定的基于空的操作。
public void printPersonById(Long id) {
Optional<Person> personOpt = repository.findById(id);personOpt.ifPresentOrElse(System.out::println,() -> System.out.println("Person not found"));
}
在Java 8中,我们可以if-else直接与isPresent方法一起使用。
public void printPersonByIdOldWay(Long id) {
Optional<Person> personOpt = repository.findById(id);if (personOpt.isPresent())System.out.println(personOpt.get());elseSystem.out.println("Person not found");
}
JDK 10 && JDK 11
从Java 10开始,您可以声明没有其类型的局部变量。您只需要定义var关键字而不是类型。从Java 11开始,您还可以将其与lambda表达式一起使用,如下所示。
public String sumOfString() {
BiFunction<String, String, String> func = (var x, var y) -> x + y;return func.apply("abc", "efg");
}
JDK 12
使用Switch表达式,您可以定义多个case标签并使用箭头返回值。此功能自JDK 12起可用。它使Switch表达式真正更易于访问。
public String newMultiSwitch(int day) {
return switch (day) {
case 1, 2, 3, 4, 5 -> "workday";case 6, 7 -> "weekend";default -> "invalid";};}
对于低于12的Java,相同的示例要复杂得多。
public String oldMultiSwitch(int day) {
switch (day) {
case 1:case 2:case 3:case 4:case 5:return "workday";case 6:case 7:return "weekend";default:return "invalid";}}
JDK 13
文本块是多行字符串文字,它避免使用转义序列,并以可预测的方式自动设置字符串格式。它还使开发人员可以控制字符串的格式。从Java 13开始,文本块可用作预览功能。它们以三个双引号(""")开头。让我们看看我们如何轻松地创建和格式化JSON消息。
public String getNewPrettyPrintJson() {
return """{
"firstName": "Piotr","lastName": "Mińkowski"}""";
}
创建Java 13之前的相同JSON字符串要复杂得多。
public String getOldPrettyPrintJson() {
return "{\n" +" \"firstName\": \"Piotr\",\n" +" \"lastName\": \"Mińkowski\"\n" +"}";}
JDK14
使用Records,您可以定义不可变的纯数据类(仅限getter)。它会自动创建toString,equals和hashCode方法。实际上,您只需要定义如下所示的字段即可。
public record Person(String name, int age) {
}
具有类似功能的类如record包含字段,构造函数,getter和实施toString,equals以及hashCode方法。
public class PersonOld {
private final String name;private final int age;public PersonOld(String name, int age) {
this.name = name;this.age = age;}public String getName() {
return name;}public int getAge() {
return age;}@Overridepublic boolean equals(Object o) {
if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;PersonOld personOld = (PersonOld) o;return age == personOld.age && name.equals(personOld.name);}@Overridepublic int hashCode() {
return Objects.hash(name, age);}@Overridepublic String toString() {
return "PersonOld{" +"name='" + name + '\'' +", age=" + age +'}';}}
JDK15
使用密封类功能,您可以限制超类的使用。使用new关键字,sealed您可以定义哪些其他类或接口可以扩展或实现当前类。
public abstract sealed class Pet permits Cat, Dog {
}
允许的子类必须定义一个修饰符。如果您不想允许任何其他扩展名,则需要使用final关键字。
public final class Cat extends Pet {
}
另一方面,您可以打开扩展类。在这种情况下,应使用non-sealed修饰符。
public non-sealed class Dog extends Pet {
}
当然,下面的可见声明是不允许的。
public final class Tiger extends Pet {
}