首页 > 编程语言 >【Java技术专题】「Guava开发指南」手把手教你如何进行使用Guava工具箱进行开发系统实战指南(基础编程篇)

【Java技术专题】「Guava开发指南」手把手教你如何进行使用Guava工具箱进行开发系统实战指南(基础编程篇)

时间:2023-06-08 23:35:52浏览次数:42  
标签:指南 排序 Java int null Objects Guava 方法

【Java技术专题】「Guava开发指南」手把手教你如何进行使用Guava工具箱进行开发系统实战指南(基础编程篇)_前置条件

Guava中的Preconditions(前置条件判断)

Preconditions(前置条件):让方法调用的前置条件判断更简单

Guava在Preconditions 类中提供了若干前置条件判断的实用方法,我们强烈建议在 Eclipse 中静态导入这些方法。每个方法都有三个变种:

  1. 当方法没有额外参数时,抛出的异常中不包含错误消息,这会使得调用方很难确定发生了什么错误。因此,我们应该在抛出异常时,为其提供一个有意义的错误消息。
  2. 当方法有一个 Object 对象作为额外参数时,我们可以使用该对象的 toString() 方法作为错误消息。这样可以保证错误消息能够包含额外参数的信息,方便调用方定位问题。
  3. 当方法有一个 String 对象作为额外参数,并且有一组任意数量的附加 Object 对象时,我们可以采用类似 printf 的方式来处理异常消息。由于考虑到 GWT 的兼容性和效率,我们只支持 %s 指示符。因此,我们可以在错误消息中使用 %s 来表示 String 参数,并使用 String.format() 方法将附加参数格式化为字符串,然后将其插入到错误消息中。

综上所述,无论是否有额外参数,我们都应该为抛出的异常提供有意义的错误消息,以便调用方能够更好地理解和解决问题。在处理异常消息时,我们应该根据具体情况选择合适的方式,以保证代码的可读性和可维护性。

实际代码案例

checkArgument(i >= 0, "Argument was %s but expected nonnegative", i);
checkArgument(i < j, "Expected i < j, but %s > %s", i, j);

判断逻辑参数场景

方法声明(不包括额外参数)

描述

检查失败时抛出的异常

checkArgument(boolean)

检查 boolean 是否为 true,用来检查传递给方法的参数。

IllegalArgumentException

checkNotNull(T)

检查 value 是否为 null,该方法直接返回 value,因此可以内嵌使用 checkNotNull?

NullPointerException

checkState(boolean)

用来检查对象的某些状态。

IllegalStateException

checkElementIndex(int index, int size)

检查 index 作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size

IndexOutOfBoundsException

checkElementIndex(int index, int size)

检查 index 作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size

IndexOutOfBoundsException

checkPositionIndex(int index, int size)

检查 index 作为位置值对某个列表、字符串或数组是否有效。index>=0 && index<=size

IndexOutOfBoundsException

checkPositionIndexes(int start, int end, int size)

检查[start, end]表示的位置范围对某个列表、字符串或数组是否有效

IndexOutOfBoundsException

提示:索引值常用来查找列表、字符串或数组中的元素,如 List.get(int), String.charAt(int) 位置值和位置范围常用来截取列表、字符串或数组,如 List.subList(int,int), String.substring(int) 相比 Apache Commons 提供的类似方法,我们把 Guava 中的 Preconditions 作为首选。

相比其他API的优势和好处

在静态导入后,Guava 方法非常清楚明晰。checkNotNull 清楚地描述做了什么,会抛出什么异常;

  • checkNotNull 直接返回检查的参数,让你可以在构造函数中保持字段的单行赋值风格:this.field = checkNotNull(field)
  • 简单的、参数可变的 printf 风格异常信息。鉴于这个优点,JDK7 已经引入Objects.requireNonNull 的情况下,我们仍然建议你使用checkNotNull。

在编码时,如果某个值有多重的前置条件,我们建议你把它们放到不同的行,这样有助于在调试时定位。此外,把每个前置条件放到不同的行,也可以帮助你编写清晰和有用的错误消息。

Guava中的Preconditions(常见Object方法)

提示:可阐述编程学习方法

equals

当一个对象中的字段可以为 null 时,实现 Object.equals 方法会很痛苦,因为不得不分别对它们进行 null 检查。使用 Objects.equal 帮助你执行 null 敏感的 equals 判断,从而避免抛出 NullPointerException。例如:

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

注意:JDK7 引入的 Objects 类提供了一样的方法 Objects.equals。

hashCode

用对象的所有字段作散列[hash]运算应当更简单。Guava 的 Objects.hashCode(Object...)会对传入的字段序列计算出合理的、顺序敏感的散列值。你可以使用 Objects.hashCode(field1, field2, …, fieldn)来代替手动计算散列值。

