以后要是再写for循环,我就捶自己

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 以后要是再写for循环,我就捶自己

点击上方 **好好学java **,选择 **星标 **公众号


重磅资讯、干货,第一时间送达
今日推荐:干掉 Navicat:这个 IDEA 的兄弟真香!个人原创100W+访问量博客:点击前往,查看更多

** 请 听 题**** **

给定一个字符串元素列表,如下所示:


["1", "2", "bilibili", "of", "codesheep", "5", "at", "BILIBILI", "codesheep", "23", "CHEERS", "6"]

里面有数字型字符串,有字母型字符串;字符串里有大写,也有小写;字符串长度也有长有短

现在要写代码完成一个小功能

我想找出所有 长度>=5的字符串,并且忽略大小写去除重复字符串,然后按字母排序,最后用“爱心❤”连接成一个字符串输出!

哟,就这点需求能难倒我?三分钟之类必搞定!

附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及春招的总结,目前,已经拿到了大厂offer,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

首先我写一个函数,判断输入字符串到底是字母还是数字


publicstaticBoolean isNum( String str ) {
for( int i=0; i<str.length(); i++ ) {
if(!Character.isDigit(str.charAt(i))) {
returnfalse;
}
}
returntrue;
}

接下来我一顿SAO操作:


// 先定义一个具备按字母排序功能的Set容器,Set本身即可去重
Set<String> stringSet = newTreeSet<String>(
newComparator<String>() {
@Override
publicint compare(String o1, String o2) {
return o1.compareTo(o2);  // 按字母顺序排列
}
}
);
// 以下for循环完成元素去重、大小写转换、长度判断等操作
for( int i=0; i<list.size(); i++ ) {
String s = list.get(i);
if( !isNum(s) && s.length()>=5) {
String sLower = s.toLowerCase(); // 统一转小写
        stringSet.add( sLower );
}
}
// 以下for循环完成连词成句
StringBuilder result = newStringBuilder();
for( String s : stringSet ) {
    result.append( s );
    result.append("❤"); // 用“爱心”连接符连接
}
String finalResult = result.substring(0,result.length()-1).toString();  // 去掉最后一个多余连接符
System.out.println( finalResult );

最后输出结果为:


bilibili❤cheers❤codesheep

啪啪啪,打脸

我原以为这个功能我只需要3分钟即可写完并运行出结果,而实际对时我发现我居然花了5分钟。。。 

而且我现在是一看到for循环遍历,我头就痛,上面代码倒还好,假如列表层级变复杂,俄罗斯套娃式的for循环** **谁扛得住。

** 函数式编程,爽!**** **

没错,自Java 8开始,引入了函数式编程范式,这对于咱这种底层劳动密集型码畜来说,简直解放了双手,代码几乎少写一半,从此真正实现编码5分钟,划水2小时

针对上面的作业,用Java 8的 Stream流式操作,仅需一行代码就可以搞定,for循环啥的统统灰飞烟灭。


String result = list.stream()// 首先将列表转化为Stream流
.filter( i -> !isNum(i) )// 首先筛选出字母型字符串
.filter( i -> i.length() >= 5)// 其次筛选出长度>=5的字符串
.map( i -> i.toLowerCase() )// 字符串统一转小写
.distinct()                 // 去重操作来一下
.sorted( Comparator.naturalOrder() ) // 字符串排序来一下
.collect( Collectors.joining("❤") ); // 连词成句来一下,完美!
System.out.println(result);

怎么样,这代码信噪比可以吧

** 言归正传**** **

上面其实已经通过举栗的方式阐述了Java 8函数式编程范式:Stream流 的优雅和强大,尤其在处理集合时,几本一步到位,嘎嘣脆。

当然Stream也仅仅只是Java 8函数式编程接口的一个而已,除了Stream接口,还有其他非常强大的函数式编程接口,比如:

  • Consumer接口- Optional接口- Function接口
    每个接口我们都来举一个好理解的例子,看完保证你难以拒绝!

一、Consumer接口****

