当前位置: 首页 > 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;都…...

网络基础(二)

目录 应用层 再谈 "协议" 协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的. 如果我们要传输一些"结构化的数据" 怎么办呢? 为什么要转换呢&#xff1f; 如果我们将struct message里面…...

Java线程知识点总结

文章目录Java 线程基础线程简介什么是进程什么是线程进程和线程的区别创建线程ThreadRunnableCallable、Future、FutureTaskCallableFutureFutureTaskCallable Future FutureTask 示例线程基本用法线程休眠线程礼让终止线程守护线程线程通信wait/notify/notifyAlljoin管道线程…...

数据结构——第三章 栈与队列(4)

队列的应用1.基于队列的医院挂号模拟系统2.队列的运用1.基于队列的医院挂号模拟系统 代码实现分享 2.队列的运用 问题描述&#xff1a;某运动会设立N个比赛项目&#xff0c;每个运动成员可以参加1~3个项目。试问如何安排比赛日程&#xff0c;既可以使同一运动员参加的项目不…...

华为机试HJ73-计算日期到天数转换

HJ73 计算日期到天数转换 题目描述&#xff1a; 描述 根据输入的日期&#xff0c;计算是这一年的第几天。 保证年份为4位数且日期合法。 进阶&#xff1a;时间复杂度&#xff1a;O(n) &#xff0c;空间复杂度&#xff1a;O(1) 输入描述&#xff1a; 输入一行&#xff0c;每行…...

【阅读笔记】你不知道的JavaScript--this与对象2

目录this默认绑定隐式绑定隐式丢失显示绑定API 调用上下文new 绑定this 绑定优先级其余绑定例外对象字面量与对象属性描述符迭代器遍历this 默认绑定 默认绑定适配 独立函数调用 默认绑定 this 指向全局对象&#xff1b; 故直接调用函数&#xff0c;该函数内部的 this 即指向全…...

单板TVS接地不当造成辐射骚扰超标问题分析-EMC

【摘要】 某产品EMC辐射骚扰测试超标&#xff0c;通过近远场扫描配合定位分析&#xff0c;逐步找出骚扰源、传播路径&#xff0c;最终通过修改 PCB 走线切断传播路径解决此问题。 1 故障现象 某产品在进行 EMC 研发摸底测试时发现&#xff0c;整机辐射骚扰垂直方向测试超标&a…...

用Python Flask为女朋友做一个简单的网站(附可运行的源码)

&#x1f31f;所属专栏&#xff1a;献给榕榕&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该专栏系为女友准备的&#xff0c;里面会不定时发一些讨好她的技术作品&#xff0c;感兴趣的小伙伴可以关注一下~&#x1f449;文章简介…...

vue3+rust个人博客建站日记5-所有界面

没有数据的前端&#xff0c;是没有灵魂的。明明标题是vue3 rust &#xff0c;但日记撰写至今&#xff0c;似乎只有第一篇提及了Rust&#xff0c;这可不行。是时候一股作气&#xff0c;完成大部分页面绘制工作了&#xff01; 最后再说一次&#xff0c;时间要加速了。 ——普奇神…...

青少年软件编程C++一级真题(202212)

1、输入一个整数x&#xff0c;输出这个整数加1后的值&#xff0c;即x1的值。 时间限制&#xff1a;1000 内存限制&#xff1a;65536 输入 一个整数x&#xff08;0 ≤ x ≤ 1000&#xff09;。 输出 按题目要求输出一个整数。 样例输入 9样例输出 10 #include<iost…...

【Spring】AOP底层原理(动态代理)-》 AOP概念及术语 -》 AOP实现

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ AOP - 面向切面编程一、简述AOP二、AOP底层原理…...