Java8新特性

从Java8到Java21各版本新特性详解 上面这张图是 Oracle 官方给出的 Oracle JDK 支持的时间线,可以看出,JDK 17的支持时间最长,可以延续到2029年9月。考虑到技术更新的速度,这次免费商用8年的时间可谓是经过精心考虑,旨在让用户放心地升级到JDK 17(不过JDK 8的支持时间更长,可以延续到2030年12月)。从JDK诞生到现在,仅有几个版本得到了长期支持,主要包括JDK 7、JDK 8、JDK 11以及即将发布的JDK 17,它将是继Java 8之后最重要的LTS版本,是Java社区八年努力的成果。 阅读详情

Lambda简介

Lambda表达式语法图

在这里插入图片描述

什么是Lambda?

Lambda表达式是一段可以传递的代码,它的核心思想是将面向对象中的传递数据变成传递行为。
Lambda表达式也可以看作是匿名内部类的简便写法。

对于一个Java变量,我们可以赋给其一个值:
在这里插入图片描述
现在我们想把一块代码赋给一个Java变量,把右边那块代码,赋给一个叫做aBlockOfCode的Java变量:
在这里插入图片描述
在Java8之前,这个是做不到的。但是Java8问世之后,利用Lambda特性,就可以做到了:
在这里插入图片描述
当然,这个并不是一个很简洁的写法。所以,为了使这个赋值操作更加优雅, 我们可以移除一些没用的声明:
在这里插入图片描述
这样,我们就成功的非常优雅的把一块代码赋给了一个变量。而这块代码,或者说这个被赋给一个变量的函数,就是一个Lambda表达式。

但是这里仍然有一个问题,就是变量aBlockOfCode的类型应该是什么?
在Jav 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是那段代码,需要是这个接口的实现。
简而言之就是,Lambda表达式本身就是一个接口的实现。

我们给上面的aBlockOfCode加上一个类型:
在这里插入图片描述
这种只有一个接口函数需要被实现的接口类型,我们叫它函数式接口。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成非函数接口,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了:
在这里插入图片描述
这样,我们就得到了一个完整的Lambda表达式声明:
在这里插入图片描述

Lambda表达式有什么作用?

最直观的作用就是使得代码变得异常简洁。

可以对比一下Lambda表达式和传统的Java对同一个接口的实现:
在这里插入图片描述
这两种写法本质上是等价的。但是显然,Java 8中的写法更加优雅简洁。并且,由于Lambda可以直接赋值给一个变量,我们就可以直接把Lambda作为参数传给函数,而传统的Java必须有明确的接口实现的定义,初始化才行:
在这里插入图片描述
有些情况下,这个接口实现只需要用到一次。传统的Java 7必须要求你定义一个污染环境的接口实现MyInterfaceImpl,而相较之下Java 8的Lambda, 就显得干净很多。

Lambda基础语法

在lambda中我们遵循如下的表达式来编写:

expression = (variable) -> action
  • variable: 这是一个变量,一个占位符。像x,y,z,可以是多个变量;
  • action: 这里我称它为action, 这是我们实现的代码逻辑部分,它可以是一行代码也可以是一个代码片段。
    可以看到Java中lambda表达式的格式:参数、箭头、以及动作实现,当一个动作实现无法用一行代码完成,可以编写 一段代码用{}包裹起来。

lambda表达式可以包含多个参数,例如:

int sum = (x, y) -> x + y;

这时候我们应该思考这段代码不是之前的x和y数字相加,而是创建了一个函数,用来计算两个操作数的和。 后面用int类型进行接收,在lambda中为我们省略去了return。

Lambda示例

public interface LambdaInter {
    int add(int x, int y);
}

public class JDK8Demo {

    public static void main(String[] args) {
        LambdaInter lambdaInter = (x, y) -> {
            return x + y;
        };

        int add = lambdaInter.add(8, 9);
        System.out.println(add);
    }

}

总结:
lambda 可以隐式的创建只有一个抽象方法的匿名内部类。
在Java编程中,方法入参传递的对象是一个接口,这时需要匿名实现这个接口并实现抽象方法。如果这个接口只有一个抽象方法,就能使用lambda方式替换。

@FunctionalInterface
interface GreetingService {
    void sayMessage(String message);
}

