每天学一点之Lambda表达式
Lambda表达式
思想导入:
函数式编程思想: 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。编程中的函数,也有类似的概念,你调用我的时候,给我实参为形参赋值,然后通过运行方法体,给你返回一个结果。对于调用者来做,关注这个方法具备什么样的功能。相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是谁来做。
@Testpublic void test1(){String[] arr = {"hello","java","hi","xiao","yu"};//把上面的字符串按照长短排序,从短到长
// Arrays.sort(arr);//按照编码排序//public static <T> void sort(T[] a, Comparator<? super T> c)Arrays.sort(arr, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {
// return o1.length()-o2.length();return Integer.compare(o1.length(), o2.length());}});/*上面的写法使用了匿名内部类,既声明了一个类,又创建了一个对象。创建这个对象的目的是为了给sort方法的第二个形参c赋值。声明匿名内部类的目的是为了重写public int compare(String o1, String o2)*/System.out.println(Arrays.toString(arr));}//这个需求中我们关心的是什么? 如何比较两个字符串的大小,至于对象不重要Arrays.sort(arr, (o1, o2) -> Integer.compare(o1.length(), o2.length()));System.out.println(Arrays.toString(arr));
做什么,而不是谁来做,怎么做
我们真的希望创建一个匿名内部类对象吗?不。我们只是为了做这件事情而不得不创建一个对象。我们真正希望做的事情是:将compareTo
方法体内的代码传递给sort
方法知晓。
传递一段代码——这才是我们真正的目的。而创建对象只是受限于面向对象语法而不得不采取的一种手段方式。使用Lambda表达式不再有“不得不创建接口对象”的束缚,就是这么简单!
一、函数接口的概念
Lambda表达式其实就是实现SAM接口的语法糖,所谓SAM接口就是Single Abstract Method,即该接口中只有一个抽象方法需要实现,当然该接口可以包含其他非抽象方法(可以包含默认方法,静态方法,也就是实现此接口的子类只要求实现一个方法)。只要满足“SAM”特征的接口都可以称为函数式接口,都可以使用Lambda表达式,但是如果要更明确一点,最好在声明接口时,加上 @FunctionalInterface. 一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。
虽然Iterable和Comparable接口也只有一个抽象方法,但它们没有@FunctionalInterface注解标记,因此不算。
序号 | 接口 | 抽象方法 | SAM接口 |
---|---|---|---|
1 | java.lang.Runnable | public void run() | |
2 | java.util.Comparator | public int compare(T t1, T t2) | |
3 | java.io.FileFilter | public boolean accept(File pathname) | |
4 | java.io.FilenameFilter | public boolean accept(File dir, String name) |
Lambda表达式语法格式
(形参列表) -> {Lambda体}
Lambda表达式的简化
- 当{Lambda体}中只有一句语句时,可以省略{}和{;}
- 当{Lambda体}中只有一句语句时,并且这个语句还是一个return语句,那么{、return、;}三者可以省略。它们三要么一起省略,要么都不省略。
- 当Lambda表达式(形参列表)的类型已知,获取根据泛型规则可以自动推断,那么(形参列表)的数据类型可以省略。
- 当Lambda表达式(形参列表)的形参个数只有一个,并且类型已知或可以自动推断,则形参的数据类型和()可以一起省略,但是形参名不能省略。
- 当Lambda表达式(形参列表)是空参时,()不能省略
二、Java8之后引入的函数式接口
Java8在java.util.function新增了很多函数式接口:主要分为四大类,消费型、供给型、判断型、功能型。
1、消费型接口
有形参,但是返回值类型是void
序号 | 接口名 | 抽象方法 | 描述 |
---|---|---|---|
1 | Consumer | void accept(T t) | 接收一个对象用于完成功能 |
2 | BiConsumer<T,U> | void accept(T t, U u) | 接收两个对象用于完成功能 |
3 | DoubleConsumer | void accept(double value) | 接收一个double值 |
4 | IntConsumer | void accept(int value) | 接收一个int值 |
5 | LongConsumer | void accept(long value) | 接收一个long值 |
6 | ObjDoubleConsumer | void accept(T t, double value) | 接收一个对象和一个double值 |
7 | ObjIntConsumer | void accept(T t, int value) | 接收一个对象和一个int值 |
8 | ObjLongConsumer | void accept(T t, long value) | 接收一个对象和一个long值 |
常用的方法:
public default void forEach(Consumer<? super T> action)
该方法功能是遍历Collection集合,并将传递给action参数的操作代码应用在每一个元素上。
List<String> list = Arrays.asList("java","c","python","c++","VB","C#");list.forEach(s -> System.out.println(s));
2、供给型接口
无参,但是有返回值
序号 | 接口名 | 抽象方法 | 描述 |
---|---|---|---|
1 | Supplier | T get() | 返回一个对象 |
2 | BooleanSupplier | boolean getAsBoolean() | 返回一个boolean值 |
3 | DoubleSupplier | double getAsDouble() | 返回一个double值 |
4 | IntSupplier | int getAsInt() | 返回一个int值 |
5 | LongSupplier | long getAsLong() | 返回一个long值 |
3、判断型接口
有参,但是返回值类型是boolean结果。
序号 | 接口名 | 抽象方法 | 描述 |
---|---|---|---|
1 | Predicate | boolean test(T t) | 接收一个对象 |
2 | BiPredicate<T,U> | boolean test(T t, U u) | 接收两个对象 |
3 | DoublePredicate | boolean test(double value) | 接收一个double值 |
4 | IntPredicate | boolean test(int value) | 接收一个int值 |
5 | LongPredicate | boolean test(long value) | 接收一个long值 |
常用的方法
public default boolean removeIf(Predicate<? super E> filter)
用于删除集合中满足filter指定的条件判断的。
//删除包含o字母的元素list.removeIf(s -> s.contains("o"));
4、功能型接口
既有参数又有返回值
序号 | 接口名 | 抽象方法 | 描述 |
---|---|---|---|
1 | Function<T,R> | R apply(T t) | 接收一个T类型对象,返回一个R类型对象结果 |
2 | UnaryOperator | T apply(T t) | 接收一个T类型对象,返回一个T类型对象结果 |
3 | DoubleFunction | R apply(double value) | 接收一个double值,返回一个R类型对象 |
4 | IntFunction | R apply(int value) | 接收一个int值,返回一个R类型对象 |
5 | LongFunction | R apply(long value) | 接收一个long值,返回一个R类型对象 |
6 | ToDoubleFunction | double applyAsDouble(T value) | 接收一个T类型对象,返回一个double |
7 | ToIntFunction | int applyAsInt(T value) | 接收一个T类型对象,返回一个int |
8 | ToLongFunction | long applyAsLong(T value) | 接收一个T类型对象,返回一个long |
9 | DoubleToIntFunction | int applyAsInt(double value) | 接收一个double值,返回一个int结果 |
10 | DoubleToLongFunction | long applyAsLong(double value) | 接收一个double值,返回一个long结果 |
11 | IntToDoubleFunction | double applyAsDouble(int value) | 接收一个int值,返回一个double结果 |
12 | IntToLongFunction | long applyAsLong(int value) | 接收一个int值,返回一个long结果 |
13 | LongToDoubleFunction | double applyAsDouble(long value) | 接收一个long值,返回一个double结果 |
14 | LongToIntFunction | int applyAsInt(long value) | 接收一个long值,返回一个int结果 |
15 | DoubleUnaryOperator | double applyAsDouble(double operand) | 接收一个double值,返回一个double |
16 | IntUnaryOperator | int applyAsInt(int operand) | 接收一个int值,返回一个int结果 |
17 | LongUnaryOperator | long applyAsLong(long operand) | 接收一个long值,返回一个long结果 |
18 | BiFunction<T,U,R> | R apply(T t, U u) | 接收一个T类型和一个U类型对象,返回一个R类型对象结果 |
19 | BinaryOperator | T apply(T t, T u) | 接收两个T类型对象,返回一个T类型对象结果 |
20 | ToDoubleBiFunction<T,U> | double applyAsDouble(T t, U u) | 接收一个T类型和一个U类型对象,返回一个double |
21 | ToIntBiFunction<T,U> | int applyAsInt(T t, U u) | 接收一个T类型和一个U类型对象,返回一个int |
22 | ToLongBiFunction<T,U> | long applyAsLong(T t, U u) | 接收一个T类型和一个U类型对象,返回一个long |
23 | DoubleBinaryOperator | double applyAsDouble(double left, double right) | 接收两个double值,返回一个double结果 |
24 | IntBinaryOperator | int applyAsInt(int left, int right) | 接收两个int值,返回一个int结果 |
25 | LongBinaryOperator | long applyAsLong(long left, long right) | 接收两个long值,返回一个long结果 |
常用的方法
default void replaceAll(UnaryOperator operator)将该列表的每个元素替换为将该运算符应用于该元素的结果。
//使用Lambda表达式实现Function<T,R>接口的子接口UnaryOperator<T>,// 可以实现将一个字符串首字母转为大写的功能。list.replaceAll(s -> s.substring(0,1).toUpperCase() + s.substring(1));
5、自定义函数式接口
只要确保接口中有且仅有一个抽象方法即可:
修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
}
接口当中抽象方法的 public abstract 是可以省略的
案例:
- 声明一个转换器Convertor<T,R>,包含抽象方法change,可以将参数转换为另一个值,并返回结果。其中T是参数类型,R是返回值类型。
@FunctionalInterface
public interface Convertor<T,R> {R change(T t);
}//使用Lambda表达式实现Convertor接口,实现取字符串的首字母的功能Convertor<String,Character> c1 = (String str)-> {return str.charAt(0);};System.out.println(c1.change("hello"));
三、方法引用与构造器引用
Lambda表达式是可以简化函数式接口的变量与形参赋值的语法。而方法引用和构造器引用是为了简化Lambda表达式的。
当Lambda表达式满足一些特殊的情况时,还可以再简化:
(1)Lambda体只有一句语句,并且是通过调用一个对象的/类现有的方法来完成的
(2)并且Lambda表达式的形参正好全部用上,Lambda体中没有额外的数据参与
序号 | 语法格式 | 场景 |
---|---|---|
1 | 实例对象名::实例方法 | Lambda表达式有多个形参,Lambda体是调用Lambda体外的某个实例对象的实例方法完成,并且Lambda表达式的形参正好依次按顺序作为该方法调用的实参 |
2 | 类名::静态方法 | Lambda表达式有多个形参,Lambda体是调用某个类的静态方法完成,并且Lambda表达式的形参正好依次按顺序作为该方法调用的实参 |
3 | 类名::实例方法 | Lambda表达式只有1个形参,该参数正好Lambda体中调用方法的对象 |
Lambda表达式有多个形参,其中第1个参数正好是Lambda体中调用方法的对象,其余形参正好依次按顺序作为该方法调用的实参 | ||
4 | 类名::new | 当Lambda表达式是一个new表达式,并且Lambda表达式形参正好依次按顺序作为所调用构造器的实参 |
5 | 数组类型名::new | 当Lambda表达式是一个创建数组对象的new表达式,Lambda表达式的形参正好是创建数组的长度 |
List<Integer> list = Arrays.asList(1,3,4,8,9);//list.forEach(t -> System.out.println(t));//用方法引用再简化list.forEach(System.out::println);// File[] subFiles = dir.listFiles(sub->sub.isFile());File[] subFiles = dir.listFiles(File::isFile);//这个需求中我们关心的是什么? 如何比较两个字符串的大小,至于对象不重要
// Arrays.sort(arr, (o1, o2) -> Integer.compare(o1.length(), o2.length()));
// Arrays.sort(arr, Comparator.comparingInt(s->s.length()));Arrays.sort(arr, Comparator.comparingInt(String::length));Arrays.sort(arr, (s1,s2) -> s1.compareToIgnoreCase(s2));//用方法引用简化/** Lambda表达式的形参,第一个(例如:s1),正好是调用方法的对象,剩下的形参(例如:s2)正好是给这个方法的实参*/Arrays.sort(arr, String::compareToIgnoreCase);ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"张三","李四","王五");//用list集合中的姓名,创建一个一个的Student对象
// ArrayList<Student>/* List<Student> result = list.stream().map(name -> new Student(name)) //Function<T,R> R apply(T t).collect(Collectors.toList());*/List<Student> result = list.stream().map(Student::new) //Function<T,R> R apply(T t).collect(Collectors.toList());result.forEach(System.out::println);Optional<Integer> opt1 = Optional.ofNullable(16);
// Optional<String[]> opt2 = opt1.map(len -> new String[len]);Optional<String[]> opt2 = opt1.map(String[]::new);System.out.println(opt2.orElse(new String[0]).length);
四、Optional类
为了解决空指针异常
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。
序号 | 构造器或方法 | 描述 |
---|---|---|
1 | static Optional empty() | 用来创建一个空的Optional |
2 | static Optional of(T value) | 用来创建一个非空的Optional |
3 | static Optional ofNullable(T value) | 用来创建一个可能是空,也可能非空的Optional |
4 | T get() | 返回Optional容器中的对象。要求Optional容器必须非空。T get()与of(T value)使用是安全的 |
5 | T orElse(T other) | 如果Optional容器中非空,就返回所包装值,如果为空,就用orElse(T other)other指定的默认值(备胎)代替。一般orElse(T other) 与ofNullable(T value)配合使用 |
6 | T orElseGet(Supplier<? extends T> other) | 如果Optional容器中非空,就返回所包装值,如果为空,就用Supplier接口的Lambda表达式提供的值代替 |
7 | T orElseThrow(Supplier<? extends X> exceptionSupplier) | 如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException |
8 | boolean isPresent() | 判断Optional容器中的值是否存在 |
9 | void ifPresent(Consumer<? super T> consumer) | 判断Optional容器中的值是否存在,如果存在,就对它进行Consumer指定的操作,如果不存在就不做 |
10 | Optional map(Function<? super T,? extends U> mapper) | 判断Optional容器中的值是否存在,如果存在,就对它进行Function接口指定的操作,如果不存在就不做 |
//其他方法类似
String str = null;Optional<String> opt = Optional.ofNullable(str);
// System.out.println(opt.get());//java.util.NoSuchElementException: No value presentString string = opt.orElse("javaxiaoyu");System.out.println(string); //javaxiaoyu
相关文章:

每天学一点之Lambda表达式
Lambda表达式 思想导入: 函数式编程思想: 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。编程中的函数,也有类似的概念,你调用我的时候,给我实参为形参赋…...

Raft分布式共识算法学习笔记
1. Raft算法 Raft算法属于Multi-Paxos算法,它是在Multi-Paxos思想的基础上,做了一些简化和限制,比如增加了日志必须是连续的,只支持领导者、跟随者和候选人三种状态,在理解和算法实现上都相对容易许多 从本质上说&am…...

中介者模式
介绍 Java中介者模式(Mediator Pattern)是一种行为设计模式,它可以降低多个对象之间的耦合性,通过一个中介者对象来协调这些对象的交互. 在中介者模式中,多个对象之间的交互不是直接进行的,而是通过一个中介者对象来进行的.这个中介者对象封装了对象之间的交互逻辑,每个对象只…...

Kaggle赛题解析:Google手语识别
文章目录一、比赛前言信息二、比赛背景三、比赛任务四、评价指标五、数据描述六、解题思路一、比赛前言信息 比赛名称:Google - Isolated Sign Language Recognition 中文名称:帮助用户从PopSign游戏学习美国手语 比赛链接:https://www.ka…...

什么是ChatGPT?
目录前言一、什么是GPT?二、什么是ChatGPT?三、ChatGPT应用场景四、ChatGPT未来展望五、OpenAI介绍前言 3月3号,早上6:30就有人发消息给我,来问我有关GPT API的事件。 那是因为3月2号,OpenAI 发布了ChatGPT 3.5的开放…...

