作者:Jack47

转载请保留作者和原文出处

欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源

本文是我写的Google开源的Java编程库Guava系列之一,主要介绍Guava中提供的很多小工具类,这些类让Java语言用起来更舒畅。

使用或者避免null值##

null引用的发明者Sir C.A.R.Hoare(也是快排算法的发明者)把null称之为十亿美元错误。Guava的开发者们通过研究Google的代码发现95%的集合中都不需要支持为null的值,所以对于开发者而言,遇到null时需要快速失败而不是默默地接受nullnull的含义在大部分场景下都不够清晰,例如Map.get(key)返回null时,可能是因为map中的值就是null,或者map中没有这个key。但null在有些情况下也很有用,从内存和性能方面来看,null很廉价,在使用对象数组,是不可避免的要用到null的。综合考虑之后,Guava库中绝大部分工具都被设计成遇到null时快速失败。

Optional

如果程序员需要使用null来表示不存在的情况,那么Optional<T>就能派上用场了。Optional<T>是用非null的值来代替一个可能为null的值。举个例子:

Optional<Integer> possible = Optional.of(null);
boolean isPresent = possible.isPresent(); // returns false

再看这个例子:

Optional<Integer> possible = Optional.of(5);
boolean isPresent = possible.isPresent(); // returns true
possible.get(); // returns 5

聪明的读者已经发现了,Optional是一个容器对象,它可能容纳一个非null的值,也可能没有值。如果这个值存在,isPresent()函数会返回true而且get()函数会返回这个值。

引入Optional类除了因为给null一个有意义的名字而增加了可读性外,最大的好处是Optional能够强制你主动思考程序中值不存在的情况,而null是很容易被忽略的。如果值不存在,想使用默认值,可以使用Optional中提供的T or(T)函数,例如:

Optional<Integer> default = Optional.of(0);
Optional possible = Optional.of(field);
return possible.or(default)

如果field为null,那么返回值就是default,调用者需要先判断值是否存在isPresent(),如果存在,再拿到值get()

Strings类提供了值可能为null的一些函数,例如:

boolean invalid = Strings.isNullOrEmpty(res);
String name = Strings.emptyToNull(passedName);

Preconditions(先决条件)##

Preconditions类中提供了几个非常实用的静态函数来帮助检查调用函数或构造函数时的先决条件是否满足。这些函数都接受一个boolean类型的表达式,如果表达式为false,会抛出一个非受检异常,来通知调用方发生了调用错误。

Preconditions类的目的是提高代码的可读性,例如checkArgument(i >=0 , "Argument was %s but expected nonnegative", i);,一看就知道是在检查传入的参数;this.field = checkNotNull(field),是检查field字段不为空。这里需要注意提供的错误信息需要清晰有效。

对象的通用函数##

使用这些函数能够简化实现对象函数的过程,例如hashCode()toString()函数

equal函数###

如果对象内部变量可以为null,实现equal函数有些费劲,因为需要单独检查nullObjects.equal函数已经实现了对null敏感的检查,不会出现NullPointerException的异常。

Objects.equal("a", "a"); //returns true
Objects.equal(null, "a"); // returns false
Objects.equal(null, null); // returns true

注:最新的JDK 7里引入了Ojbects类,提供了同样的函数。

hashCode函数###

平常实现hashCode函数是不是很痛苦?如果类内部的成员变量较多,代码就会比较冗长。Guava提供了Objects.hashCode(field1, field2,...,fieldn)的函数,它能够对指定顺序的多个字段进行哈希,这样就不用自己手工实现一遍对各个字段进行哈希的过程了。举个栗子:

return Objects.hashCode(name, address, url);

toString函数

toString在日志和调试中发挥巨大威力,但是实现起来很麻烦,需要注意各个有用字段输出时的组织格式。来看看MoreObjects.toStringHelper如何让整个过程变的简单:

// return "MyObject{x=1,y=2}
Objects.toStringHelper(this)
.add("x", 1)
.add("y", 2)
.toString();

compare/compareTo函数

实现比较器(Comparator),或者实现Comparable接口时,通常需要对类内部的所有成员变量进行比较,实现起来很麻烦。Guava提供了ComparisonChain类,它能够进行"懒"比较:只有当发现为0的结果,才会继续后面的结果,不然就忽略后续的比较。举个例子:

public int compareTo(Foo other) {
return ComparisonChain.start()
.compare(this.x, other.x)
.compare(this.y, other.y)
.result();
}

Ordering

