当前位置: 首页 > news >正文

函数式编程

函数式编程(一)

文章目录

  • 函数式编程(一)
    • 1. 前言
      • 1.1 概念
    • 2. Lambda 表达式
      • 2.1 概述
      • 2.2 基本的格式
      • 2.3 触发条件
      • 2.4 Lambda表达式
        • 2.4.1 无参无返回值
        • 2.4.2 有参无返回值
        • 2.4.3 无参数有返回值
        • 2.4.4 有参有返回值【重点】
          • 2.4.4.1 比较器接口
          • 2.4.4.2 过滤器接口
          • 2.4.4.3 类转换器接口
        • 2.4.5 总结省略规则
    • 3. Stream 流
      • 3.1 概述
      • 3.2 Stream中常用的方法
      • 3.3 常用的操作
        • 3.3.1 创建流
      • 3.4 常用的操作
        • skip
        • limit
        • count
        • distinct
        • sorted
        • filter
        • map
        • forEach
    • 4. 函数式接口
      • 4.1 概述
      • 4.2 常见的函数式接口
    • 5. 方法引用和构造器引用
      • 构造器的引用

1. 前言

1.1 概念

优点:

  1. 能够读懂公司里面的代码
  2. 大量数据下处理集合的效率比较高
  3. 代码可读性大
  4. 消灭嵌套式的地狱

面向对象:需要关注的用什么东西完成了什么事情,函数式编程的思想实际上就是关注的就是对于数据进行了什么操作。

2. Lambda 表达式

2.1 概述

它主要可以对于一些匿名内部类的写法进行简化,它是函数式编程思想的一个重要的体现,让我们不在关注什么是对象。从而更加清楚的关注对于数据进行了什么操作【返回值】【参数】。

2.2 基本的格式

(临时的变量) -> {执行代码的任务块}

2.3 触发条件

1.8版本以上有效

​ @FunctionalInterface 语法严格要求当下的接口,(有且只能有一个)尚未完成的缺省属性是public abstract 修饰的方法。

​ 函数的接口一般用于方法的增强,直接作为方法的参数,实现插件式编程。

@FunctionalInterface
interface Test{void test();
}

2.4 Lambda表达式

Lambda中,可以将接口的匿名内部类转换成为lambda表达式

2.4.1 无参无返回值

接口

@FunctionalInterface
interface Test{/*** 缺省属性是public abstract*/void test();
}

方法的设计

  /*** 检测lambda表达式** @param test 参数是接口*/public static void testLambda(Test test){System.out.println("检测lambda表达式");}

代码检验

匿名内部类的形式

public class Demo1 {public static void main(String[] args) {/*** 采用的是匿名内部类的方式将接口作为形参传入*/testLambda(new Test() {@Overridepublic void test() {System.out.println("匿名内部类的实现");}});}
}

采用lambda表达式的方式实现匿名内部类

 /*** 采用lambda表达式的分析*   :void方法没有返回值操作**   接口方法返回值是:void*   接口参数是无参数的**   所以lambda表达式是:*   () -> {大括号中无需返回值类型}**/ testLambda(()->{System.out.println("匿名内部类的方式转换成为第一种lambda的表达式");});

对于只有一行的lambda表达式可以将大括号进行省略操作

testLambda(()-> System.out.println("匿名内部类的方式转换成为第一种lambda的表达式"));

2.4.2 有参无返回值

接口

@FunctionalInterface
interface Demo<T>{/*** 采用的是有参无返回值的操作(又称为数据最终处理接口、数据处理方法终止接口,因为当前方法中数据有来无回)** @param t 使用泛型的目的是为了保证数据的多样性,方法中也是用同样的泛型,*          保证数据的一致性*/void test(T t);
}

方法的设计

/*** 方法的设计:对于字符串进行处理操作,但是没有返回值** @param str 指定的字符串* @param demo 已经约束为String类型的接口处理器*/public static void testLambda(String str,Demo<String> demo){demo.test(str);}

实现操作

匿名内部类的使用方式