深入理解Zookeeper的ZAB协议
ZAB是什么ZAB(Zookeeper Atomic Broadcast):Zookeeper原子广播ZAB是为了保证Zookeeper数据一致性而产生的算法(指的是Zookeeper集群模式)。它不仅能解决正常情况下的数据一致性问题,还可以保证主节点发生宕…...

opencv-图像几何处理
缩放 缩放只是调整图像的大小。为此,opencv提供了一个cv2.resize()函数,可以手动指定图像大小,也可以指定缩放因子。你可以使用任意一种方法调整图像的大小: import cv2 from matplotlib import pyplot as pltlogo cv2.imread(…...

[前端笔记030]vue之hello、数据绑定、MVVM、数据代理、事件处理、计算属性和监视属性
前言 本笔记参考视频,尚硅谷:BV1Zy4y1K7SH p1 -p25官网文档完善,本文只做笔记使用,官网下载vue的开发版和生产版或者使用CDN,并去谷歌商店下载开发插件 简介 组件化模式,提高代码复用率,更好维护声明式编…...

每天学一点之注解、元注解
注解 1、注解概述 定义: 注解(Annotation),也叫元数据。与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。 作用分类&#…...

STA环境
目录1. CMOS逻辑门2. 波形3. 时钟3.1. 指定时钟create_clock时钟延迟set_clock_latency 时钟不确定度set_clock_uncertainty 跨时钟域set_false_path3.2. 衍生时钟3.3. 虚拟时钟4. 时序路径2.1. 输入路径2.2. 输出路径2.3. 点对点约束本文介绍在执行静态时序分析(St…...

嵌入式系统实践 12 ——基于ARM汇编 Keil5 MSP432 P401R开发板
物联网实验1 阿里云远程控制小灯 ///****************************************************************************** // * // * MSP432P401 // * ----------------- // * | | // * | |…...

【密码学篇】密码行业标准汇总(GM)
【密码学篇】密码行业标准汇总(GM) 截止到2023年03月10日,共130个密码行业标准,适用商用密码应用与安全性评估等密码行业,可点击链接预览或下载标准—【蘇小沐】 文章目录【密码学篇】密码行业标准汇总(GM…...

桌面文件删除后没有在回收站原因和恢复方法
桌面误删文件回收站也没有怎么办?遇到电脑桌面文件误删了,重要数据回收站找不回这种情况不要慌!如今数据恢复技术很成熟,许多文件丢失问题都能够成功解决。下面我们就一起来了解下桌面误删文件回收站没有的原因和相关文件恢复方法…...

什么是业务运营?关键组成部分有哪些?
企业领导者使用收入运营和智能软件等技术来分析买家的不同接触点。这些见解决定了客户互动的成败,从而改善了业务运营,从而带来了成功。 什么是业务运营? 业务运营包括企业为保持盈利而执行的一系列日常任务。虽然这些任务可能因业务类型或行…...

腾讯云新用户怎么配置服务器的方法教程
腾讯云新用户怎么配置服务器?腾讯云服务器配置选择攻略,先选择云服务器地域和可用区,然后根据用户使用场景需要平衡型、计算型或高IO型等特性来选择云服务器CVM实例规格,主机教程网来详细说下腾讯云服务器配置选择攻略。 1、腾讯云…...

windows 11系统,通过ip地址远程连接连接ubuntu 22.04系统(共同局域网下,另一台主机不需要联网)
windows 11系统,通过ip地址远程连接连接ubuntu 22.04系统(不需要联网)问题来源问题分析解决方案问题来源 自己搭建了一台ubuntu系统作为深度学习的机器,但是学校的网络问题,一个账号只能同时登录3台设备。通过远程连接…...

头脑风暴(一):Controller层前端传参接收;在Service层实现类中?为何要build相关构建器?添加套餐业务分析
文章目录1 MyBatis中Controller层List集合接收数据,泛型添加与否1.1 案例场景1.2 应该用什么接收1.3 是否可以用其他方式接收?1.4 LIst集合接收可否不指定泛型1.5 mybatis中使用基本类型接收数据?resultType是集合中的元素的类型,…...

vue-cropper 拖动图片和截图框
现象 开发遇到vue--cropper不能拖动图片和截图框 解决方法 can-move-box设置为true,表示可以拖动截图框 can-move设置为true,表示可以拖动图片 *注意: 我外层套了一个el-col, el-col的宽高一定要大于截图框的宽高,否则移动不了…...

[Linux基础]history相关的环境变量设置
目录 背景 简介 命令操作 1. 语法: 2. 功能 3. 参数 环境变量设置 背景 工作中时常收到客户的反馈,我的系统什么也没干,就出现文件丢失,程序错误等等问题;我们在问题排查的时候查看history信息也是重要环节…...

怎么给电脑分盘与合并磁盘?教你三招
电脑只有一个C盘,想要再分出一个或多个分区,怎么办?电脑C盘的容量太小,太容易满了,想重新分盘,或者把其他盘跟它合并,但因为文件太多备份实在是太麻烦,怎么办?怎么给电脑…...

HCIP-5.4OSPF路由聚合、缺省路由
1、路由聚合 OSPF 是一种链路状态路由协议,因此 OSPF路由器不传输路由,而是传输链路状态信息。因此,OSPF 路由通过汇总 LSA 来控制链路状态信息的传输,从而减小 LSDB 数据库的大小,进而控制路由的汇总。 由于OSPF路由…...

【数据结构】——树与二叉树
文章目录树二叉树二叉树的性质完全二叉树二叉树的存储遍历二叉树和线索二叉树6.4 树和森林哈夫曼树应用树 树的定义:树是以分支关系定义的层次结构。 D; 树(Tree)是n(n≥0)个结点的有限集。 R 数据关系 有且仅有一个特定的称为根(Root) 的结点 当n>1时&…...

等离子纳秒高压脉冲电源维修HVP-20 P
等离子纳秒高压脉冲电源维修HVP-20 P;HVP-10B;HVP-05;HVP-02等型号均可维修 HVP-20 P(N)用于气体放电与低温等离子体的高性能纳秒高压脉冲电源。 HVP-20P(N)采用专有的marx电路,实现高压脉冲电源参数的便捷可调,包括峰值电压0 – 20 KV (-2…...

JavaScript内改变this指向
之前我们说的都是代码内 this 的默认指向今天我们要来说一下如何能改变 this 指向也就是说, 你指向哪我不管, 我让你指向哪, 你就得指向哪开局在函数的原型( Function.prototype ) 上有三个方法callapplybind既然是在函数的原型上, 那么只要是函数就可以调用这三个方法…...

Cobalt Strike---(2)
数据管理 Cobalt Strike 的团队服务器是行动期间Cobalt Strike 收集的所有信息的中间商。Cobalt Strike 解析来 自它的 Beacon payload 的输出,提取出目标、服务和凭据。 如果你想导出 Cobalt Strike 的数据,通过 Reporting → Export Data 。Cobalt Str…...

docker的命令使用和相关例子
Docker是一种流行的容器化平台,可以帮助开发人员更轻松地构建、发布和管理应用程序。下面是一些Docker的命令使用和相关例子: Docker镜像相关命令: 搜索Docker镜像: docker search 例子:docker search ubuntu 下载D…...

23模式--代理模式
本篇主要聊一些23中模型中的代理模式: 看一下百度百科的解释: 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目…...

【Linux】信号的产生、保存、捕捉处理 (四种信号产生、核心存储、用户态与内核态、信号集及其操作函数)
文章目录1、什么是信号?2、信号的产生2.1 通过键盘产生信号2.2 通过系统调用产生信号2.3 硬件异常产生的信号2.4 由软件条件产生的信号2.5 进程的核心转储3、信号的保存4、信号的捕捉4.1 用户态和内核态4.2 用户态到内核态的切换4.3 信号捕捉过程5、信号集操作函数以…...

redis经典五种数据类型及底层实现
目录一、Redis源代码的核心部分1.redis源码在哪里2.src源码包下面该如何看?二、我们平时说redis是字典数据库KV键值对到底是什么1.6大类型说明(粗分)2.6大类型说明3.上帝视角4.Redis定义了redisObject结构体4.1 C语言struct结构体语法简介4.2 字典、KV是什么4.3 red…...

三十而立却被裁,打工人要如何应对职场危机?
又到金三银四就业季,对于部分职场人来说,年龄成为了他们找工作的最大限制。 因为绝大部分企业招聘中层干部以下岗位的时候,都会要求年龄不超过35周岁,再加上每年千万毕业生涌入社会,竞争程度相当激烈,这就导…...