Guava提供了一个流畅型(fluent)的比较器(Comparator)类:Ordering,它提供了链条函数来微调或者增强已有的比较器,或者构造复杂的比较器,应用到对象的集合上。

Ordering的核心是一个Comparator实例。使用已有的比较器来构造一个Ordering实例:

Ordering<Item> ordering = Ordering.from(Comparator<Item> comparator);

也可以使用自然顺序: Ordering<T>.natural()

或者自己实现一个Ordering类,只需要继承并实现compare()函数就可以。

Ordering进行微调:

reverse()
compound(Comparator)
onResultOf(Function)
nullsFirst()

由于Ordering类继承自Comparator,所以在任何需要Comparator的地方,都可以使用Ordering代替,同时Ordering提供了一些操作:

immutableSortedCopy()
isOrdered()/ isStrictlyOrdered()
min()

字符串相关的函数

合并(Joiner)

流畅风格的Joiner提供了使用分隔符把一些字符串序列合并到一起的功能。例如:

Joiner joiner = Joiner.on("; ").skipNulls();
// returns "Harry; Ron; Hermione
return joiner.join("Harry", null, "Ron", "Hermione");

如果不想跳过值为null的字符串,想用某个特定字符串代替null,可以使用函数useForNull(String)

Joiner类也可以用在其他对象类型上,此时会使用对象的toString()函数得到字符串,然后进行合并。

切分(Splitter)

Java的字符串分割函数有一些诡异的行为,例如String.split()函数会默默地把尾部的分隔符丢弃掉。而使用Splitter的好处在于可以完整地显示地控制这些行为。Splitter类可以用来在任意的Pattern, char, String或者CharMatcher上进行分割。举个例子:

// returns ["foo", " bar", "", "   qux", ""]
Splitter.on(',').split("foo, bar,, qux,");

Splitter还提供了其他的配置函数来对合并过程进行定制:omitEmptyStrings(),trimResults(), limit()等。例如对于上面的例子,如果想忽略空字符串,让结果中去掉开头和结尾的空格,可以这样做:

// returns ["foo","bar","qux"]
Splitter.on(',')
.trimReults()
.omitEmptyStrings()
.split("foo, bar,, qux,");

注意:SplitterJoiner实例都是不可变的(immutable),所以SplitterJoiner都是线程安全的,可以声明为static final的常量来使用。他们的配置函数都是返回一个新的Splitter实例,此时需要使用返回的新的Splitter的实例。

字符匹配(Character Matchers)

CharMatcher类的设计思想很巧妙,定义两个基本属性,然后任意组合他们。这样API的复杂度是线性增加的,但是灵活性和功能是平方式增强的。

CharMatcher定义的两个属性:

  1. 需要匹配什么样的字符串?
  2. 在这些匹配的字符串上执行什么样的操作?例如 trimming,collapsing, removing等。

一些例子:

	// remove control characters
String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(inputString);
// only the digits
String theDigits = CharMatcher.DIGIT.retainFrom(inputString);
// eliminate all characters that aren't digits or lowercase
String lowerAndDigit = CharMatcher.JAVA_DIGIT.or(CharMatcher.JAVA_LOWER_CASE).retainFrom(inputString);
// trim whitespace and replace/collapse whitespace into single spaces
String spaced = CharMatcher.WHITESPACE.trimAndCollapseFrom(inputString, ' ');

认真的读者通过看上面的例子会发现CharMatcher已经提供了很多现成的匹配特定字符串的常量,例如WHITESPACE,JAVA_DIGIT等。也可以通过其他几个函数来构造匹配特定字符串的CharMatcher:

is(char);
isNot(char);
negate()
inRange(char, char)
or(CharMatcher);
and(CharMatcher);

可以在CharMatcher上执行的操作

boolean matchesAllOf(CharSequence)
boolean matchesAnyOf(CharSequence)
boolean matchesNoneOf(CharSequence)
int indexIn(CharSequence, int)
int countIn(CharSequence)
String removeFrom(CharSequence)
String retainFrom(CharSequence)
String trimFrom(CharSequence)
String replaceFrom(CharSequence, char)

Charsets

Charsets类提供了Java平台的所有实现中都支持的六个标准的字符集的常量引用。所以不要这样做:

try {
bytes = content.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}

而是用下面的代码替代:

bytes = content.getBytes(Charsets.UTF_8);

注:JDK7中StandardCharsets类已经实现了同样功能

基本类型相关的函数

