枚举的概述
枚举是 Java 中一种特殊的类(类型),它可以定义固定数量的枚举实例(此类的对象),例如: 性别、交通信号灯、季节等等 -> enum
枚举类的对象不是new出来的, 而是一一罗列出来的. -> 数量有限
类的对象只有有限个,确定的
- 星期:Monday(星期一)、… 、Sunday(星期天)
- 性别:Man(男)、Woman(女)
- 季节:Spring (春天)、Summer(夏天)、Autumn(秋天)、Winter(冬天)
- 支付方式:Cash(现金)、WeChatPay(微信)、Alipay(支付宝)、BankCart(银行卡)、CreditCart(信用卡)
- 就职状态:Busy、Free、Vocation、Dimission
- 订单状态:Nonpayment(未付款)、Paid(已付款)、FulFilled(已配货)、Delivered(已发货)、Return(退货)、Checked(已确认)
为什么要使用枚举
假设我们要定义一个人类,人类中包含姓名和性别。通常会将性别定义成字符串类型,效果如下:
public class Person {
private String name;
private String sex;
public Person() {
}
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
// 省略get/set/toString方法
}
public class Demo01 {
public static void main(String[] args) {
Person p1 = new Person("张三", "男");
Person p2 = new Person("张三", "abc"); // 因为性别是字符串,所以我们可以传入任意字符串,但事实上性别只能是‘男’或者‘女’
}
}
不使用枚举存在的问题:可以给性别传入任意的字符串,导致性别是非法的数据,不安全。
问题解决:
//定义一个枚举类型
public enum Gender{
//Sex类中只有2个对象
MALE,//男
FEMALE;//女
}
public class Person {
private String name;
private Gender gender;
public Person() {
}
public Person(String name, Gender gender) {
this.name = name;
this.gender = gender;
}
// 省略get/set/toString方法
}
public class Demo01 {
public static void main(String[] args) {
Person p1 = new Person("张三", Gender.MALE);
Person p2 = new Person("张三", Gender.FAMALE);
}
}
枚举类的使用
枚举的实现方式
- JDK1.5之前需要自定义普通类
- JDK1.5及以后新增的enum关键字用于定义枚举类 -> 枚举从JDK5版本有的
需求: 定义一个方法,方法的参数传递“一年四季中的某一个季节”,根据不同的季节,打印对不同季节的描述
定义枚举类的做法
枚举类的定义:
public enum 类名{
//枚举项的名称全部大写 : 规范
//枚举项都是此类的对象
枚举项1,
枚举项2,
...
枚举项n;
}
枚举对象的使用:
枚举类类名.枚举项;
public enum SeasonEnum {
//这四个枚举项是SeasonEnum枚举类的对象,只有四个!!
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
//通过枚举类 可以这样写
public static void printSeasonByEnum(SeasonEnum seasonEnum){
switch (seasonEnum){
case SPRING:
System.out.println("春暖花开");
break;
case SUMMER:
System.out.println("夏日炎炎");
break;
case AUTUMN:
System.out.println("硕果累累");
break;
case WINTER:
System.out.println("雪花飘飘");
break;
}
}
public static void main(String[] args) {
//使用枚举类,作为方法的参数 printSeasonByEnum(SeasonEnum.AUTUMN); }
案例应用
- 定义枚举:MALE表示男,FEMALE表示女
enum Sex {
MALE, FEMALE; // 男,女
}
- Perosn中的性别有String类型改为Sex枚举类型
public class Person {
private String name;
private Sex sex;
public Person() {
}
public Person(String name, Sex sex) {
this.name = name;
this.sex = sex;
}
// 省略get/set/toString方法
}
- 使用时只能传入枚举中的固定值
public class Demo02 {
public static void main(String[] args) {
Person p1 = new Person("张三", Sex.MALE);
Person p2 = new Person("张三", Sex.FEMALE);
Person p3 = new Person("张三", "abc");//这样写就不可以,只能是固定的枚举类型的对象
}
}
枚举中添加成员变量和成员方法和构造方法
枚举的本质是一个类,所以枚举中还可以有成员变量,成员方法等。
例如:定义一个交通信号灯,分别有红灯,绿灯,黄灯,并对每一个信号灯加以说明: 比如 红灯停,绿灯行,黄灯亮了等一等 ,
public enum Light {
//1.枚举类必须先定义对象 (类似调用类的无参构造器对象 )
RED("红灯停"),GREEN("绿灯行"),YELLOW("黄灯亮了等一等");
//2.在枚举中定义属性 和 方法
String colorDesc;
public String getColorDesc() {
return colorDesc;
}
public void setColorDesc(String colorDesc) {
this.colorDesc = colorDesc;
}
//3.通过构造器给不同的枚举对象传参
private Light(String colorDesc){
this.colorDesc = colorDesc;
}
}
public static void main(String[] args) {
System.out.println(Light.GREEN);
//枚举对象的方法
System.out.println(Light.GREEN.getColorDesc());
//遍历所有的枚举对象 (values() 方法来自父类 Enum类)
Light[] values = Light.values();
for(Light light : values){
System.out.println(light.name() + "---" + light.getColorDesc() );
}
Light light = Light.valueOf("GREEN");
System.out.println("根据字符串返回一个枚举对象:"+light);
}
枚举类的常用方法
常用方法 | 解释 | 返回类型 |
---|---|---|
枚举类.values() | 返回枚举类的所有对象,是一个对象数组 | 对象数组 |
枚举类.valueOf(String) | 根据字符串返回对应的枚举类型 | 枚举类型 |
枚举对象.ordinal() | 返回该对象在枚举类中的序号 | int |
枚举对象.name() | 返回该对象的枚举名称 | Stirng |
函数式接口
函数式接口: 是一个接口中有且仅有一个抽象方法的接口;
只约束了抽象方法的个数 : == 1
没有要求默认方法,静态方法的个数
注解 : @FunctionalInterface
已经学过的函数式接口:
Runnable -> void run()
Callable<T> -> T call()
Comparable<E> -> int compareTo(E o)
Comparator<E> -> int compare(E o1,E o2)
FileFilter -> boolean accept(File filename)
函数式接口是Lambda表达式的使用前提;
面向函数式编程思想
面向过程 : 凡事必躬亲
面向对象 : 自己的事情别人做,懒人思维
1. 创建对象
2. 对象调方法
面向函数 : 基于面向对象的升级
忽略了对象,只关注对象做什么
//省去了子类对象的创建,省去了重写方法的声明格式,全神贯注在重写方法的方法体!
Lambda表达式
Lambda表达式 :
1. 函数式接口是Lambda表达式的使用前提;
2. Lambda表达式运用的编程思想是 面向函数式编程
3. Lambda表达式是对匿名内部类格式的简写 (使用范围没有匿名内部类广)
匿名内部类 :
//适用场景
new 接口/抽象父类/普通父类(){
//接口,抽象父类,普通父类的某个不知类名的子类的类主体
}
Lambda表达式:
//适用场景
new 函数式接口(){
//函数式接口的某个不知类名的子类的类主体
}
能用Lambda的地方一定能用匿名内部类,能用匿名内部类的地方不一定能用Lambda
//Lambda能不能用主要看new的是不是一个函数式接口,如果是就能用!!
Lambda表达式的格式
通用Lambda格式:
(重写方法的形参列表) -> {
重写方法的方法体;
}
简化格式:
1. 当重写方法的方法体内,有且仅有一句代码的时候,可以省略重写方法的
大括号,分号,return关键字
要省都省 ,要不省都不省
2. 所有的方法形参类名可以省略,所有方法形参的名称可以改,改完方法内的变量也要改名字
3. 当形参的个数有且仅有一个的时候 可以省略包裹形参的小括号
方法引用
方法引用 : method reference
Lambda是匿名内部类的简写 -> 必须是函数式接口
方法引用是Lambda表达式的简写
1. 必须满足Lambda的使用条件
2. 要求重写的方法内有且仅有一句代码
3. 这一句话必须是:
a.对象调方法 : 对象名::方法名
b.类名调用静态方法 : 类名::静态方法名
c.创建对象 : 类名::new
d.创建数组 : 数组类型::new
方法引用的大致格式 ::
方法引用案例
@FunctionalInterface
interface InterA{
public abstract void print(String str);
}
@FunctionalInterface
interface InterB{
public abstract int change(String str);
}
@FunctionalInterface
interface InterC{
public abstract Date get();
}
@FunctionalInterface
interface InterD{
public abstract int[] get(int length);
}
Stream流
stream流:对集合的一种新的操作方式
流: 流水线
体验Stream流
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//把集合中所有以"张"开头的元素存储到一个新的集合
ArrayList<String> zhangList = new ArrayList<String>();
for(String s : list) {
if(s.startsWith("张")) {
zhangList.add(s);
}
}
// System.out.println(zhangList);
//把"张"开头的集合中的长度为3的元素存储到一个新的集合
ArrayList<String> threeList = new ArrayList<String>();
for(String s : zhangList) {
if(s.length() == 3) {
threeList.add(s);
}
}
// System.out.println(threeList);
//遍历上一步得到的集合
for(String s : threeList) {
System.out.println(s);
}
进Stream流的方法(进工厂)
1. 单列集合
Stream<E> stream() --> 来自于Collection<E>
2. 数组
static Stream<数组元素类型> stream(一维数组) -->来自于Arrays
3. 一组同类型的数据
static <T> Stream<T> of(T... values) --> 来自于Stream接口
4. 双列集合 不能直接进流
a. 双列集合中 : Set<K> keySet() 获取键集 --> 键集转流
b. 双列集合中 : Collection<V> values() 获取值集 --> 值集转流
c. 双列集合中 : Set<Map.Entry<K,V>> entrySet() 获取键值对集合 --> 键值对集合转流
对数据进行加工的方法(进车间)
过滤车间
Stream接口中的 : Stream<T> filter(Predicate<? super T> predicate)
filter: 方法具备过滤的功能 -> 缺 过滤条件!!
Predicate<? super T> : 判断性接口(函数式接口) -> 提供过滤的条件的!!
抽象方法: boolean test(T t)
跳过车间
Stream接口中的 : Stream<T> skip(long n)
跳过流中的 前 n 个数据 生成新的流对象
截取车间
Stream接口中的 : Stream<T> limit(long maxSize)
保留流中的 前 maxSize 个数据 生成新的流对象
去重车间
Stream接口中的 : Stream<T> distinct()
把流中的重复元素进行去重操作,返回去重后的新流对象 (依照equals方法进行去重)
合并车间
Stream接口中的 : static <T> Stream<T> concat(Stream<T> a, Stream<T> b)
把a流和b流中的数据进行合并,生成新的流对象
转换车间
Stream接口中的 : <R> Stream<R> map(Function<T,R> mapper)
map方法具备转换的能力 -> 缺 如何转换
Function<T,R> 接口 带有转换功能
抽象方法 : R apply(T t)
出流方法(出工厂)
遍历出厂
Stream接口中的 : void forEach(Consumer<? super T> action)
forEach 方法类似循环,循环在遍历流,拿到每个数据 -> 流中数据拿到后,做什么???
Consumer<? super T> 函数式接口 -> 消费性接口
有且仅有一个抽象方法 : void accept(T t) -> 重写后的方法体就是在使用流中数据 t
统计出厂
Stream接口中的 : long count()
统计最终流中有几个元素
收集出厂 ***
<R,A> R collect(Collector<T,A,R> collector)
Collector是一个接口,且接口中不止一个抽象方法,用起来非常的麻烦!!
所以 借助工具类 : Collectors
1. 收集成List集合 -> 元素可重复
static <T> Collector<T,?,List<T>> toList()
2. 收集成Set集合 -> 元素不能重复
static <T> Collector<T,?,Set<T>> toSet()
3. 收集成双列集合 -> 想办法把流中的单列数据转换成键和值???
static Collector toMap(Function<T,K> keyMapper, Function<T,V> valueMapper)
//转成双列集合的时候不允许流中有 重复元素
今天的文章JAVASE23天从入门到精通_Day23分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/31872.html