lombok和guava工具

写在前面

本文看下如何通过使用lombok和guava来提高生产力。

1:lombok

我们开发程序时,如read method,write method,tostring,构造函数等,其写法其实都是固定和重复的,因此就可以考虑使用程序自动来生成,无疑,程序开发的效率将会大大提高,而lombok就是来做这个事情的,lombok遵循了jsr269规范,通过提供注解的方式来工作。

1.1:主要注解

  • @getter @setter
    生成read method,write method。
  • @Slf4j
    生成slf4j logger成员变量。
  • @NoArgsConstructor,@AllArgsConstructor
    生成无参构造函数,生成包含所有属性的构造函数。
  • @Builder
    生成构造器。
  • @Data
    相当于@Getter,@Setter,@ToString等注解的组合,慎用!!!
  • @ToString
    生成tostring方法
  • 其它

1.2:使用方式

首先我们需要在idea中下载lombok插件,file-setting-plugins,如下图:

lombok和guava工具_第1张图片

然后需要启动注解处理器,如下:

lombok和guava工具_第2张图片

接着我们就可以在程序中使用了,为了也能够测试日志输出,我们需要准备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=去三里屯拿乒乓球拍子)

2:guava

guava是一个基于jdk的工具类的集合,有google公司开发,程序执行效率高。先引入依赖:

<dependency>
    <groupId>com.google.guavagroupId>
    <artifactId>guavaartifactId>
    <version>29.0-jreversion>
dependency>

看几个例子。

2.1:缓存cache

  • 代码
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 被移除了!!!

2.2:EventBus

以更简单的方式实现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;
    }
}
  • 定义2个订阅者
    通过@Subscriber注解告知回调回调哪个方法,源码如下:
/**
 * @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());
    }
}
  • 测试case
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

通过这种方式可以很简单的实现同一个进程内的模块解耦。

2.3:多值map

即当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]}

2.4:双端map

即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

2.5:其它

源码:

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包(全网最全) 。

你可能感兴趣的:(Java高级开发进阶教程,guava,java,开发语言)