一文涵盖Lambda,Stream,响应式编程,从此爱上高效率编程

一文涵盖Lambda,Stream,响应式编程,从此爱上高效率编程

前言

本文结构为 先是一个例子,带你快速体验,之后再去深究里面的方法。以及一些底层原理是如何实现的。从如何用,到如何用好,如何用精。学习操作,学习思维。

Lambda表达式

初体验

这个是Java8的新特性。来源于数学中的演算。

是一套关于函数定义、输入量、输出量的计算方案。

简单来说,Lambda表达式就是一个简单的函数。

首先来看一个案例。

这里有一个接口。

public interface Factory {
    Object getObject();
}

以及实现类


public class SubClass implements Factory{
    @Override
    public Object getObject() {
        return new User();

    }
}

实体类是:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer age;
}

我们来看前俩种写法

public static void main(String[] args) {
    //1.子类实现接口
    Factory factory = new SubClass();
    User user1 = (User) factory.getObject();
    System.out.println(user1);

    //2.匿名内部类
    factory = new Factory() {
        @Override
        public Object getObject() {
            return new User("xiaou", 18);
        }
    };
    User user2 = (User) factory.getObject();
    System.out.println(user2);
}

之后我们来看一个lambda表达式的写法。

//3.Lambda表达式
factory = () -> {
    return new User("xiaou", 18);
};

可以看出来是非常的简单的

通过对比,我们可以看出这个是非常的简单的。

我们来说一下他的优点:

  • 让代码变得更加简洁、紧凑
  • 函数式编程:
    • 函数是"第一等公民",可以像一个变量一样去调用
    • 可以赋值给变量
    • 可以作为其他函数的参数就行传递
    • 可以作为其他函数的返回值

首先来看第三条

//lambda作为参数进行传递
User user4 = getUserFormFactory(() -> {
    return new User("xiaou", 20);
}, "User");
System.out.println(user4);
public static User getUserFormFactory(Factory factory, String beanName) {
    User object = (User) factory.getObject();
    if (object != null && object.getClass().getSimpleName().equals(beanName)) {
        return object;
    }
    return null;
}

来看第四条

public static Factory getFactory() {
    return () -> {
        return new User("xiaou", 21);
    };
}
//lambda作为参数返回值
Factory factory2 = getFactory();
User user5 = (User) factory2.getObject();
System.out.println(user5);

语法细节

image-20240412115135397

了解了语法,我们就可以进行一个改进对我们上面的案例。

//3.Lambda表达式
factory = () -> {
    return new User("xiaou", 19);
};
//改进版
factory = () -> new User("xiaou", 19);

如果你不知道什么时候应该简写,idea是可以去给你提醒的

image-20240412115421836

之后来看他的别的简写语法:

  • 函数体只有一个语句,省略大括号

      (String msg) -> System.out.println("hello" + msg);
    
  • 只有一个参数,省略圆括号,同时省略类型

    msg -> System.out.println("hello " + msg);
    
  • 函数体只有一个表达式,省略return

    (int a, int b) -> a + b;
    
  • 省略参数类型,编译器可以进行推断

    (a, b) -> a + b;
    

之后来看使用lambda表达式的前提。

使用前提

1.必须有一个函数式接口

函数式接口是Java中的一个关键概念,它指的是具有以下特征的接口:

  • 必须有一个抽象方法:这是函数式接口的核心 特征,接口中只有一个抽象方法。
  • @FunctionalInterface注解:虽然这个注解不是必须的,但它可以用来明确标识一个接口是函数式接口,同时提供编译时检查。

2.常见的函数式接口

Java API提供了多个预定义的函数式接口,这些接口广泛应用于函数式编程中,它们包括:

  • Runnable / Callable:用于表示没有返回值的可执行任务,Callable还可以返回一个值并抛出异常。
  • Supplier:表示一个不带参数但可以产生结果的操作。
  • Consumer:表示一个接受单个参数并返回无内容的操作,通常用于处理输入的数据。
  • Comparator:用于定义对象比较逻辑。
  • Predicate:表示一个参数的谓词(布尔值函数),用于判断一个对象是否满足某个条件。
  • Function:表示一个参数并返回结果的函数。

下面我们来详细讲解这些函数式接口

常见的函数式接口

Runnable
public static void main(String[] args) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            System.out.println(name + "正在运行1");
        }
    }).start();


    //lambda简化
    new Thread(() -> {
        String name = Thread.currentThread().getName();
        System.out.println(name + "正在运行2");
    }).start();
}
supplier
/**
 * 求数组最大值
 */