/*** 1.采用的是匿名内部类的操作的方式进行实现*/testLambda("指定的执行的字符串", new Demo<String>() {@Overridepublic void test(String s) {System.out.println(s+"进行处理操作。(有参数无返回值的操作)");}});

转换成为lambda表达式的方法

/*** 2. 转换成为lambda表达式的方式*      分析:*      针对于接口中的方法:void test(String str)*      接口方法中  有string类型的参数*      返回值:没有返回值***      所以lambda的表达式可以写成*      (s) -> {无返回值的代码}*/
testLambda("lambda表达式的操作",s ->{System.out.println(s+"进行lambda表达式的操作");
});

lambda表达式的优化操作

testLambda("lambda表达式的操作",s -> System.out.println(s+"进行lambda表达式的操作"));

2.4.3 无参数有返回值

接口


@FunctionalInterface
interface TestA<T>{/*** 没有参数,但是有返回值操作,泛型约束是接口对应的返回值接口数据类型,要求按照泛型约束* 返回对应的数据内容** @return 返回一个数据,符合泛型约束*/T get();
}

方法设计

 /*** 作用:当前方法需要返回一个字符串类型的数据** @param test 表示TestA String 数据提供接口对应的参数* @return 字符串数据*/public static String testLambda(TestA<String> test){return test.get();}

实现

public class Demo3 {public static void main(String[] args) {/*** 匿名内部类的使用:匿名内部类的实现是介于方法,接口作为参数的格式,而且接口没有* 所谓意义上的抽象类实现,则可以通过匿名内部类实现。*/String s = testLambda(new TestA<String>() {@Overridepublic String get() {return "作为一个字符串输出操作";}});/*** 因为返回值类型是String类型,所以通过S进行接收,然后进行输出操作*/System.out.println(s);/*** 改进的方案,将匿名内部类转换成为lambda表达式*//*** 匿名内部类的使用规则:*      方法分析:T get();   现在给定的类型是String类型*      有返回值:T 表示的是返回值的类型是泛型*      无参数**       Lambda 格式*         () -> {必须返回一个 String 类型}*             return 关键字出马*/String s1 = testLambda(() -> {return "lambda表达式操作";});/***更为精简的模式:对于只有一句的返回值,我们可以将return进行清除操作*/String s1 = testLambda(() -> "lambda表达式操作");}

2.4.4 有参有返回值【重点】

2.4.4.1 比较器接口

比较器的接口经常用来实现数据的排序操作或者升序或者降序,其中返回的值如果是小于0 的值则左边的大。0表示两者一样大(> return -1 = return 0;)

接口设计

/*** 比较器接口,参数是泛型,用户指定类型*/
@FunctionalInterface
interface Comparator<T>{/*** 比较器接口的方法,参数是泛型类型,用户指定类型** @param o1    用户在使用接口时约束的泛型对应具体数据类型* @param o2    用户在使用接口时约束的泛型对应具体数据类型* @return      如果返回0表示的是,两者相同,否则两者不同*/int comparator(T o1,T o2);
}

方法设计

/*** 使用的是排序的操作,排序的数组是person 类型,排序的规则使用自定义Comparator 接口实现* 接口约束 person 类型** @param arr Person类型的数据* @param com 针对于Person类型数组的Comparator 比较器接口实现*/public static void comparatorArray(Person[] arr,Comparator<Person> com){/*** 采用的核心算法是选择排序的算法操作*/for (int i = 0; i < arr.length - 1; i++) {int index = i;/***   对于比较器中的泛型操作,目前约束的类型是 Person 类型*   当前数组中存储的类型就是Person类型对象,可以作为参数,*   同时利用compare 方法 返回值返回int类型的数据,作为*   排序算法的规则限制。*/for (int j = i + 1; j < arr.length; j++) {if (com.compare(arr[index],arr[j] ) > 0 ){index  = j;}}if (index != i) {Person temp = arr[index];arr[index] = arr[i];arr[i] = temp;}}}

实现

public class Demo {public static void main(String[] args) {/*** 数据的声明赋值部分*/Person[] arr = new Person[5];for (int i = 0; i < arr.length; i++) {int age = (int) (Math.random()*50);arr[i] = new Person("小八嘎",age,"日本");}/*** 匿名内部类比较实现*/comparatorArray(arr, new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {return o1.getAge() - o2.getAge();}});}

lambda表达式的操作

