创建List、Map
Before:
ImmutableList
Before:
After:
Iterables.concat()
After:
Constraints.constrainedList()
给List操作注入约束逻辑, 比如添加不合法元素直接报错.
Before:
private
final List
<LineItem
> purchases
=
Constraints.constrainedList(
new ArrayList <LineItem >(),
new Constraint <LineItem >() {
public void checkElement(LineItem element) {
Preconditions.checkState(catalog.isOffered(getAddress(), element.getProduct()));
Preconditions.checkState(element.getCharge().getUnits() > 0 );
}
});
/**
* Returns the modifiable list of purchases in this order.
*/
public List <LineItem > getPurchases() {
return purchases;
}
new ArrayList <LineItem >(),
new Constraint <LineItem >() {
public void checkElement(LineItem element) {
Preconditions.checkState(catalog.isOffered(getAddress(), element.getProduct()));
Preconditions.checkState(element.getCharge().getUnits() > 0 );
}
});
/**
* Returns the modifiable list of purchases in this order.
*/
public List <LineItem > getPurchases() {
return purchases;
}
不允许插入空值的Set(Constraints的用法):
MultiMap
如果一个key对应多个value的Map, 你会怎么处理? 如果还在使用Map<K, List<V>>的话, 你就out了
使用MultiMap吧:
使用MultiMap吧:
0 siblings frequency 1
1 siblings frequency 1
2 siblings frequency 1
3 siblings frequency 2
4 siblings frequency 0
5 siblings frequency 1
1 siblings frequency 1
2 siblings frequency 1
3 siblings frequency 2
4 siblings frequency 0
5 siblings frequency 1
BiMap(双向map)
Before:
After:
换一种写法:
排序
-
ComparisonChain
compareTo
傳回 1、0、-1 分別來告訴它,順序上物件比另一物件大、相等或小。
用三個值來表示順序,蠻方便的,不是嗎?並不是!有多少次你弄錯了1、0、-1 的意義呢?實際上,排序的要求還蠻多的,例如你可能想要排序時先依某人的姓來排,如果姓相同再依名來排,如果姓名都相同,再依他們居住地的郵遞區號來排,那你就可能會寫出像 compare/compareTo 中的程式碼:
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)
}
}
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)
}
}
你覺得
compareTo
好讀嗎?如果你學過 SQL,應該知道有
ORDER BY
這東西,相較之下,
compareTo
的邏輯並不清楚,如果你使用 Guava 的
ComparisonChain
,可以寫成這樣:
import com.google.common.collect.ComparisonChain;
class Person implements Comparable <Person > {
private String lastName;
private String firstName;
private int zipCode;
public int compareTo(Person other) {
return ComparisonChain.start()
. compare(lastName, other.lastName)
.compare(firstName, other.firstName)
.compare(zipCode, other.zipCode)
.result();
}
}
class Person implements Comparable <Person > {
private String lastName;
private String firstName;
private int zipCode;
public int compareTo(Person other) {
return ComparisonChain.start()
. compare(lastName, other.lastName)
.compare(firstName, other.firstName)
.compare(zipCode, other.zipCode)
.result();
}
}
|
ComparisonChain
的 start
與 compare
都會傳回 ComparisonChain
實例,在最後 result
計算結果時,就如原先 compareTo
的實作,會逐一比較要比較的對象,只要它們各自的 compareTo
不為 0 時就傳回結果。
-
Ordering
Ordering 本身就是Comparator,這看看它的類別定義就知道了:
public
abstract
class
Ordering<T>
extends
Object <strong>
implements
Comparator<T>
Collections.sort(names,
Ordering.natural().reverse().nullsFirst()
.onResultOf( new Function <String, Integer >() {
@Override
public Integer apply(String p) {
return p == null ? null : p.length();
}
})
);
Ordering.natural().reverse().nullsFirst()
.onResultOf( new Function <String, Integer >() {
@Override
public Integer apply(String p) {
return p == null ? null : p.length();
}
})
);
或者结合Java8 中的Lambda表达式:
Collections.sort(names,
Ordering.natural().reverse().nullsFirst()
.onResultOf(p - > p == null ? null : p.length())
);
Ordering.natural().reverse().nullsFirst()
.onResultOf(p - > p == null ? null : p.length())
);
public Ordering onResultOf(Function function)
{
return new ByFunctionOrdering(function, this);
}
final class ByFunctionOrdering extends Ordering {
ByFunctionOrdering(Function function, Ordering ordering)
{
this.function = (Function)Preconditions.checkNotNull(function);
this.ordering = (Ordering)Preconditions.checkNotNull(ordering);
}
public int compare(Object left, Object right)
{
return ordering.compare(function.apply(left), function.apply(right));
}
-
Comparators.fromFunction()
Before:
After: (感觉也没省多少):
Ranges
Range
的一些 static
方法與範圍的對照為:
(a..b) |
{x | a < x < b} |
open |
[a..b] |
{x | a <= x <= b} |
closed |
(a..b] |
{x | a < x <= b} |
openClosed |
[a..b) |
{x | a <= x < b} |
closedOpen |
(a..+∞) |
{x | x > a} |
greaterThan |
[a..+∞) |
{x | x >= a} |
atLeast |
(-∞..b) |
{x | x < b} |
lessThan |
(-∞..b] |
{x | x <= b} |
atMost |
(-∞..+∞) |
{x} |
all |
實際上,範圍不是數列,也就是像 Range.closed(1, 20)
並沒有實際產生 1、2 ... 20
的整數數列,它就僅僅只是個…呃…範圍!如果想要取得的是範圍中的數字,那麼可以透過 ContiguousSet
類別 static
的 create
方法,呼叫時必須指定
Range
物件及一個 DiscreteDomain
物件,DiscreteDomain
物件定義了指定的範圍中,不連續元素間的關係以及 DiscreteDomain
的邊界。
例如,結合 由於經常打算取得的是整數,因此
DiscreteDomain
提供了 integers
、 longs
以及支援大數的 bigIntegers
三個 static
方法。Range
與 DiscreteDomain
來迭代 1 到 20 的數字,可以如下撰寫:
for(
int i
: create(Range.closed(
1,
20), integers())) {
// 做些事 ...
}
// 做些事 ...
}