public class SupplierLambda {
    public static void main(String[] args) {
        int arr[] = {1, 2, 3, 4, 5};
        int max = getMax(() -> {
            int temp = arr[0];
            for (int i : arr) {
                if (i > temp) {
                    temp = i;
                }
            }
            return temp;
        });
        System.out.println(max);
    }

    public static int getMax(Supplier<Integer> supplier) {
        return supplier.get();
    }
}
Consumer

public class ConsumerLambda {
    public static void main(String[] args) {
        consumerString(str -> System.out.println(str));
        consumerString(
                s -> System.out.println(s.toUpperCase()),
                s -> System.out.println(s.toLowerCase())
        );
    }

    static void consumerString(Consumer<String> function) {
        function.accept("Hello");
    }

    static void consumerString(Consumer<String> first, Consumer<String> sec) {
        first.andThen(sec).accept("Hello World");
    }

}
Comparator
public static void main(String[] args) {

    String[] arr = {"abc", "def", "ghi"};

    //匿名类方法
    Comparator<String> comparator = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.length() - o2.length();
        }
    };

    //lambda表达式
    Arrays.sort(arr, (o1, o2) -> o1.length() - o2.length());
    System.out.println(Arrays.toString(arr));

}
Predicate
    public static void main(String[] args) {

        // 传统写法
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer t) {
                return t > 10;
            }
        };
        System.out.println(predicate.test(15));

        // lambda写法
        Predicate<Integer> predicate1 = (t) -> t > 10;
        System.out.println(predicate1.test(15));
    }
Function
public class FunctionLambda {
    public static void main(String[] args) {
        method((str) -> Integer.parseInt(str) + 10, (num) -> num * 2);
        String str = "xiaou,18";
        int ageNum = getAgeNum(str,
                s -> s.split(",")[1],
                s -> Integer.parseInt(s),
                s -> s + 10);
        System.out.println(ageNum);
    }

    static void method(Function<String, Integer> one, Function<Integer, Integer> two) {
        Integer num = one.andThen(two).apply("10");
        System.out.println(num);
    }

    static int getAgeNum(String str, Function<String, String> one, Function<String, Integer> two, Function<Integer, Integer> three) {
        return one.andThen(two).andThen(three).apply(str);
    }

Lambda底层实现

Lambda的本质:

函数式接口的匿名子类的匿名对象

我们来看下面的代码

    public static void main(String[] args) {
        List<String> stringList = Arrays.asList("掘", "金");
        stringList.forEach(s -> System.out.println(s));
    }
}

之后进行一个反编译。

public static void main(String[] args) {
    List<String> stringList = Arrays.asList("\u6398", "\u91d1");
    stringList.forEach((Consumer<String>)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)V, lambda$main$0(java.lang.String ), (Ljava/lang/String;)V)());
}

private static /* synthetic */ void lambda$main$0(String s) {
    System.out.println(s);
}

这个就是反编译的内容

可以看到,他其实就是对一个方法返回的结果进行了一个强转

所以说,他本身就是一个实例

这个方法的核心也就是去写了一个字节码文件

image-20240412143018577

下面是一个过程,比较枯燥,如果想看的可以来阅读一下

  • 为lambda表达式生成一个类,类名类似于:$$Lambda$xxx$yyy,其中xxx为lambda源码实现所在的类名,yyy为一串类似md5字符串的值。具体生成算法暂未深入研究。该类会继承于函数式接口,并且有一个public static的名为INSTANCE的字段,该字段的类型为$$Lambda$xxx$yyy,在类cinit中(经典的单例实现)。接口的抽象方法在实现很简单,就是调用一个名为xxx.lambda$zzz$N方法,xxx为lambda源码实现所在的类名,zzz为lambda源码实现所在的类的方法名,N为阿拉伯数字。xxx.lambda$zzz$N其实就是lambda表达式的具体逻辑的藏身之处。
  • xxx.lambda$zzz$N做为lambda实现的类,它是一个位于lambda实现类中的静态方法。如前文所述,它就是lambda表达式的具体实现。
  • 在lambda表达式调用的地方,会将lambda表达式替换为$$Lambda$xxx$yyy.INSTANCE。在后续调用接口方法,就直接调用$$Lambda$xxx$yyy.INSTANCE的接口实现,接着转调到实现类中的xxx.lambda$zzz$N方法,执行lambda真正的逻辑。