 /*** lambda分析,*      首先方法:*      int compare(T o1,T o2);*      获取泛型之后,泛型的类型是person类型*      返回值的数据类型是int类型**      方法的参数:2个参数*                参数的类型都是Person类型*       最终:*       (o1,o2) -> {所欲要的最重的返回值}*/
comparatorArray(arr, (o1, o2) -> o1.getAge() - o2.getAge());
2.4.4.2 过滤器接口

接口的设计

@FunctionalInterface
interface Predicate<T>{/*** 过滤器接口约束的方法,使用方法参数是用户使用时约束泛型对应具体数据参数*  返回的数据的类型是boolean类型,作用是对条件进行判断,结果反馈** @param t 方法参数是用户使用时约束泛型对应具体数据参数* @return 判断条件,结果反馈*/boolean test(T t);
}

方法的设计

/*** 方法的功能:将传入的参数进行过滤筛查,限定数组的内容,将满足条件的数组,传给一个新的数组* 将新的数组返回。*** @param people 传入的类型数组* @param predicate 过滤器参数* @return 返回过滤后的新的数组*/public static Person[] filterArrayUsing(Person[] people,Predicate<Person> predicate){// 采用的是尾插法操作。//声明一个新的数组Person[] temp = new Person[people.length];int count = 0;for (int i = 0; i < people.length; i++) {/*** 过滤对象提供的方法是test方法,* 通过调用当前的对象,判断当前对象是否满足要求,如果满足存储到新的数组中** 但是现在的比较条件没有确定,通过重写方法来确定*/if (predicate.test(people[i])){temp[count++] = people[i];}}return temp;}

匿名内部类实现操作

    public static void main(String[] args) {/*** 赋值条件*/Person[] array = new Person[5];for (int i = 0; i < array.length; i++) {int age = (int) (Math.random() * 50);array[i] = new Person( "小八嘎", age, "小日本");}/*** 使用内名内部类,重写接口中的方法,将接口中的方法的返回值进行处理*/filterArrayUsing(array, new Predicate<Person>() {@Overridepublic boolean test(Person person) {return person.getAge() > 10;}});}

lambda表达式实现操作

     /*Lambda 分析boolean test(T t); ==> 泛型约束为 Person 类型 ==> boolean test(Person t);方法返回值是 boolean方法参数1. 1 个2. Person 类型Lambda 格式p -> {要求必须返回一个 boolean}*/filterArrayUsing(array, person -> person.getAge() > 10);
2.4.4.3 类转换器接口

接口设计

// 类型转换器接口
//其中的T类型表示的是 当前的数据类型, 其中的R表示的是期望转换成为的类型
@FunctionalInterface
interface Function<T, R> {R apply(T t);	
}

方法设计

    /*** 功能:将传入的字符串数据进行处理操作导入的数据是String 类型的数据,导出的int类型的数据** @param str String类型的数据* @param function 类型转换器接口作为参数导入* @return int 类型的数据*/public static int lambdaTest(String str,Function<String,Integer> function){return function.apply(str);}

实现

  public static void main(String[] args) {String str = "开封有个包青天";int i = lambdaTest(str, new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return s.length();}});System.out.println(i);int j = lambdaTest(str, s -> s.length());System.out.println(j);}

2.4.5 总结省略规则

  1. 小括号内部的参数类型能够省略
  2. 方法体中只有一个返回语句的时候,无论是否存在返回值,其中的return关键字、 大括号、 语句分号 都可以删除,如上所示2.4.3
  3. 方法只有一个参数的时候,小括号也可以省略

3. Stream 流

3.1 概述

​ 从i d k 1.8 之后stream使用的是函数式的编程模式,如同它的名字一样,他可以被用来对集合或者数组进行流水线式的操作,可以方便我们对集合或者数组的操作。

​ stream流操作涉及到数据筛选,排序,转换类型,限制个数,最终处理…并且在处理数据的过程中,对于数据的原始空间没有任何的修改,不影响原始数据。

