响应式编程一之基础夯实(初学必看!)

响应式编程一之基础夯实(初学必看!)

  • 函数式编程
    • 常见lambda表达式
      • 求一个数组里面的最小值
      • 代码简洁的函数式编程
      • 返回指定对象的接口实例
      • JDK8 新特性
      • jdk8函数式接口
      • predicate 判断hashmap是否为空
      • consumer
      • 总结
      • 方法引用示例
      • lambda表达式的类型推断
      • 变量引用
    • Stream流
      • 内部迭代和外部迭代
      • 中间操作和终止操作
      • Stream流编程-创建流的方式
      • Stream流编程-中间操作
      • Stream流编程-终止操作
      • 并行流
      • 收集器

函数式编程

1、可以不用关注其细节【怎么做】,只需要关注命令即可【做什么】
2、可以使代码更加简洁

常见lambda表达式

求一个数组里面的最小值

public class MinDemo {
    public static void main(String[] args) {
        int[] nums = {12,23,34,78,67,24};
        int min = Integer.MAX_VALUE;
        for(int i : nums){
            if(i < min){
                min = i;
            }
        }
        System.out.println(min);

        // jdk8
        //int的stream流然后在min方法
        int min2 = IntStream.of(nums).min().getAsInt();
        System.out.println(min2);
    }
}

假设数组数据有几亿条数据,那么我们不用函数式编程的思想可能考虑的优化做法为使用多线程,创建一个线程池,然后将数组里面的数据进行拆分,然后采用快排的分治的思想进行解决。【比较麻烦】
而函数式编程则可以使用

   int min2 = IntStream.of(nums).parallel().min().getAsInt();

代码简洁的函数式编程

   new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("命令式编程");
            }
        }).start();
        //函数式编程方式
        new Thread(()-> System.out.println("函数式编程"));

返回指定对象的接口实例

  public static void main(String[] args) {
        Object target1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("命令式编程");
            }
        };
        new Thread((Runnable) target1).start();

        //jdk8
        Object target2 = (Runnable)()-> System.out.println("函数式编程");
        Runnable target3 = ()-> System.out.println("函数式编程");
        System.out.println(target2 == target3);
        new Thread((Runnable) target2).start();
    }
interface Interface1{
    int doubleNum(int i);
    default int add(int x,int y){
        return x + y;
    }
}
public class LambdaDemo1 {
    public static void main(String[] args) {

        Interface1 i1 = (i) -> i*2;
        i1.add(3,7);
        i1.doubleNum(12);

        //这是最常用的一种方式
        Interface1 i2 = i -> i *2;

        Interface1 i3 =(int i) ->  i *2;

        Interface1 i4 = (int i) ->{
            System.out.println("lambda 表达式使用");
            return i *2;
        };

    }
}

JDK8 新特性

1)函数式接口:接口只有一个需要实现的方法(@FunctionalInterface)
可以通过函数式接口将接口尽可能的封装的更细致一些,符合设计模式中的但一职责规范,然后接口与接口之间进行多重继承,抽取一个类把接口都给继承一遍
2)默认方法 通过default修饰

@FunctionalInterface
interface Interface1 {
    int doubleNum(int i);

    default int add(int x, int y) {
        return x + y;
    }
}


public class LambdaDemo1 {
    public static void main(String[] args) {

        Interface1 i1 = (i) -> i * 2;
        i1.add(3, 7);
        i1.doubleNum(12);

        //这是最常用的一种方式
        Interface1 i2 = i -> i * 2;

        Interface1 i3 = (int i) -> i * 2;

        Interface1 i4 = (int i) -> {
            System.out.println("lambda 表达式使用");
            return i * 2;
        };

    }
}

jdk8函数式接口

通过如下代码将money格式化

interface IMoneyFormat{
    String format(int i );
}
class MyMoney{
    private final int money;
    public MyMoney(int money){
        this.money =  money;
    }
    public void printMoney(IMoneyFormat moneyFormat){
        System.out.println("我的存款:" + moneyFormat.format(this.money));
    }

}
public class MoneyDemo {
    public static void main(String[] args) {
        MyMoney me = new MyMoney(999999999);
        me.printMoney(i ->new DecimalFormat(",###").format(i));
 
  }
}