Java中Arrays类提供了众多对数组进行操作的函数,基础类型对应的包装类例如Integer,也提供了很多使用函数。而Guava为Java中的8个基本类型提供了其他一些非常实用的函数,例如数组和集合相关的API,从类型转换到byte数组的表示方式等。

例如:

int[] content = {1,3,4};
Ints.indexOf(content, 3); // 1
Ints.concat(new int[] {1,2}, new int[]{3, 4}) // 1,2,3,4
Ints.contains(new int[]{10,20,30,40}, 20) // true
Ints.min(10,20,30,40) // 10
byte[] bytes = Ints.toByteArray(integer);

回到本系列目录: Google Java编程库Guava介绍


如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!

资助Jack47写作,打赏一个鸡蛋灌饼钱吧
微信打赏
支付宝打赏

Guava库介绍之实用工具类的更多相关文章

  1. C++ 之Boost 实用工具类及简单使用

    本文将介绍几个 Boost 实用工具类,包括 tuple.static_assert.pool.random 和 program_options等等.需要对标准 STL 具备一定的了解才能充分理解本文 ...

  2. 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

    一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...

  3. java Http消息传递之POST和GET两种方法--通过实用工具类来获取服务器资源

    实现该方法需要导入一些jar包 可以去一下地址下载: http://pan.baidu.com/s/1hqrJF7m /** * 实用工具类来获取服务器资源 * * get方法传送数据 * * 1.通 ...

  4. Java日期时间实用工具类

    Java日期时间实用工具类 1.Date (java.util.Date)    Date();        以当前时间构造一个Date对象    Date(long);        构造函数   ...

  5. [Google Guava] 2.4-集合扩展工具类

    原文链接 译文链接 译者:沈义扬,校对:丁一 简介 有时候你需要实现自己的集合扩展.也许你想要在元素被添加到列表时增加特定的行为,或者你想实现一个Iterable,其底层实际上是遍历数据库查询的结果集 ...

  6. Guava库介绍之集合(Collection)相关的API

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是我写的Google开源的Java编程库Guava系列之一,主要介 ...

  7. [Guava学习笔记]Collections: 集合工具类

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3861431.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  8. 实用工具类--第三方开源--Lazy

    下载地址 :https://github.com/ddwhan0123/Lazy 工具 描述 AnimationUtils 动画工具类 AppUtils APP相关信息工具类 AssetDatabas ...

  9. SpringMvc 中的实用工具类介绍(包括 ResponseEntity、 RestTemplate、WebUtils 等)

    此部分内容将包含 ResponseEntity. RestTemplate.WebUtils 等 1. ResponseEntity ① Sprring Mvc 中作为方法的返回值使用法 @Reque ...

随机推荐

  1. ExtJS 4.2 评分组件

    上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...

  2. ImageView缩放选项

    ImageView.ScaleType 将图片边界缩放到所在view边界时的缩放选项. Options for scaling the bounds of an image to the bounds ...

  3. json与JavaScript对象互换

    1,json字符串转化为JavaScript对象: 方法:JSON.parse(string) eg:var account = '{"name":"jaytan&quo ...

  4. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

  5. LeetCode 7. Reverse Integer

    Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 Have you ...

  6. 用神奇的currentColor制作简洁的颜色动画效果

    先上一个兼容性总结图:老版本ie可以直接用复杂方法了,套用某表情包的话:  2016年了,做前端你还考虑兼容IE6?你这简直是自暴自弃! 好了,知道了兼容性,我们可以放心的使用了. 在CSS3中扩展了 ...

  7. MongoDB集群配置

    本文演示:(一个主服务器,一个备份服务器,三个仲裁服务器) 官方推荐副本集的成员数量为奇数,最多12个副本集节点,最多7个节点参与选举. 本文演示基于本机,用端口区分服务(每个服务器下新建db文件夹用 ...

  8. python中IndentationError: expected an indented block错误的解决方法

    IndentationError: expected an indented block 翻译为IndentationError:预期的缩进块 解决方法:有冒号的下一行要缩进,该缩进就缩进

  9. Nginx反向代理,负载均衡,redis session共享,keepalived高可用

    相关知识自行搜索,直接上干货... 使用的资源: nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换. tomcat服务器两台,由nginx进行反向代理和负载均衡,此 ...

  10. 纯javaScript、jQuery实现个性化图片轮播

    纯javaScript实现个性化图片轮播 轮播原理说明<如上图所示>: 1. 画布部分(可视区域)属性说明:overflow:hidden使得超出画布部分隐藏或说不可见.position: ...