3.2 Stream中常用的方法

创建Stream对象

// 创建Stream流对象// 集合对象
Stream<T> stream();集合对象调用可以直接获取对应当前集合存储元素的 Stream 流对象。// 数组
Stream<T> Arrays.Stream(T[] t);利用 Arrays 工具类对当前需要按照 Stream 流方式操作的数据进行转换操作,根据当前数组的数据类型和数据存储情况,返回一个对应的 Stream 流对象

Stream中的中间处理方法

Stream<T> skip(long n);限制跳过当前 Stream 流对应元素的个数,【掐头】
Stream<T> limit(long n);限制当前 Stream 对应的元素总个数,【去尾】Stream<T> sorted();对当前 Stream 流存储的进行排序操作,要求元素有自然顺序或者遵从 Comparable 接口,默认【升序】
Stream<T> sorted(Comparator<? super T> com);对当前 Stream 流存储的进行排序操作,排序规则由 Comparator 函数式接口规范Stream<T> filter(Predicate<? super T> pre);判断过滤当前 Stream 流可以保存的数据条件,满足条件保留,不满足条件移除,过滤规则由 Predicate 接口约束Stream<T> distinct();当前 Stream 流中对应的所有元素去重擦操作Stream<R> map(Function<T, R> fun);当前 Stream 存储的数据情况转换为 Function 函数式接口要求的返回值类型,完成类型转换操作。

终止方法

终止方法:Stream流自动关闭,对于Stream流的内存自动被JVM回收

long count();返回当前 Stream 流对应的数据元素个数,为终止方法。void forEach(Consumer<? super T> con);针对于当前 Stream 存储元素的处置方法,为终止方法。<R, A> R collect(Collector<? super T, A, R> collector);Stream 流对应的元素存储内容,转换为用户要求的 集合对象。终止方法常用:Collectors.toList() 目标存储集合类型为 List 集合Collectors.toSet()  目标存储集合类型为 Set 集合Object[] toArray();Stream 流存储的元素内容转换为 Object 类型数组返回

使用方法

ArrayList<String> list = new ArrayList<>();list.add("娃哈哈AD钙奶");
list.add("不二家棒棒糖");
list.add("波力海苔");
list.add("大白兔奶糖");
list.add("双汇王中王中王");
list.add("牛肉干");System.out.println();
list.stream().skip(2).limit(6).filter(s -> s.length() > 4).sorted(Comparator.comparing(String::length)).forEach(System.out::println);

3.3 常用的操作

3.3.1 创建流

  • 单列集合
集合的对象.Stream()Stream<String> stream = list.stream();
Stream<T> stream();集合对象调用可以直接获取对应当前集合存储元素的 Stream 流对象。
  • 数组
Arrays.stream(数组) 或者使用Stream.of来创建arrays.stream或Stream.of将 Arrays Array into a Stream.
  • 双列集合
转换成为单列集合再进行创建Map<String,Integer> map = new HashMap<>();map.put("蜡笔小新",19);map.put("蜡笔小白",22);map.put("日向象养",33);Stream<Map.Entry<String,Integer>> stream = map.entrySet().stream();

3.4 常用的操作

​ 在Stream流中的操作,在不知道如何快速的书写的时候,可以通过使用内名内部类加上IDEA的快速生成lambda表达式的方式实现。

skip

中间操作表示的是跳过当前的前n个元素,返回剩下的元素

list.stream().skip(2) // 跳过当前 Stream 流对应元素的前两个元素.forEach(System.out::println);

limit

中间操作表示的是可以设置流的最大的长度,超出的部分将会被抛弃

strings.stream().skip(2).limit(8)// 表示的是从跳过去的第二个开始,一直到八个位置结束

count

  1. count 是一种处理数据的最终的方法或者是终止的方法,调用该方法,Stream流会自动关闭,对应的Stream流的空间会被JVM自动回收。

  2. 可以用来获取当前流中的元素的个数

  3. 注意:需要进行接收得到的数据,然后输出才能够得到所需的元素。

// stream流的声明操作
Stream<String> strings = list.stream();long count = strings.stream().skip(2).limit(8).filter(s -> s.length() > 2).count();System.out.println(count);