注意:JDK7 引入的 Objects 类提供了一样的方法 Objects.hash(Object...)

toString

toString方法在调试时是无价之宝,但是编写 toString 方法有时候却很痛苦。使用 Objects.toStringHelper 可以轻松编写有用的 toString 方法。例如:

// Returns "ClassName{x=1}"
Objects.toStringHelper(this).add("x", 1).toString();
// Returns "MyObject{x=1}"
Objects.toStringHelper("MyObject").add("x", 1).toString();

compare/compareTo

实现一个比较器[Comparator],或者直接实现 Comparable 接口有时也伤不起。考虑一下这种情况:

class Person implements Comparable<Person> {
private String lastName;
private String firstName;
private int zipCode;
public int compareTo(Person other) {
		int cmp = lastName.compareTo(other.lastName);
		if (cmp != 0) {
			return cmp;
		}
		cmp = firstName.compareTo(other.firstName);
		if (cmp != 0) {
			return cmp;
		}
		return Integer.compare(zipCode, other.zipCode);
	}
}

这部分代码太琐碎了,因此很容易搞乱,也很难调试。我们应该能把这种代码变得更优雅,为此,Guava 提供了ComparisonChain。

ComparisonChain

ComparisonChain 执行一种懒比较:它执行比较操作直至发现非零的结果,在那之后的比较输入将被忽略。

public int compareTo(Foo that) {
	return ComparisonChain.start()
		.compare(this.aString, that.aString)
		.compare(this.anInt, that.anInt)
		.compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
		.result();
}

这种Fluent接口风格的可读性更高,发生错误编码的几率更小,并且能避免做不必要的工作。更多 Guava 排序器工具可以在下一节里找到。

Guava中的排序器[Ordering]

Guava 强大的”流畅风格比较器” 是 Guava 流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集 合排序的功能。

