Guava用法总结

这里抛砖引玉列出Guava一些常用工具类,更多用法请自行挖掘。

1. 缓存

Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。
cache的常用参数:
  1. 缓存最大大小的设置:CacheBuilder.maximumSize(long)
  2. 过期时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)
  3. 引用类型:CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()
  4. 自动刷新cache:CacheBuilder.refreshAfterWrite
  5. 过期时间:CacheBuilder.expireAfterWrite

 LoadingCache cache = CacheBuilder.newBuilder()
                .maximumSize(10).refreshAfterWrite(10, TimeUnit.MINUTES)
                .softValues() //软引用
                .expireAfterWrite(1, TimeUnit.DAYS)
                .build(new CacheLoader() {
                    @Override
                    public BigDecimal load(String key) throws Exception {
                        return new BigDecimal(0);
                    }
                });

2.字符串处理

  • 2.1 拼接

Joiner 可以快速地把多个字符串或字符串数组连接成为用特殊符号连接的字符串。

  List list = Lists.newArrayList("a","b","c");
  String value =Joiner.on("-").skipNulls().join(list);
  System.out.println(value);
 //输出为: a-b-c
  • 2.2 分割
    Splitter用来分割字符串
  String testString = "Monday,Tuesday,,Thursday,Friday,,";
  //英文分号分割;忽略空字符串
  Splitter splitter = Splitter.on(",").omitEmptyStrings().trimResults();
  System.out.println(splitter.split(testString).toString());
  //转换为了:[Monday, Tuesday, Thursday, Friday]
  • 2.3 匹配
    CharMatcher常用来从字符串里面提取特定字符串。
    比如想从字符串中得到所有的数字.
String value = CharMatcher.DIGIT.retainFrom("some text 2046 and more");
//value=2046

3.集合

  • 3.1 集合创建
    各种以S结尾的工厂类简化了集合的创建。在创建泛型实例的时候,它们使代码更加简洁
List<String> list =Lists.newArrayList();
List<String> list2 = Lists.newArrayList("a","b","c");
Set<Integer> set = Sets.newHashSet();

类型推导的功能,在Java 7中已经得到支持。

Map<String,List<String>> m=new HashMap<>();

可以返回原返回类型的任何子类型的对象

Maps.newHashMap();
Maps.newLinkedHashMap();
  • 3.2 集合转换、查找、过滤、分割
    Lists.transform可以很方便将一个集合转换成另外一种类型的集合。
 List listStr = Lists.newArrayList("1", "2", "3");
 //将字符串集合转换为Integer集合
 List listInteger = Lists.transform(listStr, new Function() {
            @Nullable
            @Override
            public Integer apply(@Nullable String s) {
                return Integer.valueOf(s);
            }
        });

在Java 8中的实现为

  List listInteger2 = listStr.stream().map(Integer::valueOf).collect(Collectors.toList());

Iterables.find查找集合首个匹配的元素


        List<String> listStr = Lists.newArrayList("hello", "world", "hehe");
        //查找首个以h开头的值    
        String value = Iterables.find(listStr, new Predicate<String>() {
            @Override
            public boolean apply(String input) {
                return input.startsWith("h");
            }
        });

在Java 8中的实现为

 String value2 = listStr.stream().findFirst().filter(input -> input.startsWith("h")).get();

Collections2.filter过滤集合中所有符合特定条件的元素。

   List listWithH = Lists.newArrayList(Collections2.filter(listStr, new Predicate() {
            @Override
            public boolean apply(@Nullable String s) {
                return s.startsWith("h");
            }
        }));

在Java 8中的实现为

List listWithH2 = listStr.stream().filter(input -> input.startsWith("h")).collect(Collectors.toList());

Lists.partition可以将一个大的集合分割成小集合,适用于分批查询、插入等场景。

 List listStr = Lists.newArrayList("1", "2", "3","4","5","6","7");
 List>  batchList = Lists.partition(listStr,3);
 //被分割成了: [[1, 2, 3], [4, 5, 6], [7]]
  • 3.3 分组
    Maps.uniqueIndex可以根据集合中的唯一键把集合转换为以唯一键为key,以元素为value的Map.
    Multimaps.index可以根据集合中的相同的值把集合转换为以相同值为key,以List<元素>为value的Map. 相当于一键多值Map。
class Apple {
        int id;
        String color;
        public Apple(int id, String color) {
            this.id = id;
            this.color = color;
        }
        public int getId() {
            return id;
        }
        public String getColor() {
            return color;
        }
        @Override
        public String toString() {
            return MoreObjects.toStringHelper(Apple.class).add("id", id).add("color", color).toString();
        }
    }

    @Test
    public void test1() {
        List appleList = Lists.newArrayList(new Apple(1, "red"), new Apple(2, "red"), new Apple(3, "green"), new Apple(4, "green"));
        // 以主键为key,生成键值对:Map
        Map appleMap = Maps.uniqueIndex(appleList, new Function() {
            @Nullable
            @Override
            public Integer apply(@Nullable Apple apple) {
                return apple.getId();
            }
        });
      // 相当于根据颜色分类:转为Map<颜色,Collection>
     Multimap multiMap = Multimaps.index(appleList,
                new Function() {
                    @Nullable
                    @Override
                    public String apply(@Nullable Apple apple) {
                        return apple.getColor();
                    }
                });

    }