上面的代码可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的)。

Lambda表达式中的异常处理

Java 8 lambda表达式中的异常处理
如何优雅的处理Lambda中异常?
在使用Lambda开发过程中,如果发现Lambda表达式中如果存在检查异常,我们只能使用try-catch去处理异常,那么这个Lambda表达式就会看起来非常臃肿。
在Lambda中使用try-catch处理异常:

list.forEach(e -> {
    try{
        Thread.sleep(1000L);
    }catch (InterruptedException ex){
        System.err.println("发生异常  :"+ex.toString());
    }
});

这样处理的话看着非常臃肿,破坏了Lambda简洁的效果。其实我们还可以选择throw的方式将异常抛出去。
但在Lambda表达式中只能抛出非检查异常。

检查异常是不能抛出去的,编译无法通过。所以只能使用try-catch处理这个异常。

 // 非检查异常  编译通过
 list.forEach(e-> {
     throw new RuntimeException();
 });
 // 检查异常 编译不通过
 list.forEach(e -> {
     throw new IOException();
 });

使用包装方法处理非检查异常:

import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
// 对lambda异常进行处理的包装类
@Slf4j
public class HandlingConsumerWrapper {
    public static <T>  Consumer<T> handlingConsumerWrapper(Consumer<T> throwingConsumer){
        return  param -> {
            try{
                throwingConsumer.accept(param);
            }
            catch (Exception ex){
                log.error("在lambda中发生异常!", ex);
            }
        };
    }
}
public static void main(String[] args) {
    List<String> list = Arrays.asList("海", "上");
    // 非检查异常  编译通过
    list.forEach(HandlingConsumerWrapper.handlingConsumerWrapper(param->{
        Integer.valueOf(param);
    }));
}

上面这种方法并不能处理检查异常。

自定义一个函数接口来处理检查异常:

// 封装consumer接口异常的接口
public interface ThrowingConsumer<T, E extends Exception> {
    //对异常选择上抛,原consumer接口没有上抛,才不好处理异常
    void accept(T t) throws Exception;
}

import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
@Slf4j
public class HandlingConsumerWrapper {
    public static <T, E extends Exception>  Consumer<T> handlingConsumerWrapper(ThrowingConsumer<T, E> throwingConsumer){
        return  param -> {
            try{
                throwingConsumer.accept(param);
            }
            catch (Exception ex){
                log.error("在lambda中发生异常!", ex);
            }
        };
    }
}

我们定义了一个函数接口ThrowingConsumer,ThrowingConsumer的方法和Consumer接口一致,只不过抛出了异常,这样我们才可以在包装方法中处理检查异常。

将检查异常转化为非检查异常抛出去:

import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
@Slf4j
public class HandlingConsumerWrapper {
    public static <T, E extends Exception>  Consumer<T> handlingConsumerWrapper(ThrowingConsumer<T, E> throwingConsumer) throws E{
        return  param -> {
            try{
                throwingConsumer.accept(param);
            }
            catch (Exception ex){
                // 将检查异常作为非检查异常抛出去
                throwAsUnchecked(ex);
            }
        };
    }
    private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
        throw (E) exception;
    }
}

处理Lambda的工具类:

import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class LambdaExceptionUtil {

    @FunctionalInterface
    public interface Consumer_WithExceptions<T, E extends Exception> {
        void accept(T t) throws E;
    }

    @FunctionalInterface
    public interface BiConsumer_WithExceptions<T, U, E extends Exception> {
        void accept(T t, U u) throws E;
    }

    @FunctionalInterface
    public interface Function_WithExceptions<T, R, E extends Exception> {
        R apply(T t) throws E;
    }

    @FunctionalInterface
    public interface Supplier_WithExceptions<T, E extends Exception> {
        T get() throws E;
    }

    @FunctionalInterface
    public interface Runnable_WithExceptions<E extends Exception> {
        void run() throws E;
    }

    /**
     * .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name)))); or .forEach(rethrowConsumer(ClassNameUtil::println));
     */
    public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E {
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception exception) {
                throwAsUnchecked(exception);
            }
        };
    }

    public static <T, U, E extends Exception> BiConsumer<T, U> rethrowBiConsumer(BiConsumer_WithExceptions<T, U, E> biConsumer) throws E {
        return (t, u) -> {
            try {
                biConsumer.accept(t, u);
            } catch (Exception exception) {
                throwAsUnchecked(exception);
            }
        };
    }

    /**
     * .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
     */
    public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E {
        return t -> {
            try {
                return function.apply(t);
            } catch (Exception exception) {
                throwAsUnchecked(exception);
                return null;
            }
        };
    }

    /**
     * rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))),
     */
    public static <T, E extends Exception> Supplier<T> rethrowSupplier(Supplier_WithExceptions<T, E> function) throws E {
        return () -> {
            try {
                return function.get();
            } catch (Exception exception) {
                throwAsUnchecked(exception);
                return null;
            }
        };
    }

    /**
     * uncheck(() -> Class.forName("xxx"));
     */
    public static void uncheck(Runnable_WithExceptions t) {
        try {
            t.run();
        } catch (Exception exception) {
            throwAsUnchecked(exception);
        }
    }

    /**
     * uncheck(() -> Class.forName("xxx"));
     */
    public static <R, E extends Exception> R uncheck(Supplier_WithExceptions<R, E> supplier) {
        try {
            return supplier.get();
        } catch (Exception exception) {
            throwAsUnchecked(exception);
            return null;
        }
    }

    /**
     * uncheck(Class::forName, "xxx");
     */
    public static <T, R, E extends Exception> R uncheck(Function_WithExceptions<T, R, E> function, T t) {
        try {
            return function.apply(t);
        } catch (Exception exception) {
            throwAsUnchecked(exception);
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
        throw (E) exception;
    }
}

函数式编程

函数式编程是种编程方式,并不是Java8的新特性,只是Java8内置了很多函数式编程的类,它将电脑运算视为函数的计算。将业务逻辑细化,抽象,封装成一个个功能函数,并借助语言自带的高阶函数api,将整个业务流程转化为函数之间的相互调用,这就是函数式编程。

与命令式编程相比,函数式编程更加强调做什么,在函数式编程中我们只需要关注做什么样的事情,不需要关注具体的实现细节。
例子:查找一个数组中的最小值;

import java.util.stream.IntStream;

public class MainMain{

    public static void main(String[] args) throws Exception {
        int[] nums = {33,55,-55,90,-666,90};

        // 命令式编程
        int min = Integer.MAX_VALUE;
        for (int i : nums){
            if (min > i){
                min = i;
            }
        }
        System.out.println("命令式编程实现:" + min);

        // 函数式编程实现
        int asInt = IntStream.of(nums).min().getAsInt();
        System.out.println("函数式编程实现:" + asInt);
    }
}

说明:
使用命令式编程,需要用程序告诉计算机我们每一步需要做什么最终才能实现我们想要的结果;
如果我们使用函数式编程我们只需要关注我们最终要实现的结果即可,而且从代码量的角度来看,也简洁了不少;

函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,一般通过@FunctionalInterface这个注解来表明某个接口是一个函数式接口。
函数式接口可以被隐式转换为 lambda 表达式。
Runnable就是一个函数式接口,来看看jdk中的Runnable源码

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

函数式编程入门

Java8中函数式编程语法能够精简代码。
使用Consumer作为示例,它是一个函数式接口,包含一个抽象方法accept,这个方法只有输入而无输出。
现在我们要定义一个Consumer对象,传统的方式是这样定义的:

Consumer c = new Consumer() {
    @Override
    public void accept(Object o) {
        System.out.println(o);
    }
};

而在Java8中,针对函数式编程接口,可以使用Lambda表达式定义:

Consumer c = (o) -> {
    System.out.println(o);
}; 

上面已说明,函数式编程接口都只有一个抽象方法,因此在采用这种写法时,编译器会将这段函数编译后当作该抽象方法的实现。
如果接口有多个抽象方法,编译器就不知道这段函数应该是实现哪个方法的了。

语法说明:

  • =后面的函数体我们就可以看成是accept函数的实现。
  • 输入(入参):->前面的部分,即被()包围的部分。此处只有一个输入参数,实际上输入是可以有多个的,如两个参数时写法:(a, b);当然也可以没有输入,此时直接就可以是()。
  • 函数体:->后面的部分,即被{}包围的部分;可以是一段代码。
  • 输出(返回值):函数式编程可以没有返回值,也可以有返回值。如果有返回值时,需要代码段的最后一句通过return的方式返回对应的值。