distinct

中间操作可以去除流中的重复的元素

注意该方法依赖的是Object的equals方法来判断是否相同的对象,所以需要注意重写equals方法。

Stream<String> stream = strings.stream();long count = stream.skip(2).limit(8).distinct().filter(s -> s.length() > 2).count();
strings.forEach(System.out::println);
System.out.println(count);

注意

在count方法下面仍然进行调用的操作,会出现异常信息异常信息
stream has already been operated upon or closed
提示告知当前 Stream 已经被关闭!

sorted

中间操作对于流中的数据元素进行排序操作,如果要调用空参的sort方法,需要流中的元素实现了Comparable接口,重写compareTo方法。

Stream<T> sorted(Comparator<? super T> comparator);@FunctionalInterface
public interface Comparator<T> {int compare(T o1, T o2);
}
//当前方法排序所需的条件,排序规则是通过 Comparator 接口提供,数据类型支持数据排序效果,更好!!!Stream sorted();
list.stream().sorted().forEach(System.out::println);
//排序方法局限性很大,只能用于已经有自然顺序或者遵从 Comparable 接口的数据类型。
//如果是针对于对象Person而言,很有可能会出现类型转换异常的情况,如果非要调用只能去实现compareable接口,也就是需要重写compareTo方法,也就是提前将person的数据进行一定的处理。

filter

中间操作可以对于流中间的元素进行条件筛选,符合条件的语句才能够被保留在流中

Stream<T> filter(Predicate<? super T> predicate);@FunctionalInterfacepublic interface Predicate<T> {boolean test(T t);}

检验

//表示的含义是将长度大于2 的保留下来
strings.stream().filter(s -> s.length() > 2)

map

中间操作可以对于流中的数据进行条件筛选过滤,符合筛选条件的才能够保留在流中

//采用内名内部类的方式进行实现操作
stream.skip(2).limit(8).distinct().filter(s -> s.length() > 2).map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return s.length();}}).forEach(s -> System.out.print(s));
strings.forEach(System.out::println);//采用lambda表达式进行操作
.map(s -> s.length())
Stream<Person> stream = list.stream();
Stream<String> stringStream = stream.map(s -> s.toString());
stringStream.forEach(System.out::println);
stream.map(person -> person.getAge()).map(age -> age+10).forEach(System.out::println)

forEach

对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体的操作。终止操作

  Stream<String> stream = strings.stream();stream	.skip(2).limit(8).distinct().filter(s -> s.length() > 2).forEach(s -> System.out.println(s));strings.forEach(System.out::println);

4. 函数式接口

4.1 概述

只有一个抽象方法的接口 我们成为函数接口。JDK的函数式接口上都加上了@FunctionalInterface 注解进行标注,但是无论是否加上该注解,只要接口中只有一个抽象方法,都是函数式接口。

4.2 常见的函数式接口

  • Consumer 消费接口

    根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对于传入的参数进行消费(实际上接口中的方法就是一种有参 无返回值的模式)

    @FunctionalInterface
    public interface Consumer<T>{// t 表示的是与接口约束的泛型一致void accept(T t);
    }
    
  • Function计算转换接口

    采用的是有参数有返回值的操作,函数型接口遵从的是礼尚往来,对于传入的数据进行一个转换处理。

    // 类型转换器接口
    @FunctionalInterface
    interface Function<T, R> {R apply(T t);	
    }
    
  • Suppier 供给型接口

    根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对于传入的参数进行生产(实际上接口中的方法就是一种无参数 有返回值的模式)

    @FunctionalInterface
    public interface Suppier{// t 表示的是与接口约束的泛型一致T get();
    }
    
  • 断定型接口 Predicate

    根据其中的参数的类型,能够看出,传入参数,返回的是boolean类型的数据,经常用于条件的判断

    // 过滤器接口,判断器接口,条件接口
    @FunctionalInterface
    interface Predicate<T> {/*** 过滤器接口约束的方法,方法参数是用户使用时约束泛型对应具体数据参数* 返回值类型是 boolean 类型,用于条件判断,数据过来** @param t 用户约束泛型对应的具体数据类型参数* @return boolean 数据,判断结果反馈*/boolean test(T t);
    }
    

    5. 方法引用和构造器引用

    方法引用: 若lambda表达式中的内容有方法已经实现了,我们可以使用方法引用,可以理解为方法引用是lambda表达式的另外的一种书写的格式。

    使用场景:如果方法体中只有一个方法的调用的话(包括构造方法),我们可以用方法引用进一步简化代码。如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码只是调用了某个类的静态方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个静态方法中,这个时候我们就可以引用类的静态方法。

    格式:对象:: 实例方法名称类 :: 静态方法名称类 :: 实例化方法

    构造器的引用

    格式:类名:: new
    

    使用前提:

    ​ 如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的构造方法,并且我们把要重写的抽象方法中的所有的参数都按照一定的顺序传入了这个构造方法中,这个时候就可以引用构造器

    ------未完结见下章{Stream和Optional}