顾名思义,它是“消费者的含义”,接受参数而不返回值,举个最最常见的栗子:

平时我们打印字符串,本质也是接受一个参数并打印出来,我们一般想都不想,会这样写:


System.out.println("hello world");     // 打印 hello world
System.out.println("hello codesheep"); // 打印 hello codesheep
System.out.println("bilibili cheers"); // 打印 bilibili cheers

一旦你用了 Consumer之后,总感觉更加优雅一些


Consumer c = System.out::println;
c.accept("hello world");      // 打印 hello world
c.accept("hello codesheep");  // 打印 hello codesheep
c.accept("bilibili cheers");  // 打印 bilibili cheers

而且 Consumer还可以用联用,达到多重处理的效果,比如:


c.andThen(c).andThen(c).accept("hello world");
// 会连续打印 3次:hello world

当然本例只是打印字符串,比较简单,若业务更加复杂, Consumer复用带来的便利性还是不小的。

二、Function接口****

Function接口代表的含义是“函数”,其实和上面的 Consumer有点像,不过 Function既有输入,也有输出,使用更加灵活,举例:

比如我想对一个整数先乘以 2,再计算平方值


Function<Integer,Integer> f1 = i -> i+i;  // 乘以2功能
Function<Integer,Integer> f2 = i -> i*i;  // 平方功能
Consumer c = System.out::println;         // 打印功能
c.accept( f1.andThen(f2).apply(2) );      // 三种功能组合:打印结果 16

别的不说,这个炫技操作还是可以的!

三、Optional接口****

Optional本质是个容器,你可以将你的变量交由它进行封装,这样我们就不用显式对原变量进行 null值检测,防止出现各种空指针异常。举例:

我们想写一个获取学生某个课程考试分数的函数: getScore()


publicInteger getScore( Student student ) {
if( student != null) {      // 第一层 null判空
Subject subject = student.getSubject();
if( subject != null) {  // 第二层 null判空
return subject.score;
}
}
returnnull;
}

这样写倒不是不可以,但我们作为一个“严谨且良心的”后端工程师,这么多嵌套的 if 判空多少有点扎眼!

为此我们必须引入 Optional


publicInteger getScore( Student student ) {
returnOptional.ofNullable(student)
.map( Student::getSubject )
.map( Subject::getScore )
.orElse(null);
}

漂亮!嵌套的if/else判空灰飞烟灭!

** 立个Flag (滑稽)**** **

好啦,本文就抛砖引玉到这里了,大家可以在自己的代码中用函数式编程范式尝试做小规模重构,相信用起来还是非常甜蜜的。

立个Flag,以后写代码,估计我会很少使用for循环了(滑稽),Stream流用起来简直不要太爽啊。。。

开个玩笑,函数式编程范式虽然用起来很爽,但也最好根据实际业务情况来决定是否使用,毕竟大面积的动态范式代码还是挺难看懂和维护的,总之就一句话,理性使用,不要滥用

最后,再附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及春招的总结,目前,已经拿到了大厂offer,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

原文地址:https://sihai.blog.csdn.net/article/details/109465636

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 以后要是再写for循环,我就捶自己


 上一篇
CMS GC——CMS 废弃了,该怎么办呢? CMS GC——CMS 废弃了,该怎么办呢?
点击上方 **好好学java **,选择 **星标 **公众号 重磅资讯、干货,第一时间送达 今日推荐:终于放弃了单调的swagger-ui了,选择了这款神器—knife4j个人原创100W+访问量博客:点击前往,查看更多 转自:涤生
2021-04-04
下一篇 
Spring 和 Spring Boot 之间到底有啥区别? Spring 和 Spring Boot 之间到底有啥区别?
点击上方 **好好学java **,选择 **星标 **公众号 重磅资讯、干货,第一时间送达 今日推荐:干掉 Navicat:这个 IDEA 的兄弟真香!个人原创100W+访问量博客:点击前往,查看更多 作者:乐傻驴 链接:j
2021-04-04