当函数体中只有一个语句时,可以去掉{}进一步简化:

Consumer c = (o) -> System.out.println(o);

然而这还不是最简的,由于此处只是进行打印,调用了System.out中的println静态方法对输入参数直接进行打印,因此可以简化成以下写法:

Consumer c = System.out::println;

它表示的意思就是针对输入的参数将其调用System.out中的静态方法println进行打印。

JDK8中新增的函数式接口

在java.util.function包中提供了很多函数式接口。
具体分为四大类如下:
在这里插入图片描述
每个类型接口都有分支接口,接口默认入参、出参类型是泛型,分支接口就是用来限定入参、出参类型或可指定多个入参的。
比如:限定Consumer的入参类型为Long,Consumer默认是只有一个入参的,BiConsumer可以有两个入参。

Consumer

Consumer是消费的意思,即针对某个东西我们来使用它,因此它包含有一个输入而无输出的accept接口方法。
接口定义:
在这里插入图片描述
andThen方法专门用来连续执行Consumer的accept。
Consumer也有很多分支接口,比如:LongConsumer(限定入参数类型为Long)、BiConsumer(有两个入参)。

public static <T> void consumerDemo(T param, Consumer<T> consumer) {
    consumer.accept(param);
}
public static void main(String[] args) {
    consumerDemo("James", param-> {
        System.out.println("My name is " + param);
    });
    Consumer<String> c1 = (param)->{
        System.out.println(param + " c1");
    };
    Consumer<String> c2 = (param)->{
        System.out.println(param + " c2");
    };
    Consumer<String> c3 = (param)->{
        System.out.println(param + " c3");
    };
    // 连续执行Consumer的Accept方法
    c1.andThen(c2).andThen(c3).accept("Tom");
}

运行结果:

My name is James
Tom c1
Tom c2
Tom c3

Supplier

Supplier是提供者的意思,无传入参数,有返回值,直接理解成一个创建对象的工厂就可以了。
接口定义:
在这里插入图片描述

class User{    }
public static Integer supply(Supplier<Integer> supplier) {
    return supplier.get();
}
public static void main(String[] args) {
    Integer supply = supply(() -> {
        return (int) (Math.random() * 100);
    });
    System.out.println(supply);
    
    Supplier<String> supplier = String::new;
    System.out.println(supplier.get());

    Supplier<User> userSupplier = User::new;
    User user = userSupplier.get();
}

可以看到,这个接口,只是为我们提供了一个创建好的对象,提供者,提供一个对象。

Function

Function是函数的意思,也可以表示功能的意思。
而函数经常是有输入输出的,因此它含有一个apply方法,包含一个输入与一个输出。
接口定义:
在这里插入图片描述

@Test
public void test() {
    Function<Integer, Integer> f1 = s -> {
        System.out.println("f1...run...");
        return s++;
    };
    Function<Integer, Integer> f2 = s -> {
        System.out.println("f2...run...");
        return s * 2;
    };

    /**
     * 下面表示在执行compose时,先执行f2,后执行f1, 并且f2的输出当作f1的输入。
     * 相当于以下代码:
     * Integer a = f2.apply(1)
     * Integer b = f1.apply(a)
     */
    Function<Integer, Integer> compose = f1.compose(f2);
    System.out.println(compose.apply(1));
    System.out.println("---黄金分割线---");

    // 面表示在执行andThen时,先执行f1,后执行f2, 并且f1的输出当作f2的输入。
    Function<Integer, Integer> andThen = f1.andThen(f2);
    System.out.println(andThen.apply(1));
    System.out.println("---黄金分割线---");

    // identity方法会返回一个不进行任何处理的Function,即输出与输入值相等;
    System.out.println(Function.identity().apply("hello"));
}

运行结果:
在这里插入图片描述

Predicate

Predicate是断定意思,判断某个东西是否满足某种条件; 因此它包含test方法,根据输入值来做逻辑判断,其结果为True或者False。
在这里插入图片描述