在Java 8中的实现为

 List appleList = Lists.newArrayList(new Apple(1, "red"), new Apple(2, "red"), new Apple(3, "green"), new Apple(4, "green"));
  Map appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, apple -> apple));

  Map> groupsByColor =
                appleList.stream().collect(Collectors.groupingBy(Apple::getColor));
  • 3.4 其他

排序:

Collections.sort 
Ordering.natural()

集合的交集、并集和差集:

Sets.intersection(setA, setB);
Sets.union(setA, setB);
Sets.difference(setA, setB);

创建不可变的集合

 ImmutableList<String> list = ImmutableList.of("1", "2", "3");

4. 线程

com.google.common.util.concurrent目录下是各种线程工具类。
这里介绍一下:
ListenableFuture:顾名思义就是可以监听的Future,它是对java原生Future的扩展增强。
MoreExecutors:该工具类,提供了很多静态方法。其中listeningDecorator方法初始化ListeningExecutorService方法,使用此实例submit方法即可初始化ListenableFuture对象。
ListeningExecutorService的invokeAny继承自Jdk原生类,率先返回线程组中首个执行完毕的。
ListeningExecutorService的invokeAll并行执行线程组,等待所有线程执行完毕,适用于批量处理。

   public final List list = Lists.newArrayList("a", "b", "c", "d", "e", "f");

    @Test
    public void testGuava() {
        ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
        List> allThread = Lists.newArrayList();
        for (final String value : list) {
            Callable callable = new Callable() {
                @Override
                public String call() {
                    return value + " 休息了 " + sleepRandom();
                }
            };
            allThread.add(callable);
        }
        try {
            //1. 返回首个执行完毕的值
            //  String date = listeningExecutorService.invokeAny(allThread);
            // 2. 并行执行完所有线程
            List> valueList = listeningExecutorService.invokeAll(allThread);
            for (Future future : valueList) {
                System.out.println(future.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            listeningExecutorService.shutdown();
        }
    }

在Java 8中可以这样实现

 @Test
    public void testJava8() throws Exception {

        ExecutorService executor = Executors.newFixedThreadPool(10);
        List futures = list.stream()
                .map(value -> CompletableFuture.completedFuture(value).thenApplyAsync(s -> s + " 休息了 " + sleepRandom(), executor))
                .collect(Collectors.toList());
        //1. 返回首个执行完毕的值
        // CompletableFuture valueFuture = CompletableFuture.anyOf(futures.toArray(new CompletableFuture[futures.size()]));
        // 2. 并行执行完所有线程
        CompletableFuture valueFutureList = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
        futures.stream().forEach(f -> {
            try {
                System.out.println(f.get());
            } catch (Exception e) {

            }
        });

    }

5. EventBus消息总线

EventBus是Guava提供的消息发布-订阅类库,它的工作机制类似于观察者模式,通过通知者去注册观察者,最后由通知者向观察者发布消息。
如果你需要订阅某种类型的消息,只需要在指定的方法上加上@Subscribe注解即可。
代码例子:
一个观察者可以订阅多个发布者,一个发布者可以推送给多个观察者,实现了解耦。


public class MqEvent {
}
public class StatusEvent {
}
 //第一个观察者,订阅了两种类型的发布
 public class EventHandler {

    @Subscribe
    public void mq(MqEvent mq) {
        System.err.println(mq.getClass().getCanonicalName()+" work");
    }

    @Subscribe
    public void status(StatusEvent statusEvent) {
        System.err.println(statusEvent.getClass().getCanonicalName() +" work");
    }
}
// 第二个观察者只订阅了一种类型的发布
public class OtherHandler {

    @Subscribe
    public void mq(MqEvent mq) {
        System.err.println( "OtherHandler work");
    }
}

public class EventTest {

    public static void main(String[] args) {
        //初始化消息总线
        EventBus eventBus = new EventBus();
        // 注册订阅者
        eventBus.register(new EventHandler());
        eventBus.register(new OtherHandler());
        //MqEvent推送给了两个订阅者
        MqEvent mqEvent = new MqEvent();
        StatusEvent statusEvent = new StatusEvent();
        //发布消息
        eventBus.post(mqEvent);
        eventBus.post(statusEvent);
    }
}

EventBus 另有异步实现: AsyncEventBus
另一个更加专业、更加强大、更加高效,基于内存的消息处理框架是来自LMAX(伦敦外汇黄金交易所)的:Disruptor

6.秒表

我们经常使用System.currentTimeMillis()来计算某段代码执行的实现,Stopwatch 可以很方便的实现同样的功能。

  Stopwatch stopwatch = Stopwatch.createStarted();
                for(int i =0; i <10000; i++){
                 //do something test
                }
  long nanos = stopwatch.elapsed(TimeUnit.NANOSECONDS);
  System.out.println(nanos);

7.算法

了解一下Guava中激动人心的算法。详情自行搜索。

  • 6.1 布隆过滤

布隆过滤器用于判断一个元素是否在一个超大的集合中。
哈希表也能用于判断元素是否在集合中,但是布隆过滤器只需要哈希表的1/8或1/4的空间复杂度就能完成同样的功能。
Guava中的布隆过滤实现:

com.google.common.hash.BloomFilter
  • 6.2 限流算法
    Guava 中提供了RateLimiter类,它经常用于限制对一些物理资源或者逻辑资源的访问速率。
com.google.common.util.concurrent.RateLimiter

你可能感兴趣的:(java)