残業や夜更かしのせいでまだハゲてるの?まだ奇妙なニーズに応える車輪を作っていますか?それなら、あなたはぴったりの人を見つけました! !この記事は、プログラマの苦しみを私自身が体験し、舞台裏で血を吐きながらまとめた記事ですので、皆様のお役に立てれば幸いです。行け!行け!行け! !
仕事をうまくやり遂げたいなら、まず自分のツールを磨く必要があります
プログラマー、毎日 私が直面していたのは、コードを書いて自慢することでした。しかし、私はこの 2 つのバランスが取れていないことを常々感じており、毎日コードを書くのに時間がかかりすぎていて、自分を自慢できる時間があまりないのです。みなさんもこんな疑問や疑問を持っていませんか?
プログラマは最も怠惰な生き物であることを私たちは知っています。なぜ!そこで質問は、なぜ釣りをする時間がこれほど少ないのかということです。私たちはそれが上手すぎるでしょうか?いやいやいや、自分を過小評価しないでください。その理由は何でしょうか?
答えは、もちろん、あなたはまだこの記事を読んでいません。この記事は、プログラマの苦しみを私自身が体験し、背中で血を吐きながら記事をまとめたものです。今、皆さんにシェアしています。皆様のお役に立てれば幸いです。
全体プレビュー
JSON 解析ツール
#HTTP ネットワーク リクエスト ツール
##収集処理ツール
ファイル ストリーム処理ツール
暗号化および復号化ツール
#JAVA Bean オブジェクト変換ツール
キャッシュおよび電流制限ツール
はじめに
json
どのくらい一般的であるかについては、これ以上説明する必要はないと思います。使われている解析ツールは開発中です。そうですね、プログラマが日常的に使っているツールとも言えるので、最初に挙げました。見て、まとめて、使ってみましょう、GO!私がよく使う作者は#1. maven import pom 座標
<dependency> <groupid>com.alibaba</groupid> <artifactid>fastjson</artifactid> <version>1.2.83</version> </dependency>
使い方を見てみましょう
##JSON 文字列と
entity オブジェクトの間の変換
// 字符串转对象 Studen student = JSON.parseObject("{"name":"小明","age":18}", Student.class); // 对象转字符串 String str = JSON.toJSONString(student);
// 字符串转JSONObject对象 JSONObject jsonObject = JSONObject.parseObject("{"name":"小明","age":18}"); // JSONObject对象转字符串 String str = jsonObject.toJSONString();ログイン後にコピーJSON String Convert to Collection クラス
// 定义解析字符串 String studentListStr = "[{"name":"小明","age":18},{"name":"小牛","age":24}]"; // 解析为 List<student> List<student> studentList = JSON.parseArray(studentListStr, Student.class); // 定义解析字符串 String studentMapStr = "{"name":"小明","age":18}"; // 解析为 Map<string> Map<string> stringStringMap = JSONObject.parseObject(studentMapStr, new TypeReference<map>>(){});</map></string></string></student></student>ログイン後にコピー
除了 JSON 工具,作为一个优秀的互联网打工人,不学会网络请求,怎么能够在这个行业占有一席之地呢?HTTP 网络请求工具你值得拥有~~ 根据我的个人意愿,我简单介绍 httpclient的用法,因为我对这个比较熟悉
1、maven 导入 pom 坐标
2、如何使用
/** * 无参的 GET 请求 */ public static void noArgsGetHttp() throws IOException { // 定义 httpclient CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 创建 httpGet HttpGet httpGet = new HttpGet("http://www.baidu.com"); // 定义返回结果 CloseableHttpResponse execute = null; // 发送执行 execute = httpClient.execute(httpGet); // 获取返回值 HttpEntity entity = execute.getEntity(); System.out.println("响应状态为:" + execute.getStatusLine()); if (Objects.nonNull(entity)) { System.out.println("响应内容长度为:" + entity.getContentLength()); System.out.println("响应内容为:" + EntityUtils.toString(entity)); } // 释放资源 if (httpClient != null) { httpClient.close(); } if (execute != null) { execute.close(); } }
响应状态为:HTTP/1.1 200 OK 响应内容长度为:-1 响应内容为:
/** * 有参的 GET 请求 */ public static void haveArgsGetHttp() throws IOException, URISyntaxException { // 定义 httpclient CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 创建参数列表 List<namevaluepair> valueParamsList = new ArrayList(); valueParamsList.add(new BasicNameValuePair("studentId","1")); // 创建对应请求 Uri URI uri = new URIBuilder() .setScheme("http") .setHost("localhost") .setPath("/getStudentInfo") .setParameters(valueParamsList) .build(); // 根据 Uri 创建 httpGet HttpGet httpGet = new HttpGet(uri); // 定义返回结果 CloseableHttpResponse execute = null; // 发送执行 execute = httpClient.execute(httpGet); // 获取返回值 HttpEntity entity = execute.getEntity(); System.out.println("响应状态为:" + execute.getStatusLine()); if (Objects.nonNull(entity)) { System.out.println("响应内容长度为:" + entity.getContentLength()); System.out.println("响应内容为:" + EntityUtils.toString(entity)); } // 释放资源 if (httpClient != null) { httpClient.close(); } if (execute != null) { execute.close(); } }</namevaluepair>
/** * post 有参数 */ public static void haveArgsPosthttp() throws IOException { // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的) CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 创建Post请求 HttpPost httpPost = new HttpPost("http://localhost:12345/posttest"); JSONUtil.Student student = new JSONUtil.Student(); student.setName("潘晓婷"); student.setAge(18); String jsonString = JSON.toJSONString(student); StringEntity entity = new StringEntity(jsonString, "UTF-8"); // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中 httpPost.setEntity(entity); httpPost.setHeader("Content-Type", "application/json;charset=utf8"); // 响应模型 CloseableHttpResponse response = httpClient.execute(httpPost); // 从响应模型中获取响应实体 HttpEntity responseEntity = response.getEntity(); System.out.println("响应状态为:" + response.getStatusLine()); if (responseEntity != null) { System.out.println("响应内容长度为:" + responseEntity.getContentLength()); System.out.println("响应内容为:" + EntityUtils.toString(responseEntity)); } // 释放资源 if (httpClient != null) { httpClient.close(); } if (response != null) { response.close(); } }
啊!这样一步一步总结下来好累啊,看到这里的小伙伴们,点一下手里的小赞。嘿嘿~~ 当然我只是简单介绍一下 httpClient 的使用,具体高深的使用方法和配置可以参考其他博主的详细介绍,让我们介绍下一个常用的工具吧。
字符串使我们开发中最常见的类型,也是我们最常需要操作的类型了。如果不知道字符串的常用工具,那在写代码的时候简直就是场灾难!!!
字符串判空,截取字符串、转换大小写、分隔字符串、比较字符串、去掉多余空格、拼接字符串、使用正则表达式等等。
StringUtils 给我们提供了非常丰富的选择。我们着重以本类来介绍使用。
1、导入maven坐标
<dependency> <groupid>org.apache.commons</groupid> <artifactid>commons-lang3</artifactid> <version>3.12.0</version> </dependency>
2、常用方法介绍
(isNotBlank 和 isBlanK)
String str = " "; // 是否不为空 boolean res1 = StringUtils.isNotBlank(str); // 是否为空 boolean res2 = StringUtils.isBlank(str);
(isNotEmpty 和 isEmpty)
String str = " "; // 是否不为空 boolean res1 = StringUtils.isNotEmpty(str); // 是否为空 boolean res2 = StringUtils.isEmpty(str);
优先推荐使用 isBlank 和 isNotBlank 方法,因为 它会把空字符串也考虑进去。
String str2 = "1,2,3"; String[] split = StringUtils.split(str2); System.out.println(Arrays.toString(split));
相较于 String 的 split 方法来说,StringUtils 的 split 方法不会有空指针异常
给定一个字符串,判断它是否为纯数字 可以使用isNumeric方法
String str3 = "1"; boolean numeric = StringUtils.isNumeric(str3); System.out.println(numeric);
当然,这个工具类除了上面简单的三个方法之外们还有其他很多对于我们来说很使用的方法,但是这里就不一一举例了, 有兴趣的小伙伴们可以看源码统计一下
哦吼~~看完了字符串的常用工具,重中之重的集合它来了,如果说没有字符串,我们的程序就无法运行,那么没有集合,我们将会是每天在加班的中度过了,出去后将会自豪的说,老板的车轮胎我也是做了贡献的。
既然集合工具这么重要,那么当然要重点介绍。学会相关工具的使用,真的是能让我们事半功倍的,真的是能让摸鱼时间大大增加的,不信你看看。
它是 JAVA 的集合工具包,内部包括了很多我们常用的方法,下图展示了其中一些,方便食用!
在我们日常开发工作中,经常会遇到一些集合排序的需求。sort 就可以很好的帮助我们做好这一点
List<integer> list = new ArrayList(); list.add(2); list.add(1); list.add(3); //升序 Collections.sort(list); System.out.println(list); //降序 Collections.reverse(list); System.out.println(list);</integer>
结果: [1, 2, 3] [3, 2, 1]
最大值最小值是我们操作集合最常见的方法了吧!!Collections 就有现成的方法帮助我们实现
// 最大值最小值 List<integer> intList = new ArrayList(); intList.add(1); intList.add(2); intList.add(3); Integer max = Collections.max(intList); Integer min = Collections.min(intList); System.out.println("集合元素最大值:" + max); System.out.println("集合元素最小值:" + min);</integer>
结果:集合元素最大值:3 集合元素最小值:1
在多线程状态下,普通集合会产生并发问题,比如 ArrayList 并发添加会产生空值情况,这时我们又不想改动我们之前的集合怎么办? 我们简单的通过Collections 的线程安全转化就可以做到了,简简单单一行代码就可以做到!是不是方便的很!
List<integer> synchronizedList = Collections.synchronizedList(intList);</integer>
当然,Collections 还有很多有用和有趣的方法等着我们去探索,只是只是作为了一个抛转引玉的效果,就不过多的赘述了。
我最常用的便是 CollecionUtils,它是 apache 开源的工具包。它的功能可以说是相当强大的,不信你可以往下看看,反正你能想到的集合操作基本上它都有。
我们最常用的集合方法,没有之一,必须掌握它!!
List<string> stringList = new ArrayList(); boolean notEmpty = CollectionUtils.isNotEmpty(stringList); System.out.println("集合不是空的吗?"+ notEmpty);</string>
集合不是空的吗?false
在开发中,经常需要将多集合进行交并补等的数学操作,不会还是傻傻的子集写循环处理吧!那样还能有摸鱼的时间吗?下面就是大大提升效率的工具!!!
List<integer> list1 = new ArrayList(); list1.add(1); list1.add(2); list1.add(3); List<integer> list2 = new ArrayList(); list2.add(3); list2.add(4); // 获取并集 Collection<integer> union = CollectionUtils.union(list1, list2); System.out.println(union); // 获取交集 Collection<integer> intersection = CollectionUtils.intersection(list1, list2); System.out.println(intersection); //获取交集的补集 Collection<integer> disjunctionList = CollectionUtils.disjunction(list1, list2); System.out.println(disjunctionList); // 获取差集 Collection<integer> subtract = CollectionUtils.subtract(list1, list2); System.out.println(subtract);</integer></integer></integer></integer></integer></integer>
两集合并集: [1, 2, 3, 4]
两集合交集: [3]
两集合交集的补集:[1, 2, 4]
两集合差集: [1, 2]
// 判断两集合是否相等 List<integer> list3 = new ArrayList(); list1.add(3); list1.add(4); List<integer> list4 = new ArrayList(); list2.add(3); list2.add(4); boolean equalCollection = CollectionUtils.isEqualCollection(list3, list4); System.out.println("两集合相等吗?:" + equalCollection);</integer></integer>
两集合相等吗?:true
最后在集合的工具类中再补充一个 google 官方的java包,里面有很多我们想不到的超级方便的小工具,既然是说集合,我们说一下它里面的 Lists 类,也是超级好用的!
相信大家在开发中,都有过初始化集合的需要吧!那么我们一般都是 新建一个 ArrayList 然后一个一个 add 进去,现在告诉大家,不用这么麻烦,一个方法新建带初始化全搞定,真香警告!!
// 快速初始化集合 ArrayList<integer> integers1 = Lists.newArrayList(1, 2, 3); System.out.println(integers1);</integer>
[1, 2, 3]
有时候我们想将我们的大集合分散成为一些小集合,我们又不想手动操作怎么办?这些痛点肯定已经有人帮助我们想好了!!来来来,介绍一下!!
// 数组分页 ArrayList<integer> list7 = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); List<list>> partition = Lists.partition(list7, 5); System.out.println(partition);</list></integer>
[ [1, 2, 3, 4, 5], [6, 7, 8, 9, 10] ]
介绍完了 集合相关的操作类,下面我们也要介绍一下文件流相关操作,这个操作在开发中也是经常用到的。
相信我们在工作已经厌烦了,经常写** IO 流相关的类了吧。经常简单的读取和写入一个文件,我们需要大费周章的去定义一些 InputStream 和 OutputStream **等,感觉有一种杀鸡用牛刀的错觉。 介绍一个文件操作工具类,省去大量操作和关闭行为,超级好用,平常我可是经常用的。
最最常用的操作,怎么样很简单吧,就只用一行代码,秒杀!
// 将 test 写入 test.txt 文件 FileUtils.writeByteArrayToFile(new File("C:\Users\test.txt"), "test".getBytes());
知道了怎么往文件里写东西,他的好兄弟读取我们也得知道啊!
// 读取 test.txt 文件 byte[] bytes = FileUtils.readFileToByteArray(new File("D:\Users\test.txt")); System.out.println("读取到的文本为:" + new String(bytes));
读取到的文本为:test
API 很多,我也不能一一为大家介绍,深入的了解还需要大家去,熟练地运用起来,并且是不是的去看看官方的文档,查漏补缺,相信你也可以见识到很多让你叹为观止的方法。
平常我们经常会遇到比如对用户的密码进行加密 (MD5) ,校验接口的签名 (sha256) 加密等等 用到加密的场景虽然不是很多,但是有这样的工具何乐而不为呢?
因为常用的加密方法并不多,这里介绍两个方法给大家,想知道其他更多用法的伙伴们,去自己探索吧
// MD5 加密 String MD5 = DigestUtils.md2Hex("123"); System.out.println("加密后的结果:" + MD5); // sha(安全哈希算法) 加密 String sha256Hex = DigestUtils.sha256Hex("123"); System.out.println("sha256加密后:" + sha256Hex);
MD5加密后的结果:ef1fedf5d32ead6b7aaf687de4ed1b71
sha256加密后:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e3
说到这里,我们来说一下对象转化的工具,在开发中有些规范,比如DTO、DO、VO等等,之间,如果我们需要转换,单纯的我们要一个一个的 set 值,真是一项苦逼的活。
java bean对象的相关转化,我在这里介绍两个 ,一个 是大家都非常熟悉的 BeanUtils,还有一个就是我平常在开发中经常使用的 MapStruct 和 BeanUtils 最常用的莫过于对象的的拷贝了 。 不过面对需要深拷贝的对象大家要注意了,这里并不推荐大家使用此工具去实现
Student student = new Student(); student.setName("小明"); student.setAge(18); Student newStudent = new Student(); BeanUtils.copyProperties(student,newStudent); System.out.println(newStudent);
Student(name=小明, age=18)
下面我们重点说一下 MapStruct 这个转化,BeanUtils 就是一个大老粗,只能同属性映射,或者在属性相同的情况下,允许被映射的对象属性少。
但当遇到被映射的属性数据类型被修改或者被映射的字段名被修改,则会导致映射失败。而 mapstruct 就是一个巧媳妇儿了。
她心思细腻,把我们可能会遇到的情况都给考虑到了(要是我也能找一个这样的媳妇儿该多好,内心笑出了猪声)
1、首先啥都不用想上来我们先把该导的包导进去
<dependency> <groupid>org.mapstruct</groupid> <!-- jdk8以下就使用mapstruct --> <artifactid>mapstruct-jdk8</artifactid> <version>1.2.0.Final</version> </dependency> <dependency> <groupid>org.mapstruct</groupid> <artifactid>mapstruct-processor</artifactid> <version>1.2.0.Final</version> </dependency>
2、用一下
第一步:定义好我们的基础类
@Data @AllArgsConstructor @NoArgsConstructor public class Student{ private String name; private Integer age ; } @Data @AllArgsConstructor @NoArgsConstructor public class Teacher{ private String name; private Integer age ; }
第二步:接下来定义一个接口,但是注意不需要实现,他就呢能够帮我们转化很神奇的
@Mapper public interface UserCovertToTeacher { UserCovertToTeacher INSTANCE = Mappers.getMapper(UserCovertToTeacher.class); Teacher toCovert(Student student); }
最后一步:在代码中调用,聪明的小伙伴看下面代码,一下就明白了,就是这么简单
Student student = new Student(); student.setName("小明"); student.setAge(18); Teacher teacher = UserCovertToTeacher.INSTANCE.toCovert(student); System.out.println(teacher);
Teacher(name=小明, age=18)
我们介绍了完全两个类字段相同的情况,那么,更加令我们头疼的 有多个字段名字不同但是有对应关系应该怎么搞呢?
我们进阶介绍一下,如何处理这种参数名不同的对应关系 目前假设我们新定义一个微信类,我们的学生要注册到微信上,我们就要将学生对象转化为微信对象
@Data @AllArgsConstructor @NoArgsConstructor static class WeiXin{ private String username; private Integer age ; }
但是我们发现和我们上面的学生类,的名字参数名不同,怎么对应过去的? 答案就是在对方法上配置
@Mapper public interface UserCovertToWeinxin { UserCovertToWeinxin INSTANCE = Mappers.getMapper(UserCovertToWeinxin.class); // 配置字段映射规则 @Mapping(source = "name",target = "username") BeanUtilTest.WeiXin toCovert(BeanUtilTest.Student student); }
Student student = new Student(); student.setName("小明"); student.setAge(18); WeiXin weiXin = UserCovertToWeinxin.INSTANCE.toCovert(student); System.out.println(weiXin);
WeiXin(username=小明, age=18)
这么简单的两个小例子可包含不了 MapStruct这么强大的功能,不管是日期格式化、还是表达式解析、还是深拷贝,都能一一搞定,只是限于本篇文章,无法跟大家说了。想想都很伤心呢! 但是还是那句话,抛砖引玉么!剩下的就交给聪明的小伙伴们了!
最后一小节,我给大家带来我的珍藏,压箱底的东西要拿出来了,大家还不快快点赞收藏,记好,错过了,可就没有下家店了。
我也是在 guava 中发现了很多好用的工具的 首先介绍缓存工具,开发中,我们常用的内存缓存,也就常常是定义一个 Map 去存放,但是单纯的 Map 只能存和取,确无法做到,缓存过期、缓存淘汰,和相关通知等等复杂操作。
我们有必要学习掌握一种工具,能够 Cover 上面所有情况的缓存工具,有需求就有工具类,永远记住。!!!,Cache 登场了,还是老规矩,先看看它怎么用吧。
定义一个简单定时过期的缓存
Cache<string> cache = CacheBuilder.newBuilder() .expireAfterWrite(10, TimeUnit.SECONDS) .build(); // 放入缓存 cache.put("小明","活着"); Thread.sleep(10000); // 从缓存拿取值 System.out.println(cache.getIfPresent("小明"));</string>
null
看到没,结果显而易见,超过了缓存时间,就会自己释放。嘿嘿。
定义一个缓存符合以下限制:
Cache<string> cache = CacheBuilder.newBuilder()、 // 最大容量,超过按照 LRU 淘汰 .maximumSize(100) // 初始容量 .initialCapacity(10) // 并发等级 10 .concurrencyLevel(10) .expireAfterWrite(10, TimeUnit.SECONDS) .build();</string>
两个小例子,大家看明白了没有,真正的干货,还不赶紧用起来。
除了这个,一个限流器也是常常需要的,我们总不能自记去写一个限流器吧,需要考虑的太多,性能还不行哎!那就用接下来介绍的这个工具
限流器大家在并发场景下经常会遇到,最简单的实现限流就是令牌桶算法,原理很简单,但是具体实现是很复杂的,RateLimiter 帮助我们解决这一点,只需要调用简单的 API 就能实现并发限流
定义限流器,每1秒钟通过 1 个请求
RateLimiter rateLimiter = RateLimiter.create(1,1,TimeUnit.SECONDS);
并发两个去获取,看一下结果吧,是不是符合我们的预期
new Thread(()->{ System.out.println("线程 1 获取到执行权限了吗?" + rateLimiter.tryAcquire()); }).start(); new Thread(()->{ System.out.println("线程 2 获取到执行权限了吗?" + rateLimiter.tryAcquire()); }).start();
线程 1 获取到执行权限了吗?true
线程 2 获取到执行权限了吗?false
怎么样,是不是只能有一个通过,简单例子说明问题。 具体用法还得大家在实际开发中具体体会,笔者在这里就不多BB了!!留着时间大家赶快去练习吧。争取成为一个 API 调用高手。
经过上面这么多的讲解、案例和对知识的思考,相信大家已经初步掌握了线程池的使用方法和细节,以及对原理运行流程的掌握, 如果你觉得本文对你有一定的启发,引起了你的思考。 点赞、转发、收藏,下次你就能很快的找到我喽!
(学习视频分享:编程基础视频)
以上が【まとめてシェア】仕事の効率を上げてもう残業をしないための開発ツール8選!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。