@Test
public void test() {
    Predicate<String> p1 = o -> o.equals("test");
    Predicate<String> p2 = o -> o.startsWith("t");

    System.out.println(p1.test("test"));
    // negate: 做取反处理
    System.out.println(p1.negate().test("test"));

    // and: 针对同一输入值,多个Predicate均返回True时返回True,否则返回False;
    System.out.println(p1.and(p2).test("test"));

    // or: 针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False
    System.out.println(p1.or(p2).test("test"));
}

双冒号(::)运算符的使用

什么是双冒号?

双冒号::运算符在Java 8中被用作方法引用(method reference),方法引用是与Lambda表达式相关的一个重要特性,是Lambda表达式最精简的写法。

官方解释翻译:使用Lambda表达式会创建匿名方法,但有时候需要使用一个Lambda表达式只调用一个已经存在的方法(不做其它), 所以这才有了方法引用!

个人理解双冒号的用法

(参数1,参数2) -> 类名.方法名(参数1,参数2)
等价于:
类名::方法名
双冒号相当于是把函数式接口的方法的入参作为类名.方法名()的参数执行。

Java8中方法引用的语法

  • 静态方法引用(static method)语法:classname::methodname 例如:Person::getAge
  • 对象的实例方法引用语法:instancename::methodname 例如:System.out::println
  • 对象的超类方法引用语法: super::methodname
  • 类构造器引用语法: classname::new 例如:ArrayList::new
  • 数组构造器引用语法: typename[]::new 例如: String[]:new

静态方法语法

public class MainMain {

    public static void main(String[] args) throws Exception {
        List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");

        // 静态方法语法	ClassName::methodName
        list.forEach(MainMain::print);
    }

    public static void print(String content){
        System.out.println(content);
    }
}

类实例方法语法

public class MainMain {

    public static void main(String[] args) throws Exception {
        List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");

        // 对象实例语法:instanceRef::methodName
        list.forEach(new MainMain()::print);
    }

    public void print(String content){
        System.out.println(content);
    }
}

超类方法语法

public class Example extends BaseExample{
    @Test
    public void test(){
        List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
        // 对象的超类方法语法:super::methodName
        list.forEach(super::print);
    }
}

public class BaseExample {
    public void print(String content){
        System.out.println(content);
    }
}

类构造器语法

public class Example{
    @Test
    public void test(){
        InterfaceExample com =  Example::new;
        Example bean = com.create();
        System.out.println(bean);
    }
}

public interface InterfaceExample {
    Example create();
}

带参数的构造器,示例如下:

public class Example{
    private String name;

    Example(String name){
        this.name = name;
    }

    public static void main(String[] args) {
        InterfaceExample com =  Example::new;
        Example bean = com.create("hello");
        System.out.println(bean.name);
    }
}

public interface InterfaceExample {
    Example create(String name);
}

注意:Example 类并没有implements InterfaceExample接口!!!

数组构造器语法

public class Example{

    public static void main(String[] args) {
        Interface <Integer, Example[]> function = Example[]::new;
        Example[] array = function.create(4);	//这里的4是数组的大小

        for(Example e:array){
            System.out.println(e);
        }
    }
}

@FunctionalInterface
public interface Interface<A, T> {
    T create(A a);
}

接口的默认方法和静态方法

在Java语言中,一个接口中定义的方法必须由实现类提供实现。但是当接口中加入新的API时, 实现类按照约 定也要修改实现,而Java8的API对现有接口也添加了很多方法,比如List接口中添加了sort方法。 如果按照之前的做法,那么所有的实现类都要实现sort方法,JDK的编写者们一定非常抓狂。

幸运的是我们使用了Java8,这一问题将得到很好的解决,在Java8种引入新的机制,支持在接口中声明方法同时提供实现。

默认方法案例:

default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}

Java 8带来的另一个有趣的特性是在接口中可以定义静态方法,例子代码如下:

private interface DefaulableFactory {
    // Interfaces now allow static methods
    static Defaulable create( Supplier< Defaulable > supplier ) {
        return supplier.get();
    }
}

public static void main( String[] args ) {
    Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );
    defaulable = DefaulableFactory.create( OverridableImpl::new );
}

由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等。

尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误。

使用Collections工具类排序集合

