-
第六次 引入泛型
-
简而言之Lambda
-
总结
前言
–
进来给大家八卦一段,看看我自己都去干啥了?话说最近公司接了一个农产品交易网站新项目,因为一段代码重构问题差点和老大干起来,本来以为是老大故意刁难我。最后还是发现是我太菜了???,事情是这个样子滴!
在周例会上,老大告知我们最近接了一个农产品交易平台,主要用于全省农产品线上交易。首当其中,就是要把我们甘肃省的黄河蜜推销出去,我就被安排卖瓜!嗷,不,卖瓜这个功能我负责开发???;很快我设计下面的类来定义瓜 Melon
类:
/**
* 瓜
* @author Milo Lee
* @date 2021-04-07 13:21
*/
public class Melon {
/*品种/
private final String type;
/*重量/
private final int weight;
/*产地/
private final String origin;
public Melon(String type, int weight, String origin) {
this.type = type;
this.weight = weight;
this.origin = origin;
}
// getters, toString()方法省略
}
经过一顿CRUD骚操作,写完了瓜类增删改查工作,交工下班???。
第一次 按类型筛选瓜类
第二天,老大给我提了一个问题,说增加能够按瓜类型对瓜进行过滤。这不很简单吗?于是,于是我创建了一个 Filters
类, 实现了一个filterMelonByType
方法
/**
* @author Milo Lee
* @date 2021-04-07 13:25
*/
public class Filters {
/**
* 根据类型筛选瓜类
* @param melons 瓜类
* @param type 类型
* @return
*/
public static List filterMelonByType(List melons, String type) {
List result = new ArrayList<>();
for (Melon melon: melons) {
if (melon != null && type.equalsIgnoreCase(melon.getType())) {
result.add(melon);
}
}
return result;
}
}
搞定,我们来测试一下
public static void main(String[] args) {
ArrayList melons = new ArrayList<>();
melons.add(new Melon(“羊角蜜”, 1, “泰国”));
melons.add(new Melon(“西瓜”, 2, “三亚”));
melons.add(new Melon(“黄河蜜”, 3, “兰州”));
List melonType = Filters.filterMelonByType(melons, “黄河蜜”);
melonType.forEach(melon->{
System.out.println(“瓜类型:”+melon.getType());
});
}
没毛病,拿给老大看看去,老大看了我的代码说:如果我让你在增加一个按重量筛选瓜类,你打算怎么写?回去考虑一下吧,这家伙不会故意找我茬把????
第二次 按重量筛选瓜类
回到座位的我心想,上次我已经实现了按类型筛选瓜类,那我给他copy
一份改改吧!
如下所示:
/**
* 按照重量过滤瓜类
* @param melons
* @param weight
* @return
*/
public static List filterMelonByWeight(List melons, int weight) {
List result = new ArrayList<>();
for (Melon melon: melons) {
if (melon != null && melon.getWeight() == weight) {
result.add(melon);
}
}
return result;
}
public static void main(String[] args) {
ArrayList melons = new ArrayList<>();
melons.add(new Melon(“羊角蜜”, 1, “泰国”));
melons.add(new Melon(“西瓜”, 2, “三亚”));
melons.add(new Melon(“黄河蜜”, 3, “兰州”));
List melonType = Filters.filterMelonByType(melons, “黄河蜜”);
melonType.forEach(melon->{
System.out.println(“瓜类型:”+melon.getType());
});
List melonWeight = Filters.filterMelonByWeight( melons,3);
melonWeight.forEach(melon->{
System.out.println(“瓜重量:”+melon.getWeight());
});
}
程序员最喜欢的方式,CV搞定,哈哈。但是我发现filterByWeight()
与 filterByType()
非常相似,就是过滤条件不同。我心想,老大不会让我写一个按类型和重量筛选瓜类吧。拿着我的代码去给老大看,果不其然,怕什么来什么???。
第三次 按类型和重量筛选瓜类
为了满足完成老大的任务,我将上面的代码进行了糅合,很快写了如下的代码
/**
* 按照类型和重量来筛选瓜类
* @param melons
* @param type
* @param weight
* @return
*/
public static List filterMelonByTypeAndWeight(List melons, String type, int weight) {
List result = new ArrayList<>();
for (Melon melon: melons) {
if (melon != null && type.equalsIgnoreCase(melon.getType()) && melon.getWeight() == weight) {
result.add(melon);
}
}
return result;
}
老大看了我的代码说,看来你还是没有理解我的意思。假如今天不光我,还有客户继续这样提需求。
那么 Filters
将会有很多这样类似的方法,也就是说写了很多样板代码(代码冗余但又不得不写);
在我们程序员看来,这是不能接受的。如果继续添加新的过滤条件,则代码将变得难以维护且容易出错。你去了解一下lambda表达式
和函数式接口
知识点,再修改一下你的代码。我已经确定了,他就是和我过不去???
第四次 将行为作为参数传递
经过上面的三番折腾。我发现理论上Melon
类的任何属性都有可能作为过滤条件,这样的话我们的Filter
类将会有大量的样板代码,而且有些方法会非常复杂。
其实我们可以发现,我们每写一个方法,都对应一种查询行为,查询行为必然对应一种过滤条件。有没有办法我们写一个方法,将查询行为作为参数传递进去,从而返回我们的结果呢?
那么给它取了一个名字:行为参数化,在下图中进行了说明(左侧显示了我们现在拥有的;右侧显示了我们想要的),有没有发现样板代码会明显减少???
如果我们将过滤条件视为一种行为,那么将每种行为视为接口的实现是非常直观的。经过分析我们发现以上所有这些行为都有一个共同点:过滤条件和boolean
类型的返回 。抽象一个接口如下
public interface MelonPredicate {
boolean test(Melon melon);
}
例如,过滤 黄河蜜可以这样写: HHMMelonPredicate
。
public class HHMMelonPredicate implements MelonPredicate {
@Override
public boolean test(Melon melon) {
return “黄河蜜”.equalsIgnoreCase(melon.getType());
}
}
以此类推,我们也可以过滤一定重量的瓜:
public class WeightMelonPredicate implements MelonPredicate {
@Override
public boolean test(Melon melon) {
return melon.getWeight() > 5000;
}
}
其实熟悉设计模式的同学应该知道这就是:策略设计模式。
主要思想就是让系统在运行时动态选择需要调用的方法。所以我们可以认为 MelonPredicate
接口统一了所有专用于筛选瓜类的算法,并且每种实现都是一种策略,我们也可以把它理解为一种行为。
目前,我们利用策略设计模式,将查询行为进行了抽象。我们还需要一个方法接收 MelonPredicate
参数。于是我定义了 filterMelons()
方法,如下所示:
public static List filterMelons(List melons, MelonPredicate predicate) {
List result = new ArrayList<>();
for (Melon melon: melons) {
if (melon != null && predicate.test(melon)) {
result.add(melon);
}
}
return result;
}
大功告成,测试一下,果然比之前好用多了,再让老大瞅瞅去
List hhm = Filters.filterMelons(melons, new HHMMelonPredicate());
List weight = Filters.filterMelons(melons, new WeightMelonPredicate());
第五次 一次性加了100个过滤条件
就在我沾沾自喜时候,老大又给他泼了一盆冷水。他说你以为我们的平台就买黄河蜜啊,如果前前后后有几十种瓜品种,我给你列出100种过滤条件,你怎么办?
我的心里一万个草泥马在奔腾啊???!老大是不是存心和我过不去啊!虽然经过上次改造,我的代码已经足够灵活,但是如果突然增加100个过滤条件,我仍然需要编写100个策略类来实现 每一个过滤条件。然后我们需要将策略传递给 filterMelons()
方法。
有没有不需要创建这些类的办法那?聪明的我很快发现可以使用java匿名内部类。
如下所示:
List europeans = Filters.filterMelons(melons, new MelonPredicate() {
@Override
public boolean test(Melon melon) {
return “europe”.equalsIgnoreCase(melon.getOrigin());
}
});
虽然向前跨了一大步,但好像无济于事。我还是需要编写大量的代码实现此次需求。设计匿名内部类的目的,就是为了方便 Java 程序员将代码作为数据传递。有时候,匿名内部类看这比较复杂,这时候,我突然想起来老大让我学的lambda表达式,我可以用它来简化
List europeansLambda = Filters.filterMelons(
melons, m -> “europe”.equalsIgnoreCase(m.getOrigin())
);
果然看这帅多了!!!,就这样,我又一次成功完成了任务。我兴冲冲的拿着代码让老大去看看。
第六次 引入泛型
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/bbd88ae4646d0dfab68179c81533828a.jpeg)
总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
-1713565961831)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/bbd88ae4646d0dfab68179c81533828a.jpeg)
总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
[外链图片转存中…(img-zCVDIt2K-1713565961833)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!