你可以把Lambda理解为一个语法糖。他用到了ASM技术,有兴趣的也可以去了解一下。下面是一个图来进行一个总结

image-20240412143405923

方法引用

初体验

我们也直接来看一个事例。

public static void main(String[] args) {
    //调用printString方法,参数是一个Printable类型的对象 也就是函数式接口
    printString(s -> {
        System.out.println(s);
    });
}

public static void printString(Printable p) {
    p.print("Xiaou");
}

我们来进行一个简化

//调用printString方法,参数是一个Printable类型的对象 也就是函数式接口
printString(s -> {
    System.out.println(s);
});


//使用lambda表达式简化
printString(System.out::println);

这个如果你看不懂,我们可以先看一下源码:

我们可以看到out就是一个PrintStream类型的常量

image-20240412144421658

之后我们来看println

image-20240412144652618

也就是说,这个代码也可以这样写

PrintStream out = System.out;
//使用lambda表达式简化
printString(out::println);

这样看起来就很直观了。

为什么需要这个方法引用呢?

当lambda表达式所要完成的业务逻辑已经存在 --已经有某个函数实现了

我们可以直接引用对于的方法

底层实现

我们还是进行一个反编译:

image-20240412144945298

我们可以看出来,lambda和方法引用实际上是一回事。

不过lambda是需要我们自己去写方法。

而方法引用是用系统里面自带的方法。

语法格式

方法引用运算符

双冒号 ::

哪些方法可以引用?

  • 类方法
  • 构造方法
  • 实例方法

被引用方法与函数式接口抽象方法需要满足以下条件:

  • 参数列表相同

    但是这种也是兼容的,属于是特殊情况

image-20240412150159113

  • 返回值类型兼容
格式范例
类名::静态方法Integer::parseInt
类名::newStudent::new
对象::成员方法"Hello"::toUpperCase this::方法名/super::方法名

方法引用举例

静态方法引用
public static void main(String[] args) {
    int number = method(-10, Math::abs);
    System.out.println(number);
}

public static int method(int number, Calcable calcable) {
    return calcable.calsAbs(number);
}

为什么这个可以使用呢?

我们来看我们的接口

public interface Calcable {
    int calsAbs(int num);
}

之后看这个abs

image-20240412150726020

可以发现俩个的返回值是一样的。并且参数也是一样的。所以我们可以使用。

如果我们改为别的类型,例如string

image-20240412150817862

可以发现他就报错了

构造方法引用
public interface PersonBuilder {
    Person builderPerson(String name);
}
public static void main(String[] args) {
    printName("xiaou", Person::new);
}

public static void printName(String name, PersonBuilder personBuilder) {
    Person person = personBuilder.builderPerson(name);
    System.out.println(person.getName());
}
普通方法引用

这个是没有优化的

package com.xiaou.demo7;

public class Test {
    public static void main(String[] args) {
        printString(s -> {
            Method method = new Method();
            method.printUpperCassString(s);
        });
    }

    public static void printString(Printable printable) {
        printable.print("Hello");
    }
}
//优化版本 引用某个普通成员的方法 对象名::方法名
public static void main(String[] args) {
    Method method = new Method();
    printString(method::printUpperCassString);
}

public static void printString(Printable printable) {
    printable.print("Hello");
}
super和this
public class Human {
    public void say(){
        System.out.println("xiaou");
    }
}
public class Man extends Human {
    @Override
    public void say() {
        System.out.println("xiaou say");
    }

    public void method(Greetable g) {
        g.greet();
    }

    public void show() {
        method(() -> {
            Human h = new Human();
            h.say();
        });
    }
}

我们需要来简化这个方法。

我们来看一下如何简化

public void show() {
    method(super::say);
}

之后来看this的。

public class Husband {
    public void buyHouse() {
        System.out.println("buyhouse");
    }

    public void marry(Richable richable) {
        richable.buy();
    }

    public void soHappy() {
        marry(() -> this.buyHouse());
    }
}

可以简化为

public void soHappy() {
    marry(this::buyHouse);
}
数组的方法引用
public static void main(String[] args) {
    int[] arr1 = createArray(10, int[]::new);
}

public static int[] createArray(int size, ArrayBuilder arrayBuilder) {
    return arrayBuilder.builderArray(size);
}

Stream流

初体验

我们直接来看需求:

查询集合中复合条件的人员

查询集合中姓张、并且长度为3的人