List<Employee> employees = Arrays.asList(new Employee(23), new Employee(30));
Collections.sort(employees, (x, y) -> {
    return Integer.compare(x.getAge(), y.getAge());
});

List<User> list = Arrays.asList(new User(23), new User(56));
// 按自然序排序
Collections.sort(list, Comparator.comparing(User::getAge));
// 按自然序逆序
Collections.sort(list, Comparator.comparing(User::getAge).reversed());

参考:
不少Java程序员都觉得Lambda表达式很鸡肋,它到底有何用呢?

K230开发板实战:5步搞定YOLOv8模型部署(附常见报错解决方案) 本文提供了一份详细的K230开发板部署YOLOv8模型的实战教程。内容涵盖从环境准备、模型转换到代码编写的完整流程,并重点解析了使用AICube工具链时常见的“生成部署文件异常”等报错解决方案,旨在帮助开发者高效完成嵌入式AI模型部署。 阅读详情

相关推荐

MavLink协议入门

MAVLink是一个非常轻量化的开源的消息协议,用于无人机之间的通信以及无人机机载设备之间的通信。

ffffffeiyu的博客 2474

最全java8 讲解【建议收藏,反复研读】

在这里,被包起来的收集器就是用 maxBy 建立的那个,而转换函数 Optional::get 则把返回的 Optional 中的值提取出来。可以看到,行为参数化是一个很有用的模式,它能够轻松地使用不断变化的需求,这种模式可以把一个行为封装起来,并通过传递和使用创建的行为将方法的行为参数化。的抽象方法,它没有传入参数,会返回一个泛型 T 的对象,如果你需要定义一个 Lambda,输出自定义的对象,就可以使用这个接口。来定义一个默认值,遭遇到空的Optional值的时候,默认值会作为该方法的调用返回值。

1万+

带标签的PHM2009齿轮箱数据集

PHM2009附加数据集—带标签的齿轮箱数据集,可用于测试算法

qq_39379705的博客 4873

Java8(JDK1.8) 新特性介绍

这些方法可以添加到任何现有接口中,我们不需要强制在实现类中实现这些方法,因此我们可以在不破坏代码的情况下将这些默认方法添加到现有接口中。如果一个方法的参数和返回值全部是Consumer类型,那么就可以实现效果,消费一个数据的时候,首先做一个操作,然后再做一个操作,实现组合。该接口中的方法可以接收一个参数,接收的参数类型由泛型指定,对参数的操作 方式根据该接口的实现类决定,不需要返回值。2. 默认方法可以被继承,实现类可以直接调用接口默认方法,也可以重写接口默认方法。只关心抽象方法的参数列表和返回值类型。

郝南过的博客 1万+

Anaconda镜像源切换全攻略:从清华源到恢复默认设置的完整流程

本文详细介绍了Anaconda镜像源的管理与优化,重点讲解了如何配置清华源以提升国内下载速度。内容涵盖镜像源工作原理、清华源详细配置步骤、多源管理策略、常见问题排查以及如何安全恢复默认设置,帮助用户构建完整的镜像源管理体系。

weixin_28828243的博客 1020

modelsim软件安装教程及踩坑(极简版)

1.安装的网盘链接:链接:https://pan.baidu.com/s/1ltUfssyXlCnqDmLhWyhlwA提取码:jery 2.步骤(参考博文):https://blog.youkuaiyun.com/weixin_42693097/article/details/90523692?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163521788716780357213801%2522%252C%2522scm%2522%253A%2522

subtitle_的博客 3779

Java 8安装及配置

看完本文,您将学会1.Java 8的安装与配置;2.通过控制台在您的电脑上运行第一个Java程序

qq_73322993的博客 1万+

用CentOS 7安装cadence搭建适合IC Design的科研环境(四)——IC617、MMSIM151、calibre2015安装过程step by step

以下操作都在root权限下执行。建立安装目录建议把这种大型软件装在/opt目录下。mkdir -p /opt/cadence/installscape mkdir -p /opt/mentor/Calibre2015其中-p参数是直接建立父目录。因为IC617和MMISM151会自己建立安装目录,所以在这里没有建相关目录。而calibre则是默认安装在安装包所在的目录下,所以需要提前建立。解压安

