Guava库API使用部分总结

2023-11-16

Guava库

        1,  Guava是对Java API的补充,对Java开发中常用功能进行更优雅的实现,使得编码更加轻松,代码容易理解。Guava使用了多种设计模式,同时经过了很多测试,得到了越来越多开发团队的青睐。Java最新版本的API采纳了Guava的部分功能,但依旧无法替代。本文以Getting Started With Google Guava原文为学习材料,对Guava中常用的API进行学习,尽量覆盖比较有用的API,包括字符串处理,集合类处理,文件IO处理等。以往我们在使用工具包的时候首先想到是著名的Apache的Commons系列,今天我要介绍的是同样出色,并且目前发展比Apache Commons系列更为迅速的Google Guava库。

Google Guava库是一个非常优秀的包含很多Java工具类集的库,广泛使用在Google公司内部,因此它可以被使用到几乎所有的Java项目中。Google Guava库最初发布在2007年,经过几年的更新发展目前其最新的版本为14.0-rc3。

               如果你之前有使用过Google collections库,那么请注意该库也已经被合并到Guava中了。想使用Guava工具包很简单,在maven项目中的pom.xml文件中:

   <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
        </dependency>
       2,Guava工具包使用:
           1)对象工具类 Objects
                实体类(User只有userId和name两个属性)重写toString方法:
               Guava写法: 
               @Override
     public String toString() {
return MoreObjects.toStringHelper(this)
                                 .add("userId", userId)
                                 .add("name", name).toString();
     }
                实体类重写compareTo方法:
                public int compareTo(User o) {
return ComparisonChain.start().compare(userId, o.userId).compare(name, o.name).result();
     }
                实体类重写equals方法:
}     public boolean equals(Object o) {
 if (this == o)
return true;
 if (o == null || getClass() != o.getClass())
return false;
 User user = (User) o;
 return Objects.equal(userId, user.userId) && Objects.equal(name, user.name);
      }
                 实体类重写hashCode方法:
                 public int hashCode() {
return Objects.hashCode(userId, name);
      }
           2)三目运算符的写法:
                      String ret=serivce.operation(); 
                   return MoreObjects.firstNonNull(ret,"默认值");//相当于jdk中的return ret!=null?ret:"默认值";
                   字符串连接器Joiner实现字符串的拼接:
StringBuffer sb = new StringBuffer();
Joiner  joiner = Joiner.on(",").skipNulls();//字符串连接器,以|为分隔符,同时去掉null元素
sb = joiner.appendTo(sb, "pengpeng","liangliang","liang",null);
System.out.println(sb.toString());
                 //======================字符串连接器Joiner==============================
StringBuffer sb = new StringBuffer();
Joiner  joiner = Joiner.on(",").skipNulls();//字符串连接器,以|为分隔符,同时去掉null元素
sb = joiner.appendTo(sb, "pengpeng","liangliang","liang",null);
System.out.println(sb.toString());

//将map转化成字符串
java.util.Map<String,String> map = Maps.newLinkedHashMap();
map.put("Cookies", "12332");  
map.put("Content-Length", "30000");  
map.put("Date", "2016.12.16");  
map.put("Mime", "text/html");  
String mapToStr = Joiner.on("#").withKeyValueSeparator(":").join(map);
System.out.println(mapToStr);

// 连接List元素并写到文件流

//=====================字符串分割器Splitter================================
Splitter sp = Splitter.on("|").trimResults();
String str = "pengpeng | liangliang";
Iterable<String> ss = sp.split(str);
for(String str1 : ss){
System.out.println(str1);
}

// 将字符串转化为Map      内部类的引用,得到分割器,将字符串解析为map 
String mapStr = "id:10#name:pengliang";
Splitter.MapSplitter ms = Splitter.on("#").withKeyValueSeparator(":");
Map<String,String> newMap = ms.split(mapStr);
for(String key :newMap.keySet()){
System.out.println(newMap.get(key));
}
System.out.println(newMap);

//========================字符匹配器CharMatcher==============================
String str2 = "peng liang\r\ryou are a good\tboy";   //空白回车换行对应换成一个#,一对一换  
String newStr = CharMatcher.breakingWhitespace().replaceFrom(str2, "#");
System.out.println(newStr);

//字符串工具类Strings  可以处理一些字符串的非空校验等等
if(Strings.isNullOrEmpty("") && Strings.isNullOrEmpty(null)){
System.out.println("字符串空值工具类可用!");
}

//字符串中保留数据
String letterAndNumber = "1234abcdABCD56789";  
String num = CharMatcher.JAVA_DIGIT.retainFrom(letterAndNumber);
System.out.println(num);