相关文章:

函数式编程

函数式编程&#xff08;一&#xff09; 文章目录函数式编程&#xff08;一&#xff09;1. 前言1.1 概念2. Lambda 表达式2.1 概述2.2 基本的格式2.3 触发条件2.4 Lambda表达式2.4.1 无参无返回值2.4.2 有参无返回值2.4.3 无参数有返回值2.4.4 有参有返回值【重点】2.4.4.1 比较…...

【Java 类】001-访问修饰符、命名规范

【Java 类】001-访问修饰符、命名规范 文章目录【Java 类】001-访问修饰符、命名规范一、访问修饰符概述1、是什么2、作用作用问题3、访问修饰符有哪些4、作用对象二、访问修饰符使用演示1、类访问修饰符演示第一步&#xff1a;创建 Dog 类&#xff1a;public第二步&#xff1a…...

【C++】命名空间

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言一、命名空间产生的背景二、命名空…...

【AutoSAR】【MCAL】Dio

一、结构 二、功能介绍 DIO&#xff08;数字输入输出&#xff09;驱动模块主要是对端口&#xff08;Port&#xff09;&#xff0c;通道&#xff08;Channel&#xff09;和通道组&#xff08;ChannelGroup&#xff09;进行读写操作。 通道&#xff08;Channel&#xff09;&…...

瑞吉外卖——day2

目录 一、新增员工 二、查询分页数据 三、启用、禁用员工账户、编辑员工信息 一、新增员工 点击左上角新增员工 页面如下&#xff1a; 我们随便填数据 &#xff0c;点击保存&#xff0c;请求的地址如下 返回前端可以看到请求方式为Post 在employeeController中编写对应的代…...

了解java

#常见编程语言介绍 C语言 C语言 java语言 javaScript语言 PHP语言 python语言Object-C和Swift语言 C# &#xff08;c sharp&#xff09;语言 Kotlin语言 Go语言 Basic语言 #JAVA的发展 起源于1991年SUN公司GREEN项目&#xff0c;1996年JDK1.0正式发布 后被Oracle公司收购&…...

【编程实践】代码之中有创意:“我一直认为工程师世界上最具创造性的工作之一”

代码之中有创意 “我一直认为工程师世界上最具创造性的工作之一”。 文章目录 代码之中有创意一、代码可以赋予创造力1.1 代码的创造力1.2 如何发挥代码的创造力二、有创意的代码可以提高工作效率2.1 代码创意可以提高工作效率2.2 如何利用代码创意来提高工作效率三、代码创意可…...

【MySQL】表连接

一、为什么要学习 因为不合理的使用连接会导致慢查询 二、什么是连接 参与连接的表叫做 连接表&#xff0c; 连接就是把 各个连接表 进行的组合 &#xff08;笛卡儿积&#xff09;加入结果集并返回 三、连接查询 如何只是对表进行大量的连接&#xff0c;笛卡儿积作用得到的…...

2023湖南省“楚怡杯”职业技能大赛“网络安全” 项目比赛任务书

2023湖南省“楚怡杯”职业技能大赛“网络安全” 项目比赛任务书2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书A模块基础设施设置/安全加固&#xff08;200分&#xff09;A-1&#xff1a;登录安全加固&#xff08;Windows, Linux&#xff09;A-2&#xff1a;Ngi…...

