zoukankan      html  css  js  c++  java
  • Guava工具类学习

    一、介绍

    1、常用点:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等
    2、开源的Java库,这个库是为了方便编码,并减少编码错误。

    二、Optional类

    1、定义

    官方解释:用于包含非空对象的不可变对象,Optional对象不存在值表示null。
    个人解释:换言之就是把变量转成Optional对象,其中null都转成Optional.absent()(就是一个空的Optional对象),然后就可以对Optional对象进行操作。好处就是发现null可选择抛出异常。

    2、java8自带Optional

    所以建议直接用java8自带的就好了,用法一样,只是方法名字稍微不一样

    3、使用

    关键方法(解释看代码):fromNullable、of、get、or、isPresent

    @Test
    public void OptionalTest() {
    	handleParam(null,1); //后面两个参数自己随意写
    }
    
    //处理参数举例子
    void handleParam(String a,Integer b){
    	//对于处理string参数
    	Optional<String> aOpt = Optional.fromNullable(a); //允许参数空。如果非空返回一个包含引用Optional实例,否则返回Optional.absent()。
        System.out.println(aOpt.isPresent());//输出aOpt是否为空
    	a=aOpt.or("defaultValue");//如果为空,就给一个默认值defaultValue
    	System.out.println(a);
    
    	//同理对于处理int参数
    	Optional<Integer> bOpt = Optional.of(b);//不允许参数空,不然会抛出异常
    	b=bOpt.get();//get的时候不允许变量为空
    	System.out.println(b);
    }
    

    三、Preconditions类

    1、定义

    官方解释:检查方法的参数是否符合业务
    个人感觉:我不喜欢这个,我觉得没什么用,用到的几率太小,要一直捕获exception

    2、使用

    关键方法(解释看代码):checkArgument、checkState;checkPositionIndex、checkElementIndex;checkNotNull

    	@Test
    	public void PreconditionsTest() {
    		try {
    			System.out.println(sqrt(-3.0));  //计算开方
    		}catch(Exception e){
    			System.out.println(e.getMessage());
    		}
    		try {
    			System.out.println(sum(null,3)); //计算和
    		}catch(NullPointerException e){
    			System.out.println(e.getMessage());
    		}
    		try {
    			System.out.println(getValue(-1,6));//判断下标是否有效
    		}catch(IndexOutOfBoundsException e){
    			System.out.println(e.getMessage());
    		}
    	}
    
    	public double sqrt(double input) {
    		Preconditions.checkArgument(input > 0.0, "非法参数: 参数为%s", input);//和checkState差不了多少
    		return Math.sqrt(input);
    	}
    
    	public int sum(Integer a, Integer b){
    		Preconditions.checkNotNull(a, "非法参数: 参数为空");
    		Preconditions.checkNotNull(b, "非法参数: 参数为空");
    		return a+b;
    	}
    
    	public int getValue(int index, int size){
    		 Preconditions.checkPositionIndex(index, size, "无效的下标");//和checkElementIndex差不了多少
    		return index;
    	}
    

    四、Ordering类

    1、定义

    官方解释:Ordering(排序)可以被看作是一个丰富的比较具有增强功能的链接,多个实用方法,多类型排序功能等
    个人解释:反正就是列表的排序,倒序,取最大最小,取从最大到最小的k个最大的元素,取从小到最大的k个最小的元素,亮点是可以兼容null

    2、使用

    关键方法(解释看代码):greatestOf、leastOf;min、max;sortedCopy、isOrdered、reverse;nullsFirst、nullsLast

    @Test
    public void OrderingTest() {
    	List<Integer> myList = new ArrayList<Integer>();
    	myList.add(new Integer(5));
    	myList.add(new Integer(2));
    	myList.add(new Integer(15));
    	myList.add(new Integer(51));
    	myList.add(new Integer(53));
    	myList.add(new Integer(35));
    	myList.add(new Integer(45));
    	myList.add(new Integer(32));
    	myList.add(new Integer(43));
    	myList.add(new Integer(16));
    
    	Ordering ordering = Ordering.natural();
    
    	//从最大到最小的k个最大的元素
    	List list1 = ordering.greatestOf(myList, 3);
    	System.out.println("从最大到最小的k个最大的元素list1:"+list1);//输出[53, 51, 45]
    	//从小到最大的k个最小的元素
    	List list2 = ordering.leastOf(myList, 3);
    	System.out.println("从小到最大的k个最小的元素list2:"+list2);//输出[2, 5, 15]
    	//最小元素
    	int min = (int) ordering.min(myList);
    	System.out.println("最小元素:"+min);//输出2
    	//最大元素
    	int max = (int) ordering.max(myList);
    	System.out.println("最大元素:"+max);//输出53
    
    
    	//排序后复制,原list不变,从小到大排序
    	List list3 = ordering.sortedCopy(myList);
    	System.out.println("从小到大排序后复制给list3:"+list3);//输出[2, 5, 15, 16, 32, 35, 43, 45, 51, 53]
    	System.out.println("原mylist:"+myList);//输出[5, 2, 15, 51, 53, 35, 45, 32, 43, 16]
    	//排序也可以直接用Collections.sort,从小到大排序,正常情况下此方法禁止list含null
    	Collections.sort(myList);
    	System.out.println("从小到大排序好原mylist:"+myList);//输出[2, 5, 15, 16, 32, 35, 43, 45, 51, 53]
    	//查看是否已经从小到大好了序,该方法禁止list含null,如果是从大到小则返回false
    	boolean isOrdered = ordering.isOrdered(myList);
    	System.out.println("查看是否已经排好了序:"+isOrdered);//输出true
    	//换成从大到小排序或者是翻转
    	Collections.sort(myList,ordering.reverse());
    	System.out.println("从大到小排序好原mylist:"+myList);//输出53, 51, 45, 43, 35, 32, 16, 15, 5, 2]
    
    
    	//ordering允许list含有null
    	myList.add(null);
    	//对待null小于所有其他值
    	Collections.sort(myList,ordering.nullsFirst());
    	System.out.println("添加null以后,对待null小于所有其他值,myList为:"+myList);//输出[null, 2, 5, 15, 16, 32, 35, 43, 45, 51, 53]
    	//对待null大于所有其他值
    	Collections.sort(myList,ordering.nullsLast());
    	System.out.println("添加null以后,对待null大于所有其他值,myList为:"+myList);//输出[2, 5, 15, 16, 32, 35, 43, 45, 51, 53, null]
    
    }
    

    五、Range类

    1、定义

    官方解释:Range 表示一个间隔或一个序列。它被用于获取一组数字/串在一个特定范围之内。Range定义了连续跨度的范围边界,这个连续跨度是一个可以比较的类型(Comparable type)。比如1到100之间的整型数据。
    个人解释:可以生产区间,就是一段连续的整型数据,可以判断是否存在或者获取两个区间的交集和并集,可以判断是否存在或者获取一个区间的最低端点和上限端点,可以查询一个区间是包含一个或者多个元素。

    2、生产区间的方法

    概念 表示范围 guava对应功能方法
    (a..b) {x | a < x < b} open(a, b)
    [a..b] {x | a <= x <= b} closed(a, b)
    [a..b) {x | a <= x < b} closedOpen(a, b)
    (a..b] {x | a < x <= b} openClosed(a, b)
    (a..+∞) {x | x > a} greaterThan(a)
    [a..+∞) {x | x >= a} atLeast(a)
    (-∞..b) {x | x < b} | lessThan(b)
    (-∞..b] {x | x <= b} atMost(b)
    (-∞..+∞) all values all()

    3、使用

    关键方法(解释看代码):lowerEndpoint,upperEndpoint,hasUpperBound,hasLowerBound;encloses,isConnected,intersection

       @Test
    	public void RangeTest(){
    		System.out.println("-------------------基本获取---------------------");
    		//创建一个范围 [a,b]
    		Range<Integer> range1 = Range.closed(0, 9);
    		System.out.println("生成range1 [0,9]: "+ range1.toString()); //输出[0‥9]
    		//查看Range是否存在某个或某些值
    		System.out.println("range1是否存在5: " + range1.contains(5));//输出true
    		System.out.println("range1是否存在(1,2,3): " + range1.containsAll(Ints.asList(1, 2, 3)));//输出true
    
    		//查看Range的最低端点和上限端点。
    		System.out.println("range1的最低端点: " + range1.lowerEndpoint());//输出0
    		System.out.println("range1是否有上端点: " + range1.hasUpperBound());//输出true
    		System.out.println("range1的上限端点: " + range1.upperEndpoint());//输出9
    
    		System.out.println("------------------闭区间和开区间----------------------");
    
    		//创建一个范围 (a,b)
    		Range<Integer> range2 = Range.open(0, 9);
    		System.out.println("生成range2 (0,9) :"+range2.toString());
    
    		//创建一个范围 (a,b]
    		Range<Integer> range3 = Range.openClosed(0, 9);
    		System.out.println("生成range3 (0,9] : "+range3.toString());
    
    		//创建一个范围 [a,b)
    		Range<Integer> range4 = Range.closedOpen(0, 9);
    		System.out.println("生成range4 [0,9) : "+range4.toString());
    
    		//返回一个包含所有值严格大于端点的范围内 (a,∞)
    		Range<Integer> range5 = Range.greaterThan(9);
    		System.out.println("生成range5 (9,∞) : "+range5.toString());
    		System.out.println("range5是否有上端点: " + range5.hasUpperBound());
    
    		System.out.println("------------------交集和并集----------------------");
    
    		Range<Integer> range6 = Range.closed(3, 5);
    
    		//是否包含子集
    		System.out.println("range1 [0,9] 是否包含 range6 [3,5]:" + range1.encloses(range6));
    
    		Range<Integer> range7 = Range.closed(9, 20);
    
    		//是否有交集
    		System.out.println("range1 [0,9] 和 range7 [9,20]是否有交集:" + range1.isConnected(range7));
    
    		Range<Integer> range8 = Range.closed(5, 15);
    
    		//返回由两者范围和connectedRange封闭,如果这样的范围存在的最大范围。如果不相连时,直接抛出异常
    		System.out.println("range1 [0,9]和 range8 [5,15]的交集:"+range1.intersection(range8).toString());
    
    		//返回最小的范围包围两者这个范围和other等。
    		System.out.println("range1 [0,9]和 range8 [5,15]的并集:"+range1.span(range8).toString());
           
           System.out.println("-------------------拓展---------------------");
    		//输出有限range
    		ContiguousSet<Integer> set = ContiguousSet.create(range8, DiscreteDomain.integers());
    		for(int grade : set) {
    			System.out.print(grade +" ");
    		}
    
    	}
    
    
    

    六、Multiset接口

    1、定义

    Multiset接口扩展设置有重复的元素,并提供了各种实用的方法来处理这样的元素在集合中出现。

    2、使用

    关键方法(解释看代码):elementSet、iterator;count、contains、containsAll、size;add、remove

      @Test
    	public void MultisetTest(){
    		//创建一个multiset
    		Multiset<String> multiset = HashMultiset.create();
    		multiset.add("a");multiset.add("b");multiset.add("c");
    		multiset.add("d");multiset.add("a");multiset.add("b");
    		multiset.add("c");multiset.add("b");multiset.add("b");
    
    		System.out.print("把multiset转成无重复set:");
    		Set<String> set = multiset.elementSet();
    		set.forEach(e-> System.out.print(e+" "));//输出a b c d
    
    		System.out.print("
    把multiset转成可重复且有序的Iterator:");
            Iterator<String> iterator  = multiset.iterator();
            iterator.forEachRemaining(e-> System.out.print(e+" "));//输出a a b b b b c c d
    
            System.out.println("
    含有几个'b' : "+multiset.count("b"));//输出4
            System.out.println("是否包含e' : "+multiset.contains("e"));//输出false
            System.out.println("总size : "+multiset.size());//输出9
    
            //移除i个某元素
            System.out.println("移除1一个元素a");
            multiset.remove("a",1);
            //增加i个某元素
            System.out.println("增加2个元素c");
            multiset.add("c",2);
    
    		//显示集合的不同元素及其出现次数
    		System.out.print("遍历打印出multiset的元素和个数:");
            multiset.entrySet().forEach(entry->System.out.print("元素"+entry.getElement() +"的个数为 " + entry.getCount()+";"));//元素a的个数为 1;元素b的个数为 4;元素c的个数为 4;元素d的个数为 1;
    
        }
    

    七、Bimap接口

    1、定义

    BiMap确保没有重复的值,且可以从value获取key

    2、使用

    关键方法(解释看代码):put、forcePut;inverse

       @Test
        public void BimapTest(){
            BiMap<Integer, String> empIDNameMap = HashBiMap.create();
    
            empIDNameMap.put(101, "Mahesh");
            empIDNameMap.put(102, "Sohan");
            empIDNameMap.put(103, "Ramesh");
            //亮点:如果key已经存在,强制覆盖
            empIDNameMap.forcePut(101, "Mahesh1");
            //亮点:根据值找到key 。inverse():生成value到key的逆视图
            System.out.println(empIDNameMap.inverse().get("Mahesh"));//输出null
            System.out.println(empIDNameMap.inverse().get("Mahesh1"));//输出101
    
            //把所有value转成set集合
            Set<String> values = empIDNameMap.values();
            values.forEach(e-> System.out.print(e+" "));//输出Ramesh Mahesh1 Sohan
        }
    

    八、Bimap接口

    1、定义

    Table代表一个特殊的映射,其中两个键可以在组合的方式被指定为单个值。它类似于创建映射的映射。
    简单点说就是有rowKey,有columnKey,匹配对应value

    2、使用

    关键方法(解释看代码):put、row、rowKeySet、column

     @Test
        public void TableTest(){
    
            //创建一个表
            Table<String, String, String> employeeTable = HashBasedTable.create();
            employeeTable.put("IBM", "101","Mahesh");
            employeeTable.put("IBM", "102","Ramesh");
            employeeTable.put("IBM", "103","Suresh");
    
            employeeTable.put("Microsoft", "101","Sohan");
            employeeTable.put("Microsoft", "102","Mohan");
            employeeTable.put("Microsoft", "103","Rohan");
    
            employeeTable.put("TCS", "121","Ram");
            employeeTable.put("TCS", "122","Shyam");
            employeeTable.put("TCS", "123","Sunil");
    
            //获取某一行的所有列
            Map<String,String> ibmEmployees =  employeeTable.row("IBM");
            System.out.println("rowKey为IBM的这一行的所有列为");
            ibmEmployees.entrySet().forEach(entry ->System.out.println("列字段columnKey: " + entry.getKey() + ", 值value: " + entry.getValue()));//输出列字段columnKey: 103, 值value: Suresh 
     列字段columnKey: 101, 值value: Mahesh 
     列字段columnKey: 102, 值value: Ramesh
    
    
            //获取所有行的rowkey,自动按照字母顺序
            Set<String> employers = employeeTable.rowKeySet();
            System.out.print("所有的rowKey为: ");
            employers.forEach(employer-> System.out.print(employer + "、"));//输出IBM、TCS、Microsoft
    
            //获取某一列的所有行和值
            System.out.println("
    columnKey为102的所有行和值为");
            Map<String,String> EmployerMap =  employeeTable.column("102");
            EmployerMap.entrySet().forEach( entry->System.out.println("行字段rowKey: " + entry.getKey() + ", 值value: " + entry.getValue()));//输出行字段rowKey: IBM, 值value: Ramesh 
     行字段rowKey: Microsoft, 值value: Mohan
        }
    
    

    九、LoadingCache

    1、定义

    在缓存中自动加载值,它提供了许多实用的方法,在有缓存需求时非常有用。
    优点:

    • 线程安全的缓存,与ConcurrentMap相似,但前者增加了更多的元素失效策略,后者只能显示的移除元素。
    • 提供了三种基本的缓存回收方式:基于容量回收、定时回收和基于引用回收。定时回收有两种:按照写入时间,最早写入的最先回收;按照访问时间,最早访问的最早回收。
    • 监控缓存加载/命中情况
    • 集成了多部操作,调用get方式,可以在未命中缓存的时候,从其他地方获取数据源(DB,redis),并加载到缓存中。

    缺点:

    • Guava Cache的超时机制不是精确的。
    • 不能持久化本地缓存

    2、使用

    关键方法(驾驶看代码):getIfPresent、get、put、putAll、invalidate、
    invalidateAll、refresh、size、stats、asMap、

    
    
    public class GuavaTester {
        public static void main(String args[]) {
            //定义一个LoadingCache
            LoadingCache employeeCache = CacheBuilder.newBuilder()
                    .concurrencyLevel(8)//设置并发级别为8,并发级别是指可以同时写缓存的线程数
                    .maximumSize(100) // 设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
                    .expireAfterWrite(10, TimeUnit.MINUTES)//设置写缓存后10分钟后过期
                    .expireAfterAccess(30, TimeUnit.MINUTES) // 设置缓存在访问30分钟后过期
                    .initialCapacity(10) //设置缓存容器的初始容量为10
                    .recordStats() //设置要统计缓存的命中率,开启统计信息开关,
                    .removalListener(notification -> System.out.println("key为"+notification.getKey() + "的缓存被移除了, 因为" + notification.getCause()))//设置缓存的移除通知
                    .build(new CacheLoader() { //build方法中可以指定CacheLoader,,用于从数据源加载数据,在缓存不存在时可自定义策略,比如从数据库获取数据
                        @Override
                        public Object load(Object key) throws Exception {
                            //从数据库拿数据
                            return getFromDatabase(key.toString()); //自定义
                        }
    
                    });
    
    
            try {
                //第一次调用时,缓存没有命中,会从数据库拿数据,如果数据库没有就直接抛异常
                System.out.println("第一次调用:");
                System.out.println(employeeCache.get("100"));//输出Employee(name=Mahesh, dept=Finance, emplD=100)
                System.out.println(employeeCache.get("103"));//输出Employee(name=Rohan, dept=IT, emplD=103)
                System.out.println(employeeCache.get("110"));//输出EmployeeEmployee(name=Sohan, dept=Admin, emplD=110)
                //第二次调用时,直接从缓存中拿
                System.out.println("第二次调用:");
                System.out.println(employeeCache.get("100"));//输出Employee(name=Mahesh, dept=Finance, emplD=100)
                System.out.println(employeeCache.get("103"));//输出Employee(name=Rohan, dept=IT, emplD=103)
                System.out.println(employeeCache.get("110"));//输出EmployeeEmployee(name=Sohan, dept=Admin, emplD=110)
    
                System.out.println("---------------------分割线-----------------------");
                //常用方法
                System.out.println("用getIfPresent获取key为104的值:"+employeeCache.getIfPresent("104"));//获取缓存中key对应的value,如果缓存没命中,返回null
                //如果缓存有值,覆盖,否则,新增
                employeeCache.put("104",new Employee("Aria","Boss","104"));
                //删除缓存
                employeeCache.invalidate("100");
                //获取缓存中元素的大概个数
                System.out.println("获取缓存中元素的大概个数为:"+employeeCache.size());
                //缓存的状态数据,包括(未)命中个数,加载成功/失败个数,总共加载时间,删除个数等。
                System.out.println("缓存的状态数据为:"+employeeCache.stats());//输出CacheStats{hitCount=3, missCount=4, loadSuccessCount=3, loadExceptionCount=0, totalLoadTime=966956, evictionCount=0}
                //asMap()方法获得缓存数据的ConcurrentMap快照
                System.out.println("把LoadingCache转换成concurrentMap:"+ employeeCache.asMap());//输出{103=Employee(name=Rohan, dept=IT, emplD=103), 110=Employee(name=Sohan, dept=Admin, emplD=110)}
                //刷新缓存,即重新取缓存数据,更新缓存
                employeeCache.refresh("110");
                //清除缓存
               employeeCache.invalidateAll();
                //清空所有数据
                employeeCache.cleanUp();
    
    
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    
        //模拟从数据库拿数据
        private static Object getFromDatabase(String empId) {
            //局部变量,取一次,清除一次
            Employee e1 = new Employee("Mahesh", "Finance", "100");
            Employee e2 = new Employee("Rohan", "IT", "103");
            Employee e3 = new Employee("Sohan", "Admin", "110");
    
            Map database = new HashMap();
            database.put("100", e1);
            database.put("103", e2);
            database.put("110", e3);
            System.out.println("从数据库找empId为" + empId);
            return database.get(empId);
        }
    }
    
    @Data
    @AllArgsConstructor
    class Employee {
        private String name;
        private String dept;
        private String emplD;
    }
    
    

    十、Multimap

    1、定义

    可以含有多个一样的key

    2、使用

    关键方法:containsEntry、containsKey、containsValue;get、asMap、keySet、values;add、remove

    
        public static void main(String args[]){
            //初始化一个Multimap
            Multimap<String,String> multimap = ArrayListMultimap.create();
            multimap.put("lower", "a");
            multimap.put("lower", "b");
            multimap.put("lower", "c");
            multimap.put("lower", "d");
            multimap.put("lower", "e");
            multimap.put("upper", "A");
            multimap.put("upper", "B");
            multimap.put("upper", "C");
            multimap.put("upper", "D");
    
            System.out.println("是否包含键值对lower-a:"+multimap.containsEntry("lower", "a"));//输出 true
            System.out.println("是否包含键lower:"+multimap.containsKey("lower"));//输出 true
            System.out.println("是否包含值a:"+multimap.containsValue("a"));//输出 true
            System.out.println("multimap包含键值对数量:"+multimap.size());//输出9
    
            System.out.println("---------------分割线---------------");
    
            List<String> lowerList = (List<String>)multimap.get("lower");
            System.out.println("所有key为lower的值有:"+lowerList.toString());//输出[a, b, c, d, e]
    
            List<String> upperList = (List<String>)multimap.get("upper");
            System.out.println("所有key为lower的值有:"+upperList.toString());//输出[A, B, C, D]
    
            lowerList.add("f");
            upperList.remove("D");
    
            System.out.println("---------------分割线---------------");
    
            Map<String, Collection<String>> map = multimap.asMap();
            System.out.println("遍历整个multimap:");
           map.entrySet().forEach(entry->{
               String key = entry.getKey();
               Collection<String> value =  multimap.get(key);
               System.out.println(key + ":" + value);       //输出lower:[a, b, c, d, e, f] 
      upper:[A, B, C]
           });
    
            System.out.println("---------------分割线---------------");
    
            System.out.println("所有唯一key:");
            Set<String> keys =  multimap.keySet();
            keys.forEach(key-> System.out.print(key+" "));//输出lower upper
    
    
            System.out.println("
    所有的值:");
            Collection<String> values = multimap.values();
            System.out.println(values);//输出[a, b, c, d, e, f, A, B, C]
        }
    
    
  • 相关阅读:
    linux文件系统初探--Day6
    Oracle 内置函数
    libusb常用函数说明(转)
    将多个blv格式的视频合并为一个mp4格式视频
    泰迪杯赛后总结
    如何下载B站上版权受限的视频?
    查看Ubuntu版本信息
    Visual Studio存在多个项目时启动项目的问题
    mfc | 初识mfc
    re | [ACTF新生赛2020]Splendid_MineCraft
  • 原文地址:https://www.cnblogs.com/ranandrun/p/Guava.html
Copyright © 2011-2022 走看看