//===================断言工具类Preconditions===============================
int data = 10;
String strr = null;
//Preconditions.checkNotNull(strr, "strr is null");//检查是否为null,null将抛出异常IllegalArgumentException,且第二个参数为错误消息。
//Preconditions.checkArgument(data>100, "data must be less than 100");

//对象工具类 Objects
String ostr = null;
String result = Objects.firstNonNull(ostr, "hello world");// 如果第一个为空,则返回第二个,同时为null,将抛出NullPointerException异常  
System.out.println(result);

//===================整体迭代接口FluentIterable=============================
//使用Predicate整体过滤
User user1 = new User("1","tom");  
User user2 = new User("2","Fred");  
User user3 = new User("3","Barney");  
List<User> userList = Lists.newArrayList(user1, user2, user3); 
Iterable<User> iterables =  FluentIterable.from(userList).filter(new Predicate<User>(){
@Override
public boolean apply(User user) {
return Integer.parseInt(user.getUserId())>2;
}
});
for(Iterator<User> it = iterables.iterator();it.hasNext();){
System.out.println(it.next());
}
//System.out.println(Iterables.contains(iterables, user3));  

//使用Function整体替换,将List<Person>转化为List<String>
List<String> stringList = FluentIterable.from(userList).transform(new Function<User,String>(){


@Override
public String apply(User user) {
return Joiner.on("#").join(user.getUserId(), user.getName());
}
}).toList();
for(String sss : stringList){
System.out.println(sss);
}

//============集合运算工具类Sets========================
//Sets.difference()方法
Set<String> s1 = Sets.newHashSet("1", "2", "3", "4");  
Set<String> s2 = Sets.newHashSet("2", "3", "4", "5");  
// 得到第一个集合中有而第二个集合没有的字符串  
Sets.SetView<String> iterable =  Sets.difference(s1, s2);
for(Iterator<String> its = iterable.iterator();its.hasNext();){
System.out.println(its.next());
}

//集合对称差 得到第一个集合和第二个集合中不相同的元素组成的集合(差集)    Sets.symmetricDifference()方法求差集
Sets.SetView<String> res2 = Sets.symmetricDifference(s1, s2);  
for(Object it14 : res2){  
   System.out.println(it14); // 1 5  
}  

// s1和s2的交集   Sets.intersection()方法     求交集
Sets.SetView<String> res3 = Sets.intersection(s1, s2);  
for(String it14 : res3){  
   System.out.println(it14); // 2 3 4  
}

// 合并s1和s2    Sets.union()方法     求并集
Sets.SetView<String> res4 = Sets.union(s1, s2);  
for(String it14 : res4){  
   System.out.println(it14); // 1 2 3 4 5  
}

//利用Functions将Map转化为Function
Map<String, User> mp = Maps.newHashMap();  
mp.put(user1.getName(), user1);  
mp.put(user2.getName(), user2);  
mp.put(user3.getName(), user3);  
// 将map转化为Function,Function的功能是将一个类型转化为另一个类型  
Function<String, User> lookup = Functions.forMap(mp);  
// 如果键值不存在,则会抛出异常。lookup内部已经有元素  
User tmp = lookup.apply("tom");  
System.out.println(tmp == user1); // true  

//Predicate单个判断   单条的过滤元素
Predicate<User> userPre = new Predicate<User>(){
@Override
public boolean apply(User input) {
return Integer.parseInt(input.getUserId())>2;
}
};
//判断是否符合条件
System.out.println(userPre.apply(user3 ));

   //Predicates的and运算     userPre和namePre两个条件都满足才输出true
Predicate<User> namePre = new Predicate<User>(){  
   @Override  
   public boolean apply(User user) {  
       return user.getName().equals("Barney");  
   }  
};  
Predicate<User> both = Predicates.and(userPre, namePre);  // 利用Predicates工具类,同时满足两个条件成一个predicate  
System.out.println(both.apply(user1)); // false  
System.out.println(both.apply(user2)); // false
System.out.println(both.apply(user3)); // true  

// 至少一个满足组成一个Predicate  
Predicate<User> orPre = Predicates.or(userPre, namePre);  
System.out.println(orPre.apply(user3)); // false  

//==============Map工具类Maps===============
// 将List<User> 转化为Map<String, User>,其中键值对是user.userId -> User  
Map<String,User> mapp = Maps.uniqueIndex(userList.iterator(), new Function<User,String>(){
@Override
public String apply(User user) {
return user.getUserId();
}
});
for(Entry<String, User> en : mapp.entrySet()){
System.out.println("key:"+en.getKey()+";"+"value:"+en.getKey());
}

//==============一键多值类Multimap=================
// 用ArrayList保存,一键多值,值不会被覆盖  
ArrayListMultimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("foo", "1");  
multimap.put("foo", "2");  
multimap.put("foo", "3");  
multimap.put("bar", "a");  
multimap.put("bar", "a");  
multimap.put("bar", "b");  
for(String mulKey : multimap.keySet()){
System.out.println("key:"+mulKey+";"+"values:"+multimap.get(mulKey));
}

