本文看下如何通过使用lombok和guava来提高生产力。
我们开发程序时,如read method,write method,tostring,构造函数等,其写法其实都是固定和重复的,因此就可以考虑使用程序自动来生成,无疑,程序开发的效率将会大大提高,而lombok就是来做这个事情的,lombok遵循了jsr269规范,通过提供注解的方式来工作。
首先我们需要在idea中下载lombok插件,file-setting-plugins,如下图:
然后需要启动注解处理器,如下:
接着我们就可以在程序中使用了,为了也能够测试日志输出,我们需要准备log4f的日志文件log4j.xml
:
DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' >
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n" />
layout>
appender>
<appender name="file" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="spring01.log" />
<param name="Append" value="true" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
layout>
appender>
<root>
<priority value ="debug"/>
<appender-ref ref="console"/>
<appender-ref ref="file"/>
root>
log4j:configuration>
依赖:
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.12version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.25version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.25version>
dependency>
代码:
@ToString
// @NoArgsConstructor
@AllArgsConstructor
@Slf4j
@Builder
@Getter
@Setter
public class LombokBean {
private int age;
private String name;
// 测试log
public void logMe() {
// 生成的代码为:
// private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LombokBean.class)
log.info(this.name + "log me!!!");
}
}
测试代码:
public class LombokMain {
public static void main(String[] args) {
LombokBean lombokBean = new LombokBean(90, "遇到流氓怎么办?");
System.out.println("toString展示内容:");
System.out.println(lombokBean);
System.out.println("读方法获取信息:");
System.out.println(lombokBean.getAge() + " " + lombokBean.getName());
System.out.println("测试slf4j log");
lombokBean.logMe();
System.out.println("测试构造器Builder");
// 测试构造器
LombokBean lombokBean1 = LombokBean.builder().age(87).name("去三里屯拿乒乓球拍子").build();
System.out.println(lombokBean1);
}
}
运行:
toString展示内容:
LombokBean(age=90, name=遇到流氓怎么办?)
读方法获取信息:
90 遇到流氓怎么办?
测试slf4j log
[09 16:29:50,997 INFO ] [main] lombok.LombokBean - 遇到流氓怎么办?log me!!!
测试构造器Builder
LombokBean(age=87, name=去三里屯拿乒乓球拍子)
guava是一个基于jdk的工具类的集合,有google公司开发,程序执行效率高。先引入依赖:
<dependency>
<groupId>com.google.guavagroupId>
<artifactId>guavaartifactId>
<version>29.0-jreversion>
dependency>
看几个例子。
private static void cacheTest() {
Cache cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(3, TimeUnit.SECONDS)
.removalListener(removalNotification -> System.out.println(removalNotification.getValue() + " 被移除了!!!"))
.build();
cache.put("K1", "V1");
cache.put("K2", "V2");
cache.put("K3", "V3"); // 超出最大容量,会导致k1被删除
cache.invalidate("K3"); // 手动删除
}
运行:
[INFO] --- exec-maven-plugin:3.0.0:exec (default-cli) @ gogogo ---
V1 被移除了!!!
V3 被移除了!!!
以更简单的方式实现JDK的Observer的功能,包括如下几个组件:
1:EventBus
时间总线,通过EventBus发布事件,通过事件类型发布时间到订阅者
2:Event
EventBus发布的内容,订阅者监听,其实就是一个java对象
3:Subscriber
订阅者,订阅EventBus的事件
public class EventBusCenter {
private static EventBus eventBus;
//双重锁单例模式
private static EventBus getEventBus() {
if (eventBus == null) {
synchronized (EventBus.class) {
if (eventBus == null) {
eventBus = new EventBus();
}
}
}
return eventBus;
}
public static void post(Object event) {
getEventBus().post(event);
}
public static void register(Object object) {
getEventBus().register(object);
}
}
/**
* @desc 自定义事件类
**/
public class CustomEvent {
private int data;
public CustomEvent(int data) {
this.data = data;
}
public int getData() {
return this.data;
}
}
/**
* @desc 事件监听 1
**/
public class Subscriber1 {
@Subscribe
public void test1(CustomEvent event) {
System.out.println(Instant.now() + "监听者1-->回调1,收到事件:" + event.getData() + ",线程号为:" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Subscribe
public void test2(CustomEvent event) {
System.out.println(Instant.now() + "监听者1-->回调2,收到事件:" + event.getData() + ",线程号为:" + Thread.currentThread().getName());
}
}
/**
* @desc 事件监听 2
**/
public class Subscriber2 {
@Subscribe
public void test1(CustomEvent event){
System.out.println(Instant.now() +"监听者2-->回调1,收到事件:"+event.getData()+",线程号为:"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Subscribe
public void test2(CustomEvent event){
System.out.println(Instant.now() +"监听者2-->回调2,收到事件:"+event.getData()+",线程号为:"+Thread.currentThread().getName());
}
}
public class EventBusTestCase {
@Test
public void testEventBus() {
Subscriber1 listener1 = new Subscriber1();
Subscriber2 listener2 = new Subscriber2();
// 定义事件
CustomEvent customEvent = new CustomEvent(23);
// 注册订阅者们(监听器们)
EventBusCenter.register(listener1);
EventBusCenter.register(listener2);
// 发布事件
EventBusCenter.post(customEvent);
System.out.println(Instant.now() +",主线程执行完毕:"+Thread.currentThread().getName());
}
}
运行:
2023-07-09T12:48:14.201Z监听者1-->回调2,收到事件:23,线程号为:main
2023-07-09T12:48:14.320Z监听者1-->回调1,收到事件:23,线程号为:main
2023-07-09T12:48:17.320Z监听者2-->回调1,收到事件:23,线程号为:main
2023-07-09T12:48:20.323Z监听者2-->回调2,收到事件:23,线程号为:main
2023-07-09T12:48:20.324Z,主线程执行完毕:main
Process finished with exit code 0
通过这种方式可以很简单的实现同一个进程内的模块解耦。
即当put的key已经存在时,将值转换为集合,程序:
private static void testMap() {
Multimap<Integer,Integer> bMultimap = ArrayListMultimap.create();
List<Integer> list = Lists.newArrayList(4,2,3,5,1,2,2,7,6);
list.forEach(v -> bMultimap.put(v, v + 1));
System.out.println(JSON.toJSONString(bMultimap));
}
运行:
[INFO] --- exec-maven-plugin:3.0.0:exec (default-cli) @ gogogo ---
{1:[2],2:[3,3,3],3:[4],4:[5],5:[6],6:[7],7:[8]}
即key也可以当value,value也可以当key,程序:
private static void testBiMap() {
BiMap<String, Integer> words = HashBiMap.create();
words.put("First", 1);
words.put("Second", 2);
words.put("Third", 3);
System.out.println(words.get("Second").intValue());
System.out.println(words.inverse().get(3));
}
运行:
[INFO] --- exec-maven-plugin:3.0.0:exec (default-cli) @ gogogo ---
2
Third
源码:
private static void other() {
// list转逗号分割字符串
List<String> lists = Lists.newArrayList("a", "b", "g", "8", "9");
String result = Joiner.on(",").join(lists);
System.out.println(result);
String test = "34344,,,34,34,哈哈";
// string 逗号分割 转list
lists = Splitter.on(",").splitToList(test);
// list 转 map 并设置value值
Map<String, String> map1 = Maps.toMap(lists.listIterator(), a -> a + "-value");
System.out.println(JSON.toJSONString(map1));
// 将一个list 分割为多个list的集合,类似分区操作
List<Integer> list = Lists.newArrayList(4, 2, 3, 5, 1, 2, 2, 7, 6);
List<List<Integer>> list1111 = Lists.partition(list, 3);
System.out.println(list1111);
// 创建不可变集合
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("e1", "e2");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");
// map转换为特定规则的字符串
Map<String, Integer> map = Maps.newHashMap();
map.put("xiaoming", 12);
map.put("xiaohong",13);
String result111 = Joiner.on(",").withKeyValueSeparator("=").join(map);
// result为 xiaoming=12,xiaohong=13
System.out.println(result111);
// string转换为map
String str = "xiaoming=11,xiaohong=23";
Map<String,String> map2222 = Splitter.on(",").withKeyValueSeparator("=").split(str);
System.out.println(map2222);
// 判断是整数(断言)
int count = -9;
Preconditions.checkArgument(count > 0, "must be positive: %s", count);
}
运行:
a,b,g,8,9
{"34344":"34344-value","":"-value","34":"34-value","哈哈":"哈哈-value"}
[[4, 2, 3], [5, 1, 2], [2, 7, 6]]
xiaohong=13,xiaoming=12
{xiaoming=11, xiaohong=23}
Exception in thread "main" java.lang.IllegalArgumentException: must be positive: -9
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:190)
一篇让你熟练掌握Google Guava包(全网最全) 。