maxwell2ic的博客 7万+

JAVA8 十大新特性详解

一、接口的默认方法在接口中新增了default方法和static方法,这两种方法可以有方法体 1、static方法 示例代码:public interface DefalutTest { static int a =5; default void defaultMethod(){ System.out.println("DefalutTest defalut 方法

cdw8131197的博客 4万+

宝骏kiwi 630 730 560 E100 E200 E300 310 510 610 330 530维修手册电路图资料线路图接线图更新

2020-2022年宝骏RS-3维修手册和电路图。2020-2022年宝骏RS-3维修手册和电路图。2019-2021年宝骏RC-6维修手册和电路图。2019-2021年宝骏RC-6维修手册和电路图。2019-2020年宝骏RS-5维修手册和电路图。2019-2020年宝骏RS-5维修手册和电路图。2019-2020年宝骏RM-5维修手册和电路图。2019-2020年宝骏RM-5维修手册和电路图。2019-2021年宝骏510维修手册和电路图。2019-2021年宝骏510维修手册和电路图。

weixin_45821055的博客 1771

【Unity大规模RTS/攻城战框架】Large Scale Combat System - RTS Sieges深度解析

本文介绍了Unity专业级大规模RTS战斗框架Large Scale Combat System(LSCS)。该系统通过Job System+Burst技术解决了万人级单位的性能问题,提供完整的RTS操作体系、动态阵型系统、战术AI和攻城战功能。其亮点包括可破坏城门、行走城墙、战术AI配置系统,支持URP渲染管线,适用于Total War风格的大规模兵团对战项目。LSCS不仅提供核心战斗系统,还包含UI、小地图等配套模块,是Unity中少有的专业级RTS解决方案,特别适合需要深度战术玩法和大规模战斗的开发者

2403_88403568的博客 1333

java8新特性Lambda和Stream以及函数式接口等新特性介绍

主要内容 1.Lambda 表达式 2.函数式接口 3.方法引用与构造器引用 4.Stream API 5.接口中的默认方法与静态方法 6.新时间日期API 7.其他新特性 Java 8新特性简介 速度更快 速度更快 代码更少(增加了新的语法Lambda 表达式) 强大的Stream API 便于并行 最大化减少空指针异常Optional Nashorn 引擎,允许在 JVM 上运行 JS 应用 其中最为核心的为Lambda 表达式与Stream API 并行流与串行流   并行流就是把一个内容分成多个

qq_36595761的博客 3232

AHB—SRAMC项目(结构图,核心代码、Testbench架构)

文章目录一、AHB_SRAMC项目介绍1.1.AHB总线控制单元(ahb_slv_if.v)1.2.SRAM控制单元(sramc_top.v)1.3.主要的传输路径二、结构框图2.1.AHB_SRAMC结构图(重点)2.2.总线控制单元与SRAM控制单元结构图三、部分核心代码(重点理解)四、SystemVerilog Testbench架构(重点)五、目录结构 一、AHB_SRAMC项目介绍 本项...

Mr.翟的博客 3万+

【Java】从java8到java17各版本新特性详解

下面这张图是 Oracle 官方给出的 Oracle JDK 支持的时间线,可以看出,JDK 17的支持时间最长,可以延续到2029年9月。考虑到技术更新的速度,这次免费商用8年的时间可谓是经过精心考虑,旨在让用户放心地升级到JDK 17(不过JDK 8的支持时间更长,可以延续到2030年12月)。从JDK诞生到现在,仅有几个版本得到了长期支持,主要包括JDK 7、JDK 8、JDK 11以及即将发布的JDK 17,它将是继Java 8之后最重要的LTS版本,是Java社区八年努力的成果。

一个天蝎座的程序猿 5889

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【Java 8 新特性】Java 8 新特性大全

【Java 8 新特性】目录Java Util StreamJava Util FunctionJava Util ConcurrentJava UtilJava TimeJava MathJava Lang Java Util Stream 【Java 8 新特性】Java Stream中forEachOrdered()和forEach() 【Java 8 新特性】如何将Java流(Stream)转化成数组(Array) Java Util Function Java Util Concurrent

猫巳的博客 3033

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Java 8的新特性—终极版

前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with Java 8 – Lambdas and Concurrency、Java 8 Date Time API Tutorial : LocalDateTime和Abstract Class Versus

飞鸟Blog 14万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

重学Java 8新特性 | 第1讲——我们为什么要学习Java 8新特性?

为什么我们一定要学习Java 8新特性?

李阿昀的博客 1721

Java8 接口新特性

Java8 Lambda Expressions 1 Lambda出现的背景 1.1 Java8之前面对的问题 当我们实现一个接口时,因为语法定义,不得不创建一个实现类,或者一个匿名类,如下: button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {...

Weison 7301

Java8新特性——Lambda表达式

Java8新特性——Lambda表达式 Java8新特性 Java8新特性(又称为 jdk1.8)是Java语言开发的一个主要版本。Oracle公司于2014年3月18日发布Java8,它支持函数式编程,新的JavaScript引擎,新的日期API,新的Stream API等。——摘自菜鸟教程 Java8 新增特性 Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有 Java 类或对象(实

qq_50994235的博客 3535

Java 8 新特性

Java 8 新特性

YIYIYI 1573

jdk8新特性_Java系列之Java 8 新特性必知必会

课程目标:通过本课程的学习,详细掌握Java8新特性之接口默认方法、函数式接口、可重复注解、Optional;适用人群:有Java基础的开发人员; 课程概述:Java 8是一个跨越式的版本,于2014年3月18日正式发布,距今几年过去了,很多企业的项目中都使用了Java8进行开发,很多开源框架也都要求至少JDK8,由于Java8中有很多重要的变化,如果不掌握Java8的这些新特性,可能我们在实际项...

weixin_40009472的博客 85

java8新特性-排序

java8新特性排序 最近新入手一项目,基本都是java8写法(过滤,排序)感觉很不错,就抽空学习下并总结: 案例一 /** * java排序 * @author andy * */ public class Test2 { public static void main(String[] args) { List<String> strs=new ArrayList&...

最初的节奏 773

Java 进化之路:从 Java 8 到 Java 21 的重要新特性

谁能想到这个1995年诞生的语言,在2023年居然已经更新到Java 21了!看到这里你可能要问:Oracle这更新速度是要逼死开发者吗?不过学新特性这件事…毕竟面试官最爱问这些(手动狗头)这行代码当年让多少开发者感动到流泪(终于不用写冗长的匿名内部类了)(企业级应用建议锁定Java 11/17/21这三个LTS版本)→ “hello”(比trim()更智能的空白处理)(垃圾回收延迟<1ms不是梦!(终于不用写匿名类了!(再也不用第三方库了!游戏服务器和金融系统狂喜。(集合操作从此起飞)

binbinaishijie88的博客 1064

Java 8新特性总结

Java 8新特性学习总结 1 前言 Java8已经出现了很久了,但是呢,还是有很多人都还在习惯使用以前的来版本JDK,或者是以前老版本的编程方式。通过一段时间对Java8新特性的学习之后,自己也深受感触,原来java8版本写代码可以这么简洁。Java8最主要的就是给我们编程的过程带来了很多便利,不仅仅是代码量少。更多的还是让程序更简洁,减少代码冗余。Java8新特性中有几个比较主要的特性,Lam...

weixin_43288034的博客 383

Java8 新特性

Java8 新特性 前言 Java8已经出现了很久了,但是呢,还是有很多人都还在习惯使用以前的来版本JDK,或者是以前老版本的编程方式。通过一段时间对Java8新特性的学习之后,自己也深受感触,原来java8版本写代码可以这么简洁。Java8最主要的就是给我们编程的过程带来了很多便利,不仅仅是代码量少。更多的还是让程序更简洁,减少代码冗余。Java8新特性中有几个比较主要的特性,Lambda 表达...

weixin_45864733的博客 293

java8 到java11 新特性以及LTS官方维护截止时间

java8新特性介绍 https://www.oracle.com/technetwork/cn/java/javase/8-whats-new-2157071-zhs.html java9 新特性介绍 https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-9/index.html java10 新特性介绍 http...

输微 7230
上一篇: VirtualBox 之安装CentOS
下一篇: MySQL 之SQL的几种连接查询
yyangqqian
博客等级 码龄15年 406粉丝 406原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值