//HashTable存储多值类 HashMultimap  这里采用HashTable保存  
HashMultimap<String, String> hashMultimap = HashMultimap.create();  
hashMultimap.put("foo", "1");  
hashMultimap.put("foo", "2");  
hashMultimap.put("foo", "3");  
// 重复的键值对值保留一个  
hashMultimap.put("bar", "a");  
hashMultimap.put("bar", "a");  
hashMultimap.put("bar", "b");  
for(String it20 : hashMultimap.keySet()){  
   // 返回类型List<String>  
   System.out.println(it20 + " : " + hashMultimap.get(it20));  
}  
System.out.println(hashMultimap.size());  // 5  

//================多键类Table===================
//两个键操作        两个键row key和column key,其实就是map中map, map<Integer, map<Integer, String> > mp  
HashBasedTable<Integer,Integer,String> table = HashBasedTable.create();
table.put(1, 1, "book");  
table.put(1, 2, "turkey");  
table.put(2, 2, "apple");  
System.out.println(table.get(1, 1));
System.out.println(table.contains(2, 3)); // false  
System.out.println(table.containsRow(2)); // true  
table.remove(2, 2);  
System.out.println(table.get(2, 2)); // null  
//从HashBasedTable中获取单独的一个map  
Map<Integer, String> row = table.row(1);  
Map<Integer, String> column = table.column(2);  
System.out.println(row.get(1)); // book  
System.out.println(column.get(1)); // turkey  

//不可变集合类ImmutableListMultimap
Multimap<Integer, String> mulTileMap = new ImmutableListMultimap.Builder<Integer,String>().put(1, "apple").putAll(2, "apple","pear","book").build();
System.out.println("不可变集合类-"+"key:"+String.valueOf(2)+";"+"values:"+mulTileMap.get(2));
System.out.println(mulTileMap);

//=============区间工具类Range====================
//闭区间  Range.closed
Range<Integer> closedRange = Range.closed(30, 33); 
System.out.println("是否包含闭区间内的值:"+closedRange.contains(30));
// 开区间  Range.open
Range<Integer> openRange = Range.open(30, 33);  
System.out.println("是否包含开区间内的值:"+openRange.contains(30));
// Range实现了Predicate接口,这里的第一个参数是Predicate,第二个参数是Function  
// ageFunction必须返回整数
Person person1 = new Person("zhangsan",30);
Person person2 = new Person("lisi",31);
Person person3 = new Person("wangwu",32);
Function<Person, Integer> ageFunction = new Function<Person, Integer>(){  
   @Override  
   public Integer apply(Person person) {  
       return person.getAge();  
   }  
};  //Predicate判断【断言】
Predicate<Person> agePredicate = Predicates.compose(closedRange, ageFunction);//Predicates的compose运算
System.out.println(agePredicate.apply(person1)); // person1.age == 30 true  

//===========比较器工具类 Ordering============
//逆置比较器
Comparator<Person> ageCmp = new Comparator<Person>(){  
   // Ints是Guava提供的,递增  
   @Override  
   public int compare(Person o1, Person o2) {  
       return Ints.compare(o1.getAge(), o2.getAge());  
   }  
};  
List<Person> perList = Lists.newArrayList(person1,person2,person3);
// 将比较器转化为Ordering,得到比较器ageCmp的相反比较器,递减  
Collections.sort(perList,Ordering.from(ageCmp).reverse());
//遍历集合
for(Iterator iterList = perList.iterator();iterList.hasNext();){
System.out.println(iterList.next());
}

System.out.println("===============================================");
// 组合多个比较器  Ordering.compound()方法
Comparator<Person> nameCmp = new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
return o1.getName().compareTo(o2.getName());
}
};
Ordering  order = Ordering.from(ageCmp).compound(nameCmp); //按照age,name进行排序得到的集合
Collections.sort(perList,order);
for(Iterator its = perList.iterator();its.hasNext();){
System.out.println(its.next());
}

//直接获取最小几个和最大几个
Ordering order2 = Ordering.from(ageCmp);  
List<Person> leastList = order2.leastOf(perList, 2);
for(Person per1 : leastList){
System.out.println("per1:"+per1.getAge()+";"+per1.getName());
}
List<Person> greateList = order2.greatestOf(perList, 2);
for(Person per2 : greateList){
System.out.println("per1:"+per2.getAge()+";"+per2.getName());
}

//===============文件工具类Files=======================
//复制,移动重命名文件         可以通过代码来执行命令
File file1 = new File("E:/words.txt");
File file2 = new File("E:/copywords.txt");
File file3 = new File("E:/renamewords.txt");
Files.copy(file1, file2);
Files.move(file2, file3);

   // 写文件流