从实现上说,Ordering 实例就是一个特殊的 Comparator 实例。Ordering 把很多基于 Comparator 的静态方法(如 Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器。

创建排序器:常见的排序器可以由下面的静态方法创建

方法声明(不包括额外参数)

描述

natural()

对可排序类型做自然排序,如数字按大小,日期按先后排序。

usingToString()

按对象的字符串形式做字典排序[lexicographical ordering]。

natural()

对可排序类型做自然排序,如数字按大小,日期按先后排序。

from(Comparator)

把给定的 Comparator 转化为排序器。

实现自定义的排序器时,除了用上面的 from 方法,也可以跳过实现 Comparator,而直接继承 Ordering:

Ordering<String> byLengthOrdering = new Ordering<String>() {
	public int compare(String left, String right) {
		return Ints.compare(left.length(), right.length());
	}
};

链式调用方法:通过链式调用,可以由给定的排序器衍生出其它排序器

方法声明(不包括额外参数)

描述

reverse()

获取语义相反的排序器。

nullsFirst()

使用当前排序器,但额外把 null 值排到最前面。

nullsLast()

使用当前排序器,但额外把 null 值排到最后面。

compound(Comparator)

合成另一个比较器,以处理当前排序器中的相等情况。

lexicographical()

基于处理类型 T 的排序器,返回该类型的可迭代对象 Iterable的排序器。

onResultOf(Function)

对集合中元素调用 Function,再按返回值用当前排序器排序。

例如,你需要下面这个类的排序器。

class Foo {
	@Nullable String sortedBy;
	int notSortedBy;
}

考虑到排序器应该能处理 sortedBy 为 null 的情况,我们可以使用下面的链式调用来合成排序器:

Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(new Function<Foo, String>() {
	public String apply(Foo foo) {
		return foo.sortedBy;
	}
});

当阅读链式调用产生的排序器时,应该从后往前读。上面的例子中,排序器首先调用 apply 方法获取 sortedBy值,并把 sortedBy 为 null 的元素都放到最前面,然后把剩下的元素按 sortedBy 进行自然排序。之所以要从后往前读,是因为每次链式调用都是用后面的方法包装了前面的排序器。

注:用 compound 方法包装排序器时,就不应遵循从后往前读的原则。为了避免理解上的混乱,请不要把 compound 写在一长串链式调用的中间,你可以另起一行,在链中最先或最后调用 compound。超过一定长度的链式调用,也可能会带来阅读和理解上的难度。我们建议按下面的代码这样,在一个链中最多使用三个方法。此外,你也可以把 Function 分离成中间对象,让链式调用更简洁紧凑。

Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(sortKeyFunction)

运用排序器:Guava的排序器实现有若干操纵集合或元素值的方法。

方法声明(不包括额外参数)

描述

greatestOf(Iterable iterable, int k)

获取可迭代对象中最大的k个元素,相反最小:leastOf。

isOrdered(Iterable)

判断可迭代对象是否已按排序器排序:允许有排序值相等的元素,isStrictlyOrdered。

sortedCopy(Iterable) 判断可迭代对象是否已严格按排序器排序:不允许排序值相等的元素,immutableSortedCopy。


min(E, E)

返回两个参数中最小的那个。如果相等,则返回第一个参数,max(E, E)。

min(E, E, E, E...)

返回多个参数中最小的那个。如果有超过一个参数都最小,则返回第一个最小的参数,max(E, E, E, E...)

min(Iterable)

返回迭代器中最小的元素。如果可迭代对象中没有元素,则抛出 NoSuchElementException,max(Iterable), min(Iterator), max(Iterator)。

下节预告

【Java技术专题】「Guava开发指南」手把手教你如何进行使用Guava工具箱进行开发系统实战指南(异常处理篇)

标签:指南,排序,Java,int,null,Objects,Guava,方法
From: https://blog.51cto.com/alex4dream/6444227

相关文章

  • Java Kafka简单地将Map对象序列化为json
    最近用到kafka,想简单地把Map对象序列化为json发送到主题,直接用string序列化,生成的结果不是json,虽然格式很像,key都没有引号,可能是直接调用的toString方法。但是网上搜了一圈,都是spring组合或者其他不太简单的方案。在哔站看了一段视频受到启发,就实现了一个自定义json序列化类,......
  • 【Java查漏补缺(一)】数组与循环
    除了数组与循环,还有方法,讲究看吧!后续练习内容都是连贯的!BasicalJava看下Java中的变量类型吧!数据类型关键字内存占用二进制位数字节型byte1个字节4位短整型short2个字节8位整型int(常用)4个字节32位长整型long8个字节64位单精度浮点数float......
  • Java_Collections.EMPTY_LIST
     1.背景在某些情况下,我们经常需要发挥一个空的集合对象,比如说在数据查询时,并不需要发挥一个NULL或是异常,那么就可以返回一个空的集合对象。如果你想new一个空的List,而这个List以后也不会再添加元素,那么就用Collections#emptyList()好了。newArrayList()或者newLinked......
  • Java_Timer
     Java_Timer ava.util.Timer是一个实用工具类,该类用来调度一个线程,使它可以在将来某一时刻执行。Java的Timer类可以调度一个任务运行一次,或定期运行。 java.util.TimerTask是一个抽象类,它实现了Runnable接口。我们需要扩展该类以便创建自己的TimerTask,这个TimerTask内部使用jav......
  • 02-前端-javaScript
    文章目录JavaScript1,JavaScript简介2,JavaScript引入方式2.1内部脚本2.2外部脚本3,JavaScript基础语法3.1书写语法3.2输出语句3.3变量3.3.1全局变量var3.3.2局部变量let3.3.3常量const3.4数据类型3.5运算符3.5.1\==和===区别▲3.5.2类型转换3.6流程控制语句3.6.1if......
  • javaWeb核心02-Request&Response -(乱码处理、字符流、字节流、虚拟目录、请求转发、重
    文章目录Request&Response1,Request和Response的概述2,Request对象2.1Request继承体系2.2Request获取请求数据2.2.1获取请求行数据2.2.2获取请求头数据2.2.3获取请求体数据2.2.4获取请求参数的通用方式基于上述理论,request对象为我们提供了如下方法:★代码演示2.3IDEA快速创......
  • Java数据类型、数组
    Java数据类型基本数据类型(8种)byte\short\int\long\;float\double;char\boolean引用数据类型类、数组、接口、枚举、注解、记录一维数组packagecom.study.onearray;publicclassOneArrayTest01{//快捷方式:psvm+回车,快速生成main方法......
  • 讲真,这三道Java入门级面试题,你也不一定能搞定
    下面是一道入门级面试题,这道题基本上都是问初级的小伙伴比较多,但如果你是中级,或者高级。我觉得未必都能回答上来。说说Java语言有哪些特点尽量答出以下几个关键词:1)简单易学。Java有丰富的类库,能够通过静态方法封装,降低API的学习成本,提高工作效率。2)面向对象。这个也是Java最重要的......
  • 给小白讲java中两大怪物,附带面试题!
    类介绍Java程序是由若干个类组成的,类也是面向对象编程思想的具体实现。以下为类的定义:publicclassUser{//私有属性privateLonguserId;privateStringname;privateIntegerage;//构造方法publicUser(){}//有残构造方法publ......
  • 如何吃透一个Java项目?
    现在Austin的文档我觉得还是比较全的,但到了看代码的时候,可能有的同学就不知道应该怎么看,有想知道模块之间的调用链路,有想一点一点把细节给全看了。这时候就很可能在项目里犯迷糊了,绕不出不来了。Java开源项目消息推送平台......