并打印出来

我们来看传统的做法。

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("张三");
    list.add("张三丰");
    list.add("张学友");
    list.add("张伟");

    // 遍历List集合
    List<String> listA = new ArrayList<>();
    for (String s : list) {
        if (s.startsWith("张")) {
            listA.add(s);
        }
    }

    //对listA进行处理
    List<String> listB = new ArrayList<>();
    for (String s : listA) {
        if (s.length() == 3) {
            listB.add(s);
        }
    }
    for (String s : listB) {
        System.out.println(s);
    }
}

可以看出来是非常的长的

我们来看stream实现

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("张三");
    list.add("张三丰");
    list.add("张学友");
    list.add("张伟");
    list.stream()
            .filter(name -> name.startsWith("张"))
            .filter(name -> name.length() == 3)
            .forEach(System.out::println);
}

stream只关注做什么,不关注怎么做。

filter也就是过滤。

特点

专注于对容器对象的聚合操作

提供串行/并行两种模式 使用Fork/Join框架拆分任务

image-20240412190954643

提高编程效率、可读性

使用步骤:

获得流->中间操作->终结操作

image-20240412190804942

API

中间操作 (Intermediate Operations)

中间操作会返回一个新的流,可以无限制地在一个流上串联起来。这些操作通常不会执行流的计算,而是构建一个流的处理管道。

  • map: 对流中的每个元素应用一个函数,并将结果作为新流的元素。
  • flatMap: 类似于map,但是可以创建一个流的流,然后将这些流连接起来。
  • filter: 过滤掉不满足给定谓词的元素。
  • distinct: 去除流中重复的元素。
  • sorted: 根据自然顺序或者提供的比较器对流中的元素进行排序。
  • peek: 查看流中的元素,通常用于调试。
  • limit: 限制流中元素的数量。
  • skip: 跳过流中前面的元素,数量由参数指定。
  • parallel: 将流的并行性设置为并行。
  • sequential: 将流的并行性设置为顺序。
  • unordered: 表示流的元素没有特定的顺序。
  • concat: 将两个流连接起来,形成一个有序的流。

终结操作 (Terminal Operations)

终结操作是流操作的最后步骤,它会生成一个结果或者副作用,并且会消耗流中的元素。

  • forEach: 对流中的每个元素执行一个操作。
  • forEachOrdered: 与forEach类似,但是保证按照流中元素的遇到顺序执行操作。
  • toArray: 将流中的元素收集到一个数组中。
  • reduce: 对流中的元素进行累积操作,得到一个结果。
  • collect: 收集流中的元素到一个收集器中。
  • min: 返回流中最小的元素。
  • max: 返回流中最大的元素。
  • count: 返回流中元素的数量。
  • iterator: 返回流中元素的迭代器。
  • anyMatch: 检查流中是否至少有一个元素满足给定的谓词。
  • allMatch: 检查流中的所有元素是否都满足给定的谓词。
  • noneMatch: 检查流中是否没有元素满足给定的谓词。
  • findFirst: 返回流中的第一个元素。
  • findAny: 返回流中的任意一个元素。

需要注意的是,我们不能再终结方法之后再去添加中间操作。

因为在执行终结方法后,流就已经执行完了。并且关闭了。

常用API

我们来看一些常用的API

获得流

首先是获取流

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    Stream<String> stream1 = list.stream();

    Set<String> set = new HashSet<>();
    Stream<String> stream2 = set.stream();

    Map<String, String> map = new HashMap<>();
    Set<String> keySet = map.keySet();
    Stream<String> stream3 = keySet.stream();

    Collection<String> values = map.values();
    Stream<String> stream4 = values.stream();

    Set<Map.Entry<String, String>> entries = map.entrySet();
    Stream<Map.Entry<String, String>> stream5 = entries.stream();


    //把数组转换为Stream流
    Integer[] arr = {1, 2, 3, 4, 5};
    String[] arr2 = {"a", "b", "c"};

    Stream<Integer> stream6 = Stream.of(arr);

    Stream<String> stream7 = Stream.of(arr2);

}
foreach
public static void main(String[] args) {
    Stream<String> stream = Stream.of("a1", "a2", "b1", "c2", "c1");
    stream.forEach(System.out::println);
}
filter

这个就和我们上一个例子是一样的。

map
public static void main(String[] args) {
    Stream<String> stream = Stream.of("1", "2", "3", "4", "5");
    Stream<Integer> stream2 = stream.map(Integer::parseInt);
    stream2.forEach(System.out::println);
}
count
public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);

    long count = list.stream().count();
    System.out.println(count);
}
collect
public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("张三");
    list.add("李四");
    list.add("王五五");

    Stream<String> stream = list.stream().filter(s -> s.length() > 2);

    List<String> collect = stream.collect(Collectors.toList());
    System.out.println(collect);

    Set<Integer> set = new HashSet<>();
    set.add(10);
    set.add(20);
    set.add(30);
    set.add(50);
    Stream<Integer> integerStream = set.stream().filter(s -> s > 20);
    Set<Integer> collect1 = integerStream.collect(Collectors.toSet());
    System.out.println(collect1);

    String[] strArray = {"张三,30", "李四,35", "王五,20"};
    Stream<String> stringStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
    Map<String, Integer> collect2 = stringStream.collect(Collectors.toMap(
            s -> s.split(",")[0],
            s -> Integer.parseInt(s.split(",")[1])
    ));
    System.out.println(collect2);
}
skip
public static void main(String[] args) {
    String[] arr = {"a", "b", "c", "d", "e", "f", "g", "h"};
    Stream<String> arr1 = Stream.of(arr);
    //跳过前三个元素
    arr1.skip(3).forEach(System.out::println);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/537848.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录——二分查找(二)

模版 func binarySearch(nums []int, target int) int {l, r : 0, len(nums)-1for l < r {mid : l (r-l)/2if nums[mid] target {return mid} else if nums[mid] < target {l mid 1} else {r mid}}return -1 }例题 一.第一个错误的版本 代码&#xff1a; func fi…

GPT建模与预测实战

代码链接见文末 效果图&#xff1a; 1.数据样本生成方法 训练配置参数&#xff1a; --epochs 40 --batch_size 8 --device 0 --train_path data/train.pkl 其中train.pkl是处理后的文件 因此&#xff0c;我们首先需要执行preprocess.py进行预处理操作&#xff0c;配置参数…

SpringBoot入门(Hello World 项目)

SpringBoot关键结构 1.2.1 Core Container The Core Container consists of the Core, Beans, Context, and Expression Language modules. The Core and Beans modules provide the fundamental parts of the framework, including the IoC and Dependency Injection featur…

【嵌入式日志调试】嵌入式系统限制打印后使用echo定向到串口节点实现日志输出

背景 系统在启动业务进程时把输出定向到NULL&#xff0c;如./sample > /dev/null&#xff0c;正式版本的系统又是只读系统&#xff0c;不方便开放日志。然后又需要输出日志进行分析问题&#xff0c;系统不支持的情况&#xff0c;只改自己负责的进程实现日志打印 方案 步骤…

书生·浦语大模型实战营之XTuner 微调个人小助手认知

书生浦语大模型实战营之XTuner 微调个人小助手认知 在本节课中讲一步步带领大家体验如何利用 XTuner 完成个人小助手的微调&#xff01; 为了能够让大家更加快速的上手并看到微调前后对比的效果&#xff0c; 用 QLoRA 的方式来微调一个自己的小助手&#xff01; 可以通过下面两…

通过ckeditor组件在vue2中实现上传图片

1&#xff0c;开始实现逻辑前&#xff0c;优先启项目&#xff0c;然后将ckeditor引入&#xff0c;大概如下&#xff1a; 1&#xff0c;npm i ckeditor/ckeditor5-vue2 2&#xff0c;下载sdk&#xff0c;https://ckeditor.com/ckeditor-5/online-builder/#&#xff0c;打开这个地…

Linux——十个槽位,RWX

Linux——RWX 十个槽位 - 表示文件 d 表示文件夹 l 表示软链接 r权&#xff0c;针对文件可以查看文件内容 针对文件夹&#xff0c;可以查看文件夹内容&#xff0c;如ls命令 w权&#xff0c;针对表示可以修改此文件 针对文件夹&#xff0c;可以在文件夹内&#…

只需5分钟,利用Python掌握SQLite3

在数据涌现的今天&#xff0c;数据库已成为生活中不可或缺的工具。Python作为一种流行的编程语言&#xff0c;内置了多种用于操作数据库的库&#xff0c;其中之一就是SQLite。SQLite是一种轻量级的关系型数据库管理系统&#xff0c;它在Python中的应用非常广泛。本文介绍如何使…

如何快速制作问卷?时间省略必备技能

我们可以采用“提出重要问题、简化问题长度、使用调查逻辑、预填答案、避免询问技术性问题、分次调查、问题模块化、增加问题的多样性”等方式来缩短问卷制作的时间。 高回复率对于问卷调查的最终结果至关重要。就像一支强壮而细长的箭头可以走更远的距离一样&#xff0c;清晰而…

matlab 安装 mingw64(6.3.0),OPENEXR

matlab安装openexr 1. matlab版本与对应的mingw版本选择2. mingw&#xff08;6.3.0&#xff09;下载地址&#xff1a;3. matlab2020a配置mingw&#xff08;6.3.0&#xff09;流程“4. matlab 安装openexr方法一&#xff1a;更新matlab版本方法二&#xff1a;其他博文方法方法三…

详解Qt添加外部库

在Qt项目中添加外部库是一项常见任务&#xff0c;无论是静态库还是动态库都需要正确的配置才能让项目顺利编译链接。以下是详细步骤和不同场景下的配置方法&#xff1a; 方法一&#xff1a;手动编辑.pro文件 添加头文件路径&#xff1a; 在Qt项目中的.pro文件中使用INCLUDEPAT…

VsCode 安装Jupyter Notebook

VsCode 安装Jupyter Notebook 安装 1、打开 VSCode 编辑器&#xff0c;点击界面左端的【扩展】栏&#xff1b; 2、在【搜索框】中输入python&#xff0c;点击第一个Python&#xff0c;检查是否已经安装 python 插件&#xff0c;没安装的点击安装&#xff1b;已安装的继续第3步…

AI预测体彩排3第1弹【2024年4月12日预测--第1套算法开始计算第1次测试】

前面经过多个模型几十次对福彩3D的预测&#xff0c;积累了一定的经验&#xff0c;摸索了一些稳定的规律&#xff0c;有很多彩友让我也出一下排列3的预测结果&#xff0c;我认为目前时机已成熟&#xff0c;且由于福彩3D和体彩排列3的玩法完全一样&#xff0c;我认为3D的规律和模…

大文件传输之为啥传输过程中出现宽带不足的情况

在当今数字化时代&#xff0c;大文件传输已成为企业日常运营的关键环节。然而&#xff0c;许多企业在传输大文件时经常面临宽带不足的问题&#xff0c;这不仅影响了工作效率&#xff0c;还可能导致业务机会的丧失。本文将探讨大文件传输过程中宽带不足的原因&#xff0c;以及镭…

目前电视盒子哪个最好?测评工作室盘点超强电视盒子推荐

每年我们会进行数十次电视盒子测评&#xff0c;对各个品牌的产品都有深入的了解&#xff0c;最近我们收到了很多私信不知道目前电视盒子哪个最好&#xff0c;这次我们结合配置总结了五款性能超强的电视盒子推荐给各位&#xff0c;预算足够想买高配电视盒子的朋友们可不要错过啦…

视频评论ID提取工具|视频关键词评论批量采集软件

视频评论ID提取工具&#xff1a;批量抓取视频评论 视频评论ID提取工具是一款功能强大的软件&#xff0c;可以帮助您批量抓取视频视频下的评论信息。通过输入关键词和评论监控词&#xff0c;即可进行评论的抓取&#xff0c;并提供评论昵称、评论日期、评论内容、命中关键词以及所…

机器学习和深度学习 -- 李宏毅(笔记与个人理解)Day 13

Day13 Error surface is rugged…… Tips for training :Adaptive Learning Rate critical point is not the difficult Root mean Square --used in Adagrad 这里为啥是前面的g的和而不是直接只除以当前呢? 这种方法的目的是防止学习率在训练过程中快速衰减。如果只用当前的…

pip install tensorflow-gpu 报错

查阅官网后可知&#xff0c;该命令已经被删除掉了。 tensorflow-gpu PyPI 【解决办法】 我直接安装了其他版本的包 pip install tensorflow-gpu2.10.0 测试 import tensorflow as tfprint("tf.__version__: ", tf.__version__)# print("tf.test.is_gpu_av…

String类(2)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&…

计算机视觉:技术与应用的深度解析

一、引言 计算机视觉&#xff0c;作为人工智能的一个重要分支&#xff0c;旨在通过计算机模拟人类的视觉系统&#xff0c;实现对图像或视频信息的自动分析和理解。随着深度学习、神经网络等技术的快速发展&#xff0c;计算机视觉在各个领域的应用日益广泛&#xff0c;包括安全…