File file4 = new File("E:/write.txt");
Files.write("hello world", file4 ,Charsets.UTF_8);//重新写
Files.append("china", file4, Charsets.UTF_8); // 追加    在hello world后面追china


//获取文件哈希码
HashCode hashCode = Files.hash(file3, Hashing.md5());  
   System.out.println(file3.getName() + " : " + hashCode);  

    //读取文件流,将文件行转化为List
    // 读文件流  
   int lineNumber = 1;  
   List<String> fileList = Files.readLines(file3, Charsets.UTF_8);
   for(Iterator<String> it = fileList.iterator(); it.hasNext();){  
       System.out.println("line " + lineNumber + ":" + it.next());  //把文件中每行的内容都输出来的    有一种mapreduce处理文本文件的意思
       lineNumber++;  
   }  

   System.out.println("====================================");
   //对文件中的内容进行处理,再一次得到List
   int lineNumber1 = 1;  
   File file5 = new File("E:/after.txt");
   //TitleLineProcessor:读取文本的每一行内容,以,分割成数组,再将数组中的第一个元素组转到集合List中
   List<String> afterFileList = Files.readLines(file5, Charsets.UTF_8,new TitleLineProcessor());
   for(Iterator<String> afterIt = afterFileList.iterator();afterIt.hasNext();){
    System.out.println("line " + lineNumber1 + ":" + afterIt.next());  
    lineNumber1++;  
   }


         public class TitleLineProcessor implements LineProcessor<List<String>> {

private final static int INDEX = 0;  
private final static Splitter splitter = Splitter.on(",");  
private List<String> titles = new ArrayList<String>();  


// 每一行都会调用这个函数,进而追加成一个list
@Override
public boolean processLine(String line) throws IOException {
// 获取第一项,并追加到titles  
        titles.add(Iterables.get(splitter.split(line), INDEX));  
        return true;  
}


// 最终的结果  
@Override
public List<String> getResult() {
 return titles;  
}
        }

   //================编码工具类BaseEncoding================
   //BaseEncoding.base64()的编码和解码
   BaseEncoding base64Encoding = BaseEncoding.base64();
   byte[] content = Files.toByteArray(file5);
   //对原内容进行加密  base64编码
   String encoded  = base64Encoding.encode(content);
   System.out.println("encoded:\n" + encoded);  
   // 获得对应的加密字符串,可以解密,可逆的,得到原来的字节  
   byte[] decoded = base64Encoding.decode(encoded);  
   for(int i = 0; i < decoded.length; i++){  
            System.out.print(decoded[i] + " ");  
        }  
   System.out.println(" ");  
   
   //读输入字节流ByteSource和写输出字节流ByteSink
   // source是源的意思,封装输入流  
   ByteSource byteSource = Files.asByteSource(file4);  
   try {  
       byte[] contents1 = byteSource.read();  
       byte[] contents2 = Files.toByteArray(file4); // 两个方法的作用相同  
       for(int i = 0; i < contents1.length; i++){  
           assert(contents1[i] == contents2[i]);  
           System.out.print(contents1[i] + " ");  
       }  
   } catch (IOException e) {  
       e.printStackTrace();  
   }  
     
   // sink是目的地的意思,封装输出流,流会自动关闭  
   File tmpFile = new File("E:/hello.txt"); // acd  
   ByteSink byteSink = Files.asByteSink(tmpFile);  
   try {  
       byteSink.write(new byte[]{'a', 'c', 'd', '\n'});  
   } catch (IOException e) {  
       e.printStackTrace();  
   }


public class GuavaDemo {
private static Logger logger = Logger.getLogger(GuavaDemo.class);
/*
 * 使用Optional的意义:
 * Optional对象的使用强迫你去积极的思考这样一种情况,如果你想让你的程序返回null值,这null值代表的含义是什么,因为你想要取得返回值,
 * 必然从Optional对象内部去获得,所以你必然会这么去思考,增加了程序的可读性。
 * 
 * 常用方法
 * Optional.fromNullable(T):将一个T的实例转换为Optional对象,T的实例可以不为空,也可以为空
 * Optional.of(T):获得一个Optional对象,其内部包含了一个非null的T数据类型实例,若T=null,则立刻报错。
 * T get():返回Optional包含的T实例,该T实例必须不为空;否则,对包含null的Optional实例调用get()会抛出一个IllegalStateException异常
 * 用途:
 * Optional<T>的最常用价值在于,例如,假设一个方法返回某一个数据类型,调用这个方法的代码来根据这个方法的返回值来做下一步的动作,
 * 若该方法可以返回一个null值表示成功,或者表示失败,在这里看来都是意义含糊的,所以使用Optional<T>作为返回值,
 * 则后续代码可以通过isPresent()来判断是否返回了期望的值(原本期望返回null或者返回不为null,其意义不清晰),并且可以使用get()来获得实际的返回值。
 */
   public static Optional<Integer> test1() {
       return Optional.fromNullable(15);
   }
   
   /*
    * Preconditions
    * 判断参数,如果参数配置错误,就抛出异常
    * 写代码时我们可以这样参数判断。 
    * 
    * 用途:所以推荐在方法的入口,或运算开始前,先检查数据。
    */
   public static void test2(boolean status,List<String> list, int position) {
    Preconditions.checkArgument(status); //等价: if (!preCondition) {throw new IllegalArgumentException("preCondition not allow!!");}
    Preconditions.checkNotNull(list, "数组对象为:null");//等价于: if (array == null) {throw new NullPointerException("array is null!!");}
    Preconditions.checkPositionIndex(position, list.size(), "index超出数组的index了");//等价:  if (position > array.length || position < 0) {throw new ArrayIndexOutOfBoundsException("position error!!");}
   }
   public static String test3( ) {
    return null;
   }
   public static void doSomething() throws Throwable {
       //ignore method body
   }
   /*
    * Guava中的排序器是Ordering
    * 
    * 常用的静态方法
    * natural():对传入的参数进行自然排序,例如:String排字典序,Int排大小。。。
               * usingToString():排字典序。
               * artibrary():无序。每次的排序结果都不同。
    * 
    */
   public static void OrderingTest(){
   
    List<Integer> intList = Lists.newArrayList(1,4,3,5,0,8,7);
    Ordering<Integer> natural = Ordering.natural();
    intList = natural.sortedCopy(intList);
    logger.info("natural.sortedCopy:"+intList);
                   //也可以自定义Ordering排序器
        Ordering<Integer> orderingBig = new Ordering<Integer>() {
        @Override
        public int compare(Integer left, Integer right) {
               return left - right;
           }
       };
   }
   
   /*
    * Guava Throwable类
    * 简化了异常和错误的传播与检查;
    * 
    * 功能:
    * guava类库中的Throwables提供了一些异常处理的静态方法,这些方法的从功能上分为两类:
    *1, 一类是帮你抛出异常
    * 2,另外一类是帮你处理异常。
    * 案例:当我们调用一个抛出Throwable或者Exception异常的方法时他们什么异常都有可能抛出来,如果我们要调用这样的方法,
    * 就需要对他们的异常做一些处理了,我们需要判断什么样的异常需要抛出去,什么样的异常需要封装成RuntimeException。
    * 假定我们要实现一个doIt的方法,该方法要调用doSomething方法,而doIt的定义中只允许抛出SQLException,我们可以这样做:
    * 
    */
   public static void doIt() throws SQLException {
       try {
           doSomething();
       } catch (Throwable throwable) {
        //如果是SQLException就抛出
           Throwables.propagateIfInstanceOf(throwable, SQLException.class);
           //抛出RuntimeException异常
           Throwables.propagateIfPossible(throwable);
       }
   }
   
   public static void main(String[] args){
    //===================Optional 处理方法返回为null的情况=================
 Optional<Integer> possible = test1();
           if(possible.isPresent()){
            logger.info("possible value:"+possible.get());
           }else{
           logger.error("possible value : null");
           }
    //==========================================================
    //===================Preconditions 参数判断========================
        test2(true,Lists.newArrayList("yytttrrrr","fsdf","fsfsff"),2);
        //==========================================================
        //====================默认值得设定==============================
       String ret=test3();
       //String result = ret!=null?ret:"默认值";
       String result = MoreObjects.firstNonNull(ret,"默认值"); //Guava工具包的写法
       logger.info("result默认值:"+result);
       //===========================================================
       //=====================排序===================================
       OrderingTest();
       //===========================================================
       try {
doIt();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
       //=====================Cuava集合================================
       Multimap<String,User> scoreMultimap = ArrayListMultimap.create(); 
       for (int i = 0; i < 5; i++) {
        User user = new  User();
        user.setUserId(String.valueOf(i));
       user.setName("tom"+i);
          scoreMultimap.put("key"+i, user);
}
       Collection<User> userCollection = scoreMultimap.get("key1");
       scoreMultimap.remove("key1", userCollection);
       for(User user : userCollection){
        System.out.println("name:"+user.getName());
       }
       //google guava集合之Table
       Table<Integer, Integer, String> table = HashBasedTable.create();
       for (int row = 0; row < 10; row++) {
           for (int column = 0; column < 5; column++) {
               table.put(row, column, "value of cell (" + row + "," + column + ")");
           }
       }
       //遍历Table
       for (int row=0;row<table.rowMap().size();row++) {
           Map<Integer,String> rowData = table.row(row);
           for (int column =0;column < rowData.size(); column ++) {
               System.out.println("cell(" + row + "," + column + ") value is:" + rowData.get(column));
           }
       }
    }
             }


参考:http://blog.csdn.net/guozebo/article/details/51590517
/*
 * GuavaCache实现本地缓存
 *清楚缓存的策略:
 * 1)基于存活时间的清除(Timed Eviction)
 *      这应该是最常用的清除策略,在构建Cache实例的时候,CacheBuilder提供两种基于存活时间的构建方法:
 *      (1)expireAfterAccess(long, TimeUnit):缓存项在创建后,在给定时间内没有被读/写访问,则清除。
 *      (2)expireAfterWrite(long, TimeUnit):缓存项在创建后,在给定时间内没有被写访问(创建或覆盖),则清除。
 *      expireAfterWrite()方法有些类似于redis中的expire命令,但显然它只能设置所有缓存都具有相同的存活时间。若遇到一些缓存数据的存活时间为1分     *      钟,一些为5分钟,那只能构建两个Cache实例了。
 * 2)于容量的清除(size-based eviction)
 *      在构建Cache实例的时候,通过CacheBuilder.maximumSize(long)方法可以设置Cache的最大容量数,当缓存数量达到或接近该最大值时,Cache将*  *      清除掉那些最近最少使用的缓存。以上是这种方式是以缓存的“数量”作为容量的计算方式,还有另外一种基于“权重”的计算方式。比如每一项缓存  *      所占据的内存空间大小都不一样,可以看作它们有不同的“权重”(weights)。你可以使用CacheBuilder.weigher(Weigher)指定一个权重函数,并   *      且用CacheBuilder.maximumWeight(long)指定最大总重。
 */
public class CacheService {
static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
// 构建cache实例
final static Cache<Integer, String> cache = CacheBuilder.newBuilder().initialCapacity(10) // 设置cache的初始大小为10,要合理设置该值
.concurrencyLevel(5) // 设置并发数为5,即同一时间最多只能有5个线程往cache执行写入操作
.expireAfterWrite(5, TimeUnit.SECONDS) // 设置cache中的数据在写入之后的存活时间为5秒
.build();


public static void main(String[] args) throws Exception {// main方法是一个线程
// 启动一个线程,每隔2秒输出当前缓存容器缓存数据大小
new Thread() {


@Override
public void run() {
while (true) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(
Thread.currentThread().getName() + sdf.format(new Date()) + " size: " + cache.size());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}
}.start();


// main方法线程做得事情
cache.put(1, "pengliang");
System.out.println(Thread.currentThread().getName() + "write key:1 ,value:" + cache.getIfPresent(1));
Thread.sleep(10000);
cache.put(2, "bbb");
System.out.println(Thread.currentThread().getName() + "write key:2 ,value:" + cache.getIfPresent(2));
Thread.sleep(10000);
// when read other key ,key:2 do not clear
System.out.println(Thread.currentThread().getName() + sdf.format(new Date()) + " after write, key:1 ,value:"
+ cache.getIfPresent(1));
Thread.sleep(2000);
// when read same key ,key:2 clear
System.out.println(Thread.currentThread().getName() + sdf.format(new Date()) + " final, key:2 ,value:"
+ cache.getIfPresent(2));


/*
* 总结: 这在GuavaCache被称为“延迟删除”,即删除总是发生得比较“晚”,这也是GuavaCache不同于其他Cache的地方!
* 这种实现方式的问题:缓存会可能会存活比较长的时间,一直占用着内存。如果使用了复杂的清除策略如基于容量的清除,
* 还可能会占用着线程而导致响应时间变长。但优点也是显而易见的,没有启动线程,不管是实现,还是使用起来都让人觉得简单(轻                                量)。
* 如果你还是希望尽可能的降低延迟,可以创建自己的维护线程,以固定的时间间隔调用Cache.cleanUp(),
* ScheduledExecutorService可以帮助你很好地实现这样的定时调度。不过这种方式依然没办法百分百的确定一定是自己的维护线程
* “命中”了维护的工作。
*/


}
}

















本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Guava库API使用部分总结 的相关文章

  • SpringBoot——整合Mongodb

    简单介绍 Mongdb是一个开源 高性能 无模式的文档型数据库 NoSQL数据库产品中的一种 是最像关系型数据库的非关系型数据库 使用场景 用户数据 存储位置 数据库 特征 永久性存储 修改频率极低 游戏装备数据 存储位置 数据库 Mong
  • 2023华为od机试 Java实现【关联子串】

    题目 我们有两个字符串 分别叫做 str1 和 str2 现在规定 如果 str1 的排列组合只要有一个是 str2 的子串 我们就称str1是str2的关联子串 请返回子串在str2的起始位置 若不是关联子串则返回 1 示例1 输入输出示
  • jvm垃圾回收

    为什么需要垃圾回收 首先这个问题的话 主要因为内存是计算机中比较宝贵的财富 如果堆积的对象过多 可想而知 内存会用尽 出现内存溢出的问题 这也就是为什么需要垃圾回收的原因 对什么区域进行回收 jvm中的内存结构中 虚拟机栈 本地方法栈 程序
  • 模拟蒙特卡罗方法计算圆周率

    使用蒙特卡罗方法计算出圆周率 并输出程序运行的时间 以及画出散点图 import random as r 调用random库 import time as t 调用time库 import math 调用math库 import matpl
  • mysql gtid坑_mysql Statement violates GTID consistency 的坑

    今天项目迁移 重新换了一个数据库版本 然后问题来了 原本运行正常的程序迁移过来之后就是不能正常运行 后台报错如下 update tbl user info set 强制下架 mv count mv count 1 update time n
  • Visual Studio配置c环境

    Visual Studio配置c环境 Visual Studio配置c环境 1 下载Visual Studio 下载Visual Studio软件可以直接在其内进行c的运行 不需要配置 官网 其中社区版免费 2 安装Visual Studi
  • TreeMap用法总结

    public class TreeMap
  • Java项目获取图片时的相对路径

    在eclipse环境下 1 通过new ImageIcon 相对路径 getImage 获取 此时的绝对位置是项目根目录 相对路径从下一级目录写起 如项目名为project 要获取的图片a png在src目录下的pic目录下 则代码为 Im
  • 这个智能家居项目开源了

    今天 推荐一个物联网项目 物美智能 如果你具备硬件 软件知识 这个项目肯定符合你的胃口 物美智能是一套软硬件结合的开源项目 该系统可助你快速搭建自己的智能家居系统 你可以学习到设备的集成和软硬件交互 PC 端或者手机与服务端通信 单片机可以
  • spark-shell 加载本地文件报错 java.io.FileNotFoundException

    学习spark shell 时候发现一个问题 从本地文件加载数据生成RDD 报错 文件找不到 原因 spark shell 如果启动了集群模式 真正负责计算的executor会在 该executor所在的 worker节点上读取文件 并不是
  • Element plus 表单验证功能

    以下是官网提供的例子
  • [QT_046]Qt学习之网格布局器(QGridLayout)

    本文转自 Qt编程指南 作者 奇先生 Qt编程指南 Qt新手教程 Qt Programming Guide 6 3 网格布局器 本节介绍网格布局器 QGridLayout 当控件分布的行 列都比较有规律时 可以不用一行行设置布局器 而是直接
  • Linux下文件操作命令练习

    1 创建目录 home hadoop work1 home hadoop work2 mkdir home hadoop work1 mkdir home hadoop work2 2 将当前目录切换到 home hadoop work1
  • Hbuilder+PhPstudy配置PHP环境走过的坑

    由于比较喜欢用Hbuilder写前端 所以选择在这上面写PHP 在网上看到许多搭建环境的方法 最后选择了通俗易懂的PhPstudy 1 在PhPstudy官网上下载 注意 安装的路径不能出现中文和空格 这里我装在d盘 netstat ano

随机推荐

  • safari5.1 进程死掉的故障

    某个网页 在其他版本的safari包括safari mobile都可用 唯独升级到5 1后页面打不开了 用safari自带调试功能发现 解析css时进程死掉了 部分样式出现了 但其他样式没有出现 故障初步定在css上 一个多月过去了 后来将
  • Beyond Compare 3 许可证密钥被撤销

    最近在使用 Beyond Compare 3 时突然出现 许可证密钥被撤销 问题 现象截图以下 自己清除注册表并重新安装后还是出现相同的问题 没办法只能求助于百度 找到解决方法 删除 C Users Administrator AppDat
  • 当我问 ChatGPT 能否推荐一下好用的 API 管理工具时?

    近期围绕 ChatGPT 的话题 真的太多了 我们就知道了 ChatGPT 简单说就是搜索引擎 社交工具 这个解释最简单明了 出于好奇 我也用 ChatGPT 测试了一下 我 在中国 最好的 API 管理工具是什么 ChatGPT 我无法确
  • 剑指 Offer 09. 用两个栈实现队列

    题目链接 09 用两个栈实现队列 思路分析 用两个栈实现队列 首先把1 gt 2然后逐个弹出顶端元素 class CQueue public stack
  • 【华为OD机试真题】单向链表中间节点(寻找链表的中间结点)(C++&java&python)100%通过率 超详细代码注释 代码深度解读

    华为OD机试真题 2022 2023 真题目录 点这里 华为OD机试真题 信号发射和接收 试读 点这里 华为OD机试真题 租车骑绿道 试读 点这里 寻找链表的中间结点 知识点链表数组 时间限制 1s空间限制 256MB限定语言 不限 题目描
  • 2021美赛成绩查询证书下载

    下载证书地址为 http www comap math com mcm 2021Certs pdf 链接中的6个 替换为自己队的编号 如 http www comap math com mcm 2021Certs 123456 pdf
  • 中央循环管式蒸发器总图

    中央循环管式蒸发器属于自然循环型的蒸发器 它是工业生产中广泛使用且历史悠久的大型蒸发器 至今在化工 轻工 环保等行业中仍被广泛采用 它的加热室由管径为25mm 75mm 长度为1m 2m 长径之比约为20 40 的直立管束组成 在管束中央安
  • HCSR04超声波传感器驱动

    HC SR04是一款使用较为广泛的超声波测距模块 模块图如下 该模块具有四个引脚 分别为VCC GND TRIG ECHO 其中VCC GND为供电脚 TRIG为测距触发引脚 ECHO为测距输入引脚 该模块的驱动模式为 控制口发一个 10U
  • 【WIN】svchost与共享进程服务

    查看注册表中的系统服务文件夹 我们可以发现某些服务的ImagePath显示的是svchost exe的路径 如下图所示 svchost exe 是微软Windows操作系统中的系统文件 微软官方对它的解释是 svchost exe 是从动态
  • SpringBoot 整合 Druid+ 全局事务管理 +Mybatis-Plus+ 代码生成器

    SpringBoot 整合 Druid 全局事务管理 Mybatis Plus 代码生成器 在 springboot 开发当中 Druid 全局事务管理 代码生成器都是非常实用的 特此记录下整合的过程 整合 Druid 连接池 spring
  • js逆向技巧

    一 总结 搜索 全局搜索 代码内搜索 debug 常规debug XHR debug 行为debug 查看请求调用的堆栈 执行堆内存中的函数 修改堆栈中的参数值 写js代码 打印windows对象的值 勾子 cookie钩子 请求钩子 he
  • 存在的意义

    到目前为止出现过的所有备选答案 1 成功 成为人上人 2 好吃的 好听的 好看的 3 明白些道理 遇见有趣的事 4 像吃蛋糕和甜甜圈一样 在于吃的过程 5 纯粹为了快感而嗑药 6 为了我爱的人和爱我的人 7 为社会和他人作贡献 8 为神服务
  • FreeRTOS学习笔记—任务挂起和恢复

    文章目录 一 任务挂起和恢复API函数 1 1 vTaskSuspend 函数 1 2 vTaskResume 函数 1 3 xTaskResumeFromISR 函数 二 任务挂起和恢复 2 1 任务1挂起解挂任务2 2 2 中断中解挂任
  • 绘制ER图(数据库关系图)

    http www texample net tikz examples entity relationship diagram https www assembla com wiki show tikz er2 usepackage tik
  • Spring Boot 报错ThreadPoolTaskExecutor : Shutting down ExecutorService ‘applicationTaskExecutor‘

    问题 Spring Boot 报错ThreadPoolTaskExecutor Shutting down ExecutorService applicationTaskExecutor 原因 idea没有运行项目 运行了测试类 解决 运行
  • Angular 11常用api

    ngFor渲染每个商品 div div 属性绑定 div h3 a a h3 div 插值 div h3 a product name a h3 div
  • 【Android】使用native开发遇到的bug---java.lang.UnsatisfiedLinkError: No implementation found for

    今晚终于解决了一个困扰我三天的bug 就是这个java lang UnsatisfiedLinkError No implementation found for 感觉人生达到了巅峰 特此记录下 前几天老师给我一个项目 让我实现一个将视频下
  • 使用Xshell通过隧道代理进行SSH跳转访问

    文章来源 http www aloneray com 886 html 可能需要vpn翻墙才能访问 链接流程 本地服务器Local gt 中转服务器Jump gt 目标服务器Destination 简单来说 就是不直接访问你的目标服务器 而
  • weblogic作为文件浏览服务器,weblogic配置文件服务器

    weblogic配置文件服务器 内容精选 换一换 该任务指导用户使用Loader将数据从Hive导出到SFTP服务器 创建或获取该任务中创建Loader作业的业务用户和密码 确保用户已授权访问作业中指定的Hive表的权限 获取SFTP服务器
  • Guava库API使用部分总结

    Guava库 1 Guava是对Java API的补充 对Java开发中常用功能进行更优雅的实现 使得编码更加轻松 代码容易理解 Guava使用了多种设计模式 同时经过了很多测试 得到了越来越多开发团队的青睐 Java最新版本的API采纳了