Android应用启动优化笔记整理

应用启动相关流程与优化 应用启动主要涉及SystemServer进程 和 app进程。 SystemServer进程负责app进程创建和管理、窗口的创建和管理&#xff08;StartingWindow 和 AppWindow&#xff09;、应用的启动流程调度等。 App进程被创建后&#xff0c;进行一系列进程初始化、组件初…...

图像bytes字节串二进制转十六进制及bytes转为图像

目录前言正文二进制与十六进制的bytes互转读取bytes为图像法1:直接写入f.read的结果法2: 转换为PIL或Numpy前言 参考&#xff1a; 8. python基础之基础数据类型–bytes - CSDN python 16进制与图片互转 - CSDN 正文 二进制与十六进制的bytes互转 bytes保存的是原始的字节(二…...

信息安全与数学基础-笔记-②同余

知识目录同余完全剩余系剩余类完全剩余系❀简化剩余系❀欧拉函数逆元&#xff01;欧拉定理 &#xff01;同余 a,b 两个数字&#xff0c;都模m&#xff0c;当两个数字模m后余的数一样即为同余。 例子&#xff1a; a bq r (mod m)&#xff0c;这里的a 和 r 就是同余 &#xff…...

网络安全法

目录正文第一章第二章第三章第四章第五章第六章 法律责任第七章 附则正文 学习网络安全应该知道网络安全法 第一章 总则 第一条: 为了保障网络安全&#xff0c;维护网络空间主权和国家安全、社会公共利益&#xff0c;保护公民、法人和其他组织的合法权益&#xff0c;促进经济…...

django框架开发部署项目

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

Unity记录1.3-入门-第一阶段总结

文章首发及后续更新&#xff1a;https://mwhls.top/4447.html&#xff0c;无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评&#xff0c;非常感谢&#xff01; 汇总&#xff1a;Unity 记录 摘要&#xff1a;第一阶段的总…...

Linux入门篇-文件管理

简介 简单的文件管理。 ⽂件内容的查看 ⽂本⽂件内容的查看 cat ⽂本⽂件的path1 ⽂本⽂件的path2 head ⽂本⽂件的path &#xff0c;显示⽂件的前10⾏内容 head -n 5 ⽂本⽂件的path , 显示⽂件的前5⾏内容 head -5 等于head -n 5tail ⽂本⽂件的path, 显示⽂件的后10⾏内容…...

如何从错误中成长?

在上一篇文章“技术人的犯错成本”里&#xff0c;我和你聊了技术人可能会犯的各式各样的错误&#xff0c;也举了很多例子&#xff0c;说明了技术人犯错的成本。在竞争激烈的互联网时代&#xff0c;试错当然是好事&#xff0c;但了解错误成本&#xff0c;避免不应该犯的错误&…...

谈谈一个程序员的职场心得(真有用)

谈谈一个程序员的职场心得 我会分为三个部分&#xff1a;软件开发&#xff0c;职场协作和认知成长&#xff0c;每个部分精简成 7 条心得。 软件开发 若无必要&#xff0c;勿增实体。 这是奥卡姆剃刀的定义&#xff0c;所谓剃刀就是法则&#xff0c;是奥卡姆这个英国学者提出来…...

Pytest:一个卓有成效的测试工具

大家都知道&#xff0c;目前最流行的Python单元测试框架有三种&#xff0c;分别是unittest, nose和pytest。其中unittest是Python自带的测试框架&#xff0c;但问题是比较老了&#xff0c;赶不上时代发展了&#xff08;哈哈哈&#xff09;&#xff1b;nose2定位是带插件的unitt…...

Compose 动画 (三) : AnimatedVisibility 从入门到深入

1. AnimatedVisibility 是什么 AnimatedVisibility可以实现Compose组件的显示和隐藏&#xff0c;并且可以指定显示/隐藏时候的动画效果。(EnterTransition/ExitTransition) 和 animateXxxAsState、animateContentSize、Crossfade、AnimatedContent 这几个API一起&#xff0c;都…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...