第二种写法用Function

interface IMoneyFormat{
    String format(int i );
}
class MyMoney{
    private final int money;
    public MyMoney(int money){
        this.money =  money;
    }
     public void printMoney(Function<Integer,String> moneyFormat){
        System.out.println("我的存款:" + moneyFormat.apply(this.money));
    }

}
public class MoneyDemo {
    public static void main(String[] args) {
        MyMoney me = new MyMoney(9999999);
          me.printMoney(i -> new DecimalFormat(",###").format(i));
        // 我们学习lambda表达式就可以这样写
     //   Function<Integer,String > moneyFormate=i -> new DecimalFormat("#.###").format(i);
         // 函数接口链式操作
//        me.printMoney(moneyFormate.andThen(s->"人民币" +s));
    }
}

predicate 判断hashmap是否为空

 public static boolean isNullOrEmpty(Map map) {

        //这里需要指定范型,这里是Map,指定好了范型后,方法里面才能用Map对象的方法
        Predicate<Map> predicate = (map1)->{
            if (null == map1 || 0 == map1.size()) {
                System.out.println("map 的 size is 0");
                return true;
            } else {
                return false;
            }
        };
        return predicate.test(map);
    }

    public static void main(String[] args) {
        Map map = new HashMap();
        //使用predicate方法
        System.out.println( isNullOrEmpty(map));
    }

consumer

   //客户需要购物
    public static void shopping(double x, Consumer consumer) {
        consumer.accept(x);
    }

    public static void main(String[] args) {
        Consumer<Double> c1 = (x) -> {
            System.out.println("小李花了" + x + "元,买了一辆车");
        };
        shopping(20000, c1);

        Consumer<Double> c2 = (x) -> {
            System.out.println("小明花了" + x + "元,买了一堆化妆品");
        };
        shopping(50000, c2);
    }

总结

在这里插入图片描述
前五个对应一个输入一个输出,没有输出是消费者,没有输入是生产者。

方法引用示例

import java.util.function.*;

class Dog{
    private String name= "哮天犬";
    private int food =10;

    public static void bark(Dog dog){
        System.out.println(dog +"叫了");
    }

    public Dog (String name){
        this.name = name;
    }
    public Dog ( ){

    }
    @Override
    public String toString() {
        return this.name;
    }

    /**
     * 吃狗粮,静态方法
     * 接下来我们对这成员方法进行成员引用,成员引用套路都是一样的,就是分析他的输入和输出,输入一个int输出一个int
     * @param this  JDK默认会把当前实例传入到非静态方法,参数名为this,位置是第一个
     * @param num
     * @return
     */

    public int eat(Dog this,int num){
        System.out.println("吃了" +num+ "斤狗粮");
        this.food = this.food - num;
        return this.food;
    }
}
public class MethodRefrenceDemo {
    public static void main(String[] args) {
        // 这就是一个lambda表达式,箭头左边是输入参数,箭头右边是函数的执行体
        // 当你的函数执行体里面只有一个函数进行调用,而且函数的参数和传入参数是一样的话,我们就缩写成
       Consumer<String> consumer = s-> System.out.println(s);
       consumer.accept("接收数据1");
        // 方法引用的方式
        Consumer<String> consumer2 = System.out::println;
        consumer2.accept("接受数据");
       //静态方法的方法引用
        Dog dog = new Dog();
        Consumer<Dog> consumer3 = Dog::bark;
        consumer3.accept(dog);

        // 非静态方法,使用对象实例来引用
        Function<Integer,Integer> funtion = dog::eat;
        System.out.println("还剩下" +funtion.apply(2)+ "斤");
        // 演进 1 当输入和输入都是相同类型则可以用一元函数
        UnaryOperator<Integer> unaryOperator = dog::eat;
        System.out.println("还剩下" +unaryOperator.apply(2)+ "斤");
        // 演进2 :因为我们这都是Integer,所以JDK8针对类型也有对应的函数接口
        IntUnaryOperator intUnaryOperator = dog::eat;
        System.out.println("还剩下" +intUnaryOperator.applyAsInt(2)+ "斤");

        // 静态方法和成员方法有一个区别是什么呢?
        // 成员方法可以调用this, 静态方法不能调用this ,那jdk是怎样实现的的,他是在方法里面传递了this
        Dog dog1 = new  Dog();
        dog1.eat(23);

        // 使用类名来方法引用
        BiFunction<Dog,Integer,Integer> eatFunction = Dog::eat;
        System.out.println(eatFunction.apply(dog1,2));

        // 构造函数的方法引用
        // 无构造参数
        // 我们dog里面没有对应的构造方法,我们默认是空的构造方法
        // 这也就是传入是空的,返回一个结果也就生产者
        Supplier<Dog> supplier  = Dog::new;
        System.out.println("创建了新对象:" +supplier.get());
        // 有参数的构造方法
        // 我们这里是和上面一样的,我们的JDK会自动找到有对应参数的
        Function<String,Dog> fun = Dog::new;
        System.out.println(fun.apply("警犬"));


    }
}

lambda表达式的类型推断

之前说过lambda表达式是一个匿名函数,它最后返回来的是实现某个接口的对象。

@FunctionalInterface
interface IMath{
    int add(int x,int y);
}

@FunctionalInterface
interface IMath2{
    int add(int x,int y);
}

public class TypeDemo {
    public static void main(String[] args) {
       // 变量类型定义
       IMath lambda = (x,y) -> x +y;
       // 强转
        Object lambda2 = (IMath) (x,y) -> x + y;
        //通过返回类型
        IMath createLambda = createLambda();
        // 实际我们编写的是后都是在方法里面调用的
        TypeDemo demo = new TypeDemo();
       // demo.test((x,y) ->x +y);
        // 注意:我们这里如果重载的话就会有问题,此时我们可以
        //通过强制类型转化
        demo.test((IMath) (x,y) ->x +y);
    }

    public void test(IMath iMath){

    }
    public void test(IMath2 iMath){

    }
    private static IMath createLambda() {
        return  (x,y) -> x +y;
    }
}

变量引用

consumer是作为值传递的外面定义的变量

/**
 * Lambda表达式是实现某个接口的匿名类,那他引用变量和我们匿名类是相同的
 */
public class VarDemo {
    public static void main(String[] args) {
        //此处默认加了一个final
        String str = "欢迎您";
        //str = "SSS";
        Consumer<String> consumer = s -> System.out.println(s + str);
        consumer.accept("北京");
        // jdk8之前内部类引用外面的变量,这变量必须声明为final类型,
        // 那jdk8里面默认可以不写,他默认增加了final
        // 匿名类引用外面的变量必须是final
        // 因为我们java方法传参的形式,是传的值而不是引用
        List<String> list =new ArrayList<>();
        Consumer<String> consumer2 = s -> System.out.println(s + list);
        consumer.accept("北京");
    }
}

Stream流

内部迭代和外部迭代

     int[] nums = {1,2,3};
        // 外部迭代
        int sum1 = 0;
        for(int i : nums){
            sum1 += i;
        }
        System.out.println("结果为:" + sum1);
        // 使用Stream的内部迭代
        //比较简短
        int sum2 = IntStream.of(nums).sum();
        System.out.println("结果为:" + sum2);

中间操作和终止操作

    public static void main(String[] args) {
        int[] nums = {1,2,3};
        // map 是中间操作 (返回Stream的操作)
        // sum 是终止操作
        int sum3 = IntStream.of(nums).map(StreamDemo1::doubleNum).sum();
        System.out.println("结果为:" + sum3);
        System.out.println("惰性求值就是最终没有调用的情况下,中间操作不会执行");
        //此处不会输出执行了乘以2
        IntStream.of(nums).map(StreamDemo1::doubleNum);
    }
    public static int doubleNum(int i){
        System.out.println("执行了乘以2");
        return i * 2;
    }

Stream流编程-创建流的方式

在这里插入图片描述

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        // 从集合创建流
        list.stream();
        list.parallelStream();

        // 从数组创建流
        Arrays.stream(new int[]{1,2,3,4,5});

        // 创建数字流
        IntStream.of(1,2,3,4);
        IntStream.rangeClosed(1,10);

        //使用random创建一个无限流
        new Random().ints().limit(10);
        Random random = new Random();
        // 自己产生流
        Stream.generate(() -> random.nextInt()).limit(20);

    }

Stream流编程-中间操作

在这里插入图片描述
无状态操作:当前的操作和其他前后的操作无关
有状态操作:当前结果依赖于其他的结果

    String str = "my name is Jack";
        // 把每个单词的长度调用出来
       Stream.of(str.split(" ")).map(s ->s.length()).forEach(System.out::println);
       //筛选出长度大于2的单词
      Stream.of(str.split(" ")).filter(s -> s.length() > 2)
                .map(s -> s.length()).forEach(System.out::println);
        // flatMap A -> B属性(是个集合),最终得到所有的A元素里面的所有B属性集合
        // intStream/longStream 并不是Stream的子类,所以要进行装箱
        Stream.of(str.split(" ")).flatMap(s -> s.chars().boxed() ).forEach(System.out::println);
 Stream.of(str.split(" ")).flatMap(s -> s.chars().boxed()).forEach(
                i -> System.out.println((char)i.intValue()));
//        // peek 用于debug,是中间操作和forEach 是终止操作
        System.out.println("=============peek===============");
        Stream.of(str.split(" ")).peek(System.out::println).forEach(System.out::println);
        // limit 使用,主要用于无限流
        // 1、我们不做限制的看看他是否出现异常,这里没有异常,好像一直不会结束
        new Random().ints().forEach(System.out::println);
        new Random().ints().filter(i -> i > 100 && i < 1000).limit(3)
                .forEach(System.out::println);

Stream流编程-终止操作

在这里插入图片描述

       // 使用并行流,我们打印一下发现是乱序的
        str.chars().parallel().forEach(i -> System.out.print((char)i));
        System.out.println();
//        // 使用 forEachOrdered保证顺序
        str.chars().parallel().forEachOrdered(i -> System.out.print((char)i));
 //第二行:collect/toArray我们可以看到他是一个收集的作用,他可以转成数组或者集合
        // 收集到list
        List<String> list = Stream.of(str.split(" ")).collect(Collectors.toList());
        // 第三个是reduce操作,reduce就是减少的意思,他就是将流合成一个数据,
       //使用reduce拼接字符串
          // 这里返回一个optional 这也是新jdk8添加的, optional是选项的意思,避免自己调用一些空判断,所以我们一般是这样使用
        Optional<String> letters = Stream.of(str.split(" "))
                .reduce((s1, s2) -> s1 + "|" + s2);
        System.out.println(letters.orElse(""));

   // 带初始化值的reduce
        String reduce = Stream.of(str.split(" "))
                .reduce("", (s1, s2) -> s1 + "|" + s2);
        System.out.println(reduce);

  //这就是字符串总长度
       Integer length = Stream.of(str.split(" ")).map(s ->s.length())
                .reduce(0, (s1, s2) -> s1 +  s2);
        System.out.println(length);
    // 使用max
        Optional<String> max = Stream.of(str.split(" ")).max((s1, s2) -> s1.length() - s2.length());
        System.out.println(max.get());
     // 使用findFirst短路操作
        OptionalInt any = new Random().ints().findAny();
        System.out.println(any.getAsInt());

        OptionalInt first = new Random().ints().findFirst();
        System.out.println(first.getAsInt());
    // allMatch
        Student stu1 = new Student( 19, "张三");
        Student stu2 = new Student( 23, "李四");
        Student stu3 = new Student( 28, "王五");
        List<Student> students = new ArrayList<>();
        students.add(stu1);
        students.add(stu2);
        students.add(stu3);
        //判断学生年龄是否都大于18
        boolean flag = students.stream().allMatch(stu -> stu.getAge() > 18);
        System.out.println(flag);

并行流


  public static void debug(int i){
        System.out.println(Thread.currentThread().getName() + "  debug " + i);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void debug2(int i){
        System.out.println("  debug2 " + i);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
     //1、调用 顺序进行调用(串行)
         IntStream.range(1,100).peek(StreamDemo5::debug).count();
        //2、调用 paralled产生一个并行流(并行)
          IntStream.range(1,100).parallel().peek(StreamDemo5::debug).count();
        //3、现在要实现一个这样的效果: 先并行,再串行
        // 多次调用 parallel / sequential 以最后一次为准,下例子是串行的
        IntStream.range(1,100)
                // 调用paralled产生并行流
                .parallel().peek(StreamDemo5::debug)
//                // 调用sequential 产生串行流
                .sequential().peek(StreamDemo5::debug2)
                .count();
        // 4.并行流使用的线程池:ForkJoinPool.commonPool
            IntStream.range(1,100).parallel().peek(StreamDemo5::debug).count();

    public static void debug(int i){
        System.out.println(Thread.currentThread().getName() + "  debug " + i);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
  // 5、我们现在并行流都是用的同一个线程池,那就会有一下问题:
        //  多个并行任务用同一个线程池,就会有排队等待的情况,这时候我们就需要自己创建线程池
        // 防止任务被阻塞
         ForkJoinPool pool = new ForkJoinPool(20);
        pool.submit(() -> IntStream.range(1,100).parallel().peek(StreamDemo5::debug).count());
        // 处理完毕线程池会自动关闭
        pool.shutdown();
        // 我们实现将自己的任务放到自己并行线程池里面,我们测试一下
        // 发现控制台并没有任何日志打印出来
        // 这是因为主线程已经停了,我们线程池是守护线程的关系,所以他也自动退出了,那我们需要让我们的主线程不要退出

        synchronized (pool){
            try {
                pool.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 运行之后发现用的是我们自己的线程池 ForkJoinPool-1

收集器

public class Person {
    private String name;
    private int age;
    private Gender gender;
    private Grade grade;

    public Person(String name, int age, Gender gender, Grade grade) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", grade=" + grade +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Gender getGender() {
        return gender;
    }

    public void setGender(Gender gender) {
        this.gender = gender;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    enum Gender{
        MALE,FEMALE
    }
    enum Grade{
        ONE,TWO,THREE,FOUR;
    }

    public static void main(String[] args) {
        List<Person> peoples = Arrays.asList(
                new Person("小明",10,Gender.MALE,Grade.ONE),
                new Person("小林",12,Gender.FEMALE,Grade.ONE),
                new Person("李刚",13,Gender.MALE,Grade.TWO),
                new Person("小花",14,Gender.MALE,Grade.TWO),
                new Person("小兰",5,Gender.FEMALE,Grade.THREE),
                new Person("天涯",16,Gender.MALE,Grade.ONE),
                new Person("善缘",16,Gender.MALE,Grade.TWO),
                new Person("谷歌",43,Gender.FEMALE,Grade.FOUR),
                new Person("黎明",33,Gender.MALE,Grade.ONE)
        );

        // 1、得到所有学生的年龄列表
        // 或者我们可以转化为:Collectors.toSet() ,或者指定的集合类型:他默认是hashSet我们如果用TreeSet
        // 可以如下:Collectors.toCollection(TreeSet::new )
        List<Integer> ages = peoples.stream().map(s -> s.getAge()).collect(Collectors.toList());
        System.out.println("所有学生的年龄 :" + ages);
       // 1、统计汇总信息
        IntSummaryStatistics ageSummaryStatistics = peoples.stream().collect(Collectors.summarizingInt(Person::getAge));
        System.out.println("年龄汇总:" + ageSummaryStatistics);
        //2、分块
        Map<Boolean, List<Person>> genders = peoples.stream().
                collect(Collectors.partitioningBy(s -> s.getGender() == Gender.MALE));
        //
        //System.out.println( "男女学生列表:" + genders);
        // 上述打印不直观
        MapUtils.verbosePrint(System.out,"男女学生列表",genders);
        // 3、分组
        Map<Grade, List<Person>> grades = peoples.stream()
                .collect(Collectors.groupingBy(Person::getGrade));
        MapUtils.verbosePrint(System.out,"学习班级列表",grades);
        // 4、得到所有班级的个数
        Map<Grade, Long> gradesCount = peoples.stream()
                .collect(Collectors.groupingBy(Person::getGrade,Collectors.counting()));
        MapUtils.verbosePrint(System.out,"班级学生个数列表:",gradesCount);

    }
}

引入pom

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>

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

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

相关文章

解题方式篇-回溯

回溯算法 1、简介 简介&#xff1a;回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。回溯是一种暴力的搜索方式。 回溯法&#xff0c;一般可以解决如下几种问题&#xff1a;组合&#xff08;无序&#xff0…

西南科技大学数字电子技术实验五(用计数器设计简单秒表)预习报告

一、计算/设计过程 说明&#xff1a;本实验是验证性实验&#xff0c;计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程&#xff0c;越详细越好。用公式输入法完成相关公式内容&#xff0c;不得贴手写图片。&#xff08;注意&#xff1a;从抽象公式直接得出结…

Keil 编译输出信息分析:Program size: Code, RO-data , RW-data, ZI-data

一般 MCU 包含的存储空间有&#xff1a;片内 Flash 与片内 RAM&#xff0c;RAM 相当于内存&#xff0c;Flash 相当于硬盘。编译器会将一个程序分类为好几个部分&#xff0c;分别存储在 MCU 不同的存储区。 如图所示&#xff0c;在Keil中编译工程成功后&#xff0c;在下面的Bul…

AI+无代码助力企业供应链优化

内容来自演讲&#xff1a;潘峰 | 预见明日科技&#xff08;北京&#xff09;有限公司 | CEO 摘要 本文介绍了企业供应链中的挑战和解决方案。文章指出&#xff0c;供应链成本占企业经营成本的大部分&#xff0c;且存在供给端和需求端的高度不确定性。为应对这种不确定性&…

Embedding压缩之基于二进制码的Hash Embedding

推荐系统中&#xff0c;ID类特征的表示学习&#xff08;embedding learning&#xff09;是深度学习模型成功的关键&#xff0c;因为这些embedding参数占据模型的大部分体积。这些模型标准的做法是为每一个ID特征分配一个unique embedding vectors&#xff0c;但这也导致存储emb…

【QT 5 调试软件+(Linux下验证>>>>串口相关初试串口)+Windows下qt代码在Linux下运行+参考win下历程+基础样例】

【QT 5 调试软件Linux下验证>>>>串口相关初试串口参考win下历程基础样例】 1、前言2、实验环境3、先行了解4、自我总结-win下工程切到Linux下1、平台无关的代码&#xff1a;2、依赖的库&#xff1a;3、文件路径和换行符&#xff1a;4、编译器差异&#xff1a;5、构…

揭秘高效大型语言模型:技术、方法与应用展望

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在自然语言处理领域取得了显著的进展&#xff0c;如GPT-series(GPT-3, GPT-4)、Google-series(Gemini, PaLM), Meta-series(LLAMA1&2), BLOOM, GLM等模型在各种任务中展现出惊人的能力。然而&#xff0c;随着模…

IDC报告:国内游戏云市场,腾讯云用量规模位列第一

12月12日消息&#xff0c;IDC公布最新的《中国游戏云市场跟踪研究&#xff0c;2022H2》报告&#xff08;以下简称“《报告》”&#xff09;显示&#xff0c;腾讯云凭借全球化节点布局以及国际领先的游戏技术积累&#xff0c;在整体规模、云游戏流路数、CDN流量峰值带宽等多维度…

C++笔记之Delegate和委托构造(Delegating constructor)

C笔记之Delegate和委托构造辨析 code review! —— 杭州 2023-12-10 参考博文&#xff1a;C笔记之文档术语——将可调用对象作为函数参数 文章目录 C笔记之Delegate和委托构造辨析0.有道词典&#xff1a;英语发音1.ChatGPT&#xff1a;delegate概念详解2.Delegate和“将可调…

Python异常、模块和包

Python异常、模块和包 1.了解异常2.异常的捕获方法3.异常的传递4.Python模块5.Python包 1.了解异常 1.1什么是异常 当检测到一个错误是&#xff0c;Python解释器就无法继续执行了&#xff0c;发而出现了一些错误提示&#xff0c;这就是所谓的“异常”&#xff0c;也就是我们常…

橡胶塑料企业网站建设的作用是什么

橡胶塑料产品一般属于大额交易&#xff0c;对企业来说&#xff0c;需要不断提升品牌和拓客&#xff0c;但如今线下信息传播力不足&#xff0c;难以全面呈现内容&#xff0c;需要商家不断提升线上能力&#xff0c;获得进一步发展。 1、品牌宣传展示难 线上没有自己的平台难以将…

HTML---列表.表格.媒体元素

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.列表 无序列表 HTML中的无序列表&#xff08;Unordered List&#xff09;用于显示一组项目&#xff0c;每个项目之前没有特定的顺序或编号。无序列表使用<ul>标签来定义&#xff0c;每…

MTK Android P Sensor架构(一)

需求场景&#xff1a; 本来如果只是给传感器写个驱动并提供能读取温湿度数据的节点&#xff0c;是一件比较轻松的事情&#xff0c;但是最近上层应用的同事要求我们按照安卓标准的流程来&#xff0c;这样他们就能通过注册一个服务直接读取传感器事件数据了。这样做的好处就是第…

初始数据库 - 了解数据库

centos 7 版本当中安装 mysql 安装与卸载中&#xff0c;⽤⼾全部切换成为root&#xff0c;⼀旦 安装&#xff0c;普通⽤⼾是可以使用的。 卸载不需要的环境 首先&#xff0c;在安装之前&#xff0c;要先确定你当前系统当中是否已经有了mysql 的环境&#xff0c;如果你不想卸…

1838_emacs_evil中跳转到任意字符evil-avy-goto-char的功能分析

Grey 全部学习内容汇总&#xff1a;GitHub - GreyZhang/editors_skills: Summary for some common editor skills I used. 1838_emacs_evil中跳转到任意字符evil-avy-goto-char的功能分析 avy是一个比较成熟的emacs的插件&#xff0c;可以实现快速跳转到指定的字符位置的功能…

数据在网络中是怎么传输的?

计算机通信场景大致如下所示&#xff1a; 1.同一个子网中两台计算机通信 2.不属于同一个子网&#xff0c;两台计算机进行通信 以下内容&#xff0c;将围绕这两种场景进行阐述&#xff0c;在阐述之前&#xff0c;先举个场景示例&#xff0c;帮助大家理解一些名词 场景一&…

机器学习---Boosting

1. Boosting算法 Boosting思想源于三个臭皮匠&#xff0c;胜过诸葛亮。找到许多粗略的经验法则比找到一个单一的、高度预 测的规则要容易得多&#xff0c;也更有效。 预测明天是晴是雨&#xff1f;传统观念&#xff1a;依赖于专家系统&#xff08;A perfect Expert) 以“人无…

Reinfocement Learning 学习笔记PartⅠ

文章目录 Reinfocement Learning一、基本概念二、贝尔曼公式&#xff08;bellman equation&#xff09;2.1 为什么return重要2.2 state value function的定义2.3 贝尔曼公式推导2.4 如何求解贝尔曼公式2.5 Action value的定义 三、贝尔曼最优公式&#xff08;bellman optimalit…

HarmonyOS—实现UserDataAbility

UserDataAbility接收其他应用发送的请求&#xff0c;提供外部程序访问的入口&#xff0c;从而实现应用间的数据访问。Data提供了文件存储和数据库存储两组接口供用户使用。 文件存储 开发者需要在Data中重写FileDescriptoropenFile(Uriuri,Stringmode)方法来操作文件&#xf…

在做题中学习(32):只出现一次的数字 III

260. 只出现一次的数字 III - 力扣&#xff08;LeetCode&#xff09; 根据题目可知&#xff1a;有两个元素只出现一次&#xff0c;其余出现两次。 而在只出现一次的数字 I 里&#xff0c;只有一个元素出现一次&#xff0c;可以用异或的方式直接得到最后的答案&#xff0c;而此…