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("\n把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("\n含有几个'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 \n 列字段columnKey: 101, 值value: Mahesh \n 列字段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("\ncolumnKey为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 \n 行字段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] \n  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("\n所有的值:");
        Collection<String> values = multimap.values();
        System.out.println(values);//输出[a, b, c, d, e, f, A, B, C]
    }
Guava工具类学习的更多相关文章
- 强大的 Guava 工具类
		Java 开发的同学应该都使用或者听说过 Google 提供的 Guava 工具包.日常使用最多的肯定是集合相关的工具类,还有 Guava cache,除了这些之外 Guava 还提供了很多有用的功能 ... 
- 工具篇:介绍几个好用的guava工具类
		前言 平时我们都会封装一些处理缓存或其他的小工具.但每个人都封装一次,重复造轮子,有点费时间.有没有一些好的工具库推荐-guava.guava是谷歌基于java封装好的开源库,它的性能.实用性,比我们 ... 
- Google的Guava工具类splitter和apache stringutil对比 编辑
		一直用的是apache的stringutil工具类,其实google的工具类项目 guava中居然也有字符串的分隔类splitter的,在 http://code.google.com/p/guava ... 
- Guava工具类
		原文链接:http://blog.csdn.net/mnmlist/article/details/53425865 Objects类 Objects类有几个比较不错的方法,toString.hash ... 
- Google guava工具类的介绍和使用
		概述 工具类 就是封装平常用的方法,不需要你重复造轮子,节省开发人员时间,提高工作效率.谷歌作为大公司,当然会从日常的工作中提取中很多高效率的方法出来.所以就诞生了guava.. 高效设计良好的API ... 
- Properties工具类学习
		Properties类学习 1.定义 Properties,java.utils包下的一个工具类,主要用于读取Java的配置文件.各种语言都有自己所支持的配置文件,配置文件中很多变量是经常变动的. 这 ... 
- commons-lang3工具类学习(三)
		六.ObjectUtils Object工具类 allNotNull(Object... values) 检查所有元素是否为空,返回一个boolean 如果有一个元素为空返回false,所有元素不为空 ... 
- commons-lang3工具类学习(二)
		三.BooleanUtils 布尔工具类 and(boolean... array) 逻辑与 BooleanUtils.and(true, true) = true Boolea ... 
- commons-lang3工具类学习(一)
		一.ArchUtils java运行环境的系统信息工具类 getArch();// 获取电脑处理器体系结构 32 bit.64 bit.unknown getType();// 返回处理器类型 ... 
随机推荐
- 源码解读:webdriver client的原理
			前言 又到年底了,群里很多朋友说要开始备战2020金三银四,其实,我建议是,如果你不是技术大牛,就不要去凑热闹. 其实,现在(11,12月份)就是最佳换工作的时候,因为很多人想等着拿了年终再走,虽然招 ... 
- 如何有效的清理yum缓存
			如果遇到下面问题,请执行下面命令 yum clean all #清除缓存 
- MyBatis 插入记录同时获取主键
			MyBatis 插入记录同时获取主键 MyBatis 插入记录同时获取主键的系统界面 useGeneratedKeys 属性 keyProperty 属性 keyColumn 属性 selectKey ... 
- Nginx日志管理(四)
			Nginx日志对于统计.系统服务排错很有用.Nginx日志主要分为两种:access_log(访问日志)和error_log(错误日志).通过访问日志我们可以得到用户的IP地址.浏览器的信息,请求的处 ... 
- c语言命名规范图
			来自armbbs 
- linux的cpu使用率
			linux 上一个核占满是 100%,双核机器占满整个 CPU 是 200% 
- Codechef Prime Distance On Tree
			[传送门] FFT第四题! 暑假的时候只会点分,然后合并是暴力合并的...水过去了... 其实两条路径长度的合并就是卷积的过程嘛,每次统计完路径就自卷积一下. 刚开始卷积固定了值域.T了.然后就不偷懒 ... 
- RaxML使用
			1.下载 https://github.com/stamatak/standard-RAxML 2.How many Threads shall I use? 重要的是要知道,RAxML PThrea ... 
- Umi + Dva的数据传递学习Demo(代码有详细注释)
			刚学习时写了篇笔记,以免自己忘记,用了一段时间后,觉得不如做个demo,代码写上注释,方便也在学习umi-dva的同学们理解更好,更容易上手. 这可能是网上注释最多,看了最易理解的学习小指南吧,哈哈. ... 
- Python程序设计例题
			例一:蒙特卡罗方法求解 π 值 from random import random from math import sqrt from time import clock DARTS=1000 hi ... 
