GuavaとJava7

# はじめに

ちょっと前になりますが、ADTが一部を除いてJava7に対応しましたね。
(try-with-resourcesはminSdkVersionの19のようですね。)

ADTプラグインの説明の[22.6.0の説明](http://developer.android.com/tools/sdk/eclipse-adt.html)
こちらのブログがとても分かりやすく書かれています。[(切り身こわい)](http://d.hatena.ne.jp/kirimin/20140310/1394469046)


さて、話は変わってGoogle製のJavaライブラリ、[Guava](https://code.google.com/p/guava-libraries/)。
Androidでも、Android以外でもJavaでの開発に使っている方も多いのではないでしょうか？
先日、Google+の[Guava公式アカウント](http://plus.google.com/+googleguava)が[Guava APIs obsoleted by JDK7](http://plus.google.com/+googleguava/posts/TtFEKhU8qnG)というタイトルで投稿をしていました。

以下、[Guava APIs obsoleted by JDK7](http://plus.google.com/+googleguava/posts/TtFEKhU8qnG)より
>
While Guava doesn't require JDK7, there are a bunch of Guava APIs that have been obsoleted by JDK7. If you're using JDK7, you should prefer the built-in JDK7 APIs over the Guava APIs; at some point, we may remove these APIs from Guava. Here’s a list of obsoleted Guava APIs and their JDK replacements:
>
-instead of c.g.c.base.Charsets.UTF_8, prefer java.nio.charset.StandardCharsets.UTF_8 (same goes for the other constants in our Charsets class)
-instead of c.g.c.base.Objects.equal(), prefer java.util.Objects.equals()
-instead of c.g.c.base.Objects.hashCode(), prefer java.util.Objects.hash()
-instead of c.g.c.collect.Iterators.emptyIterator(), prefer java.util.Collections.emptyIterator()
-instead of c.g.c.primitives.Booleans.compare(), prefer java.lang.Boolean.compare() (same goes for the other compare() methods in our primitive wrapper classes)
-instead of the static factory methods for creating collections (e.g. Lists.newArrayList()), prefer the constructors with the diamond operator (e.g., new ArrayList<>())
>
JDK8 obsoletes a ton of Guava APIs, so we’re hard at work figuring out what a JDK8-friendly version of Guava will look like!


なるほど。
よく使うものが並んでいますね。
こちらの投稿に関するコメントで大変勉強になるものがいくつかあったので、そこで言われていたことに、自分の考えを追加してまとめました。

Objects#equalとLists#newArrayListは、無くなっちゃ悲しいし、Guavaの方が便利ですね。
という話です。

# GuavaのObjects#equalとJava7のObjects#equals


次のようなコードがあるとします、

```java:
String a = getString();
String b = getString();
if(a.equals(b)){
// 略
```

この場合getStringがnullを返し得るならば、aがnullの場合NullPointerExceptionになってしまうので、nullでないか事前のチェックが必要です。

このようにオブジェクトがnullの場合まで含めたequlasの比較はGuavaのObjects#equalメソッドが便利です。

次のコードはGuavaのObjects.equalの使用例です。

```GuavaのObjects.equal
System.out.println(Objects.equal("hoge", "hoge")); // true
System.out.println(Objects.equal(null, "hoge")); // false
System.out.println(Objects.equal("hoge", null)); // false
System.out.println(Objects.equal(null, null)); // true
```

```java:GuavaのObjects.equalを使う
String a = getString();
String b = getString();
if(Objects.equal(a,b)){
// 略
// ただしaもbもnullな場合真なことに注意
```

このObjects.equalはObjectのメソッドは、equalsメソッドをオーバーライドする際にも大変役立ちます。

さて、Java7にはjava.lang.Objectsクラスにequalsというメソッドがあります。

Guavaのcom.google.common.base.Objectsの[equalメソッド](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Objects.html#equal(java.lang.Object, java.lang.Object))
Java7のjava.lang.Objectsクラスの[equalsメソッド](http://docs.oracle.com/javase/jp/7/api/java/util/Objects.html#equals(java.lang.Object, java.lang.Object))

どちらも二つのObject型の引数をとり、nullの対処も同じです。

非常に良く似ていますが、大きな違いがあります。GuavaはequalでJava7はequalsです。sの違いです。このsによって、あることがGuavaではできますが、Java7ではできません。

メソッドのstaticインポートです。
Javaのすべてのクラスの親クラス[Object](http://docs.oracle.com/javase/7/docs/api/)クラス。このクラスはいくつかのメソッドを持っていますが、Object型一つを引数にとるequlsもその一つです。

そのため、Java7のequalsメソッドはstaticインポートが書けません。それに比べて、Guavaはstaticインポートが可能です。


```java:com.google.common.base.Objects#equal
import static com.google.common.base.Objects.equal;

//略
Hoge a = createHoge();
Hoge b = createHoge();
if(equal(a,b)) { // staticインポートしているので、equalだけの記述でOK
	// anything TODO
}
```

```java:java.lang.Objectsクラス#equals
Hoge a = createHoge();
Hoge b = createHoge();
if(Objects.equals(a,b)) { // 「if(equals(a, b))」はコンパイルエラー
	// anything TODO
}
```

まぁ、正直次のやつにくらべたら無くなっても、いいかなという感じですが．．．

# GuavaのLists#newArrayListとJava7で導入されたダイヤモンドオペレーター

Java7はダイヤモンドオペレーターにより次のように、型の記述がすこし簡略化できるようになりました。

```java:ダイヤモンドオペレーターを使う
List<String> list = new ArrayList<>();
```

実は、GuavaのLists#newArrayListも型推論をしてくれるので、インスタンス化の方の型の記述をしなくてもいいです。

```java:GuavaのLists#newArrayList
List<String> list = Lists.newArrayList();

// 上記メソッドをstaticインポートすれば
// List<String> list = newArrayList();
// でいい。
```

これだけであればわざわざGuavaを導入しなくても、単純にダイヤモンドオペレーターを使えば良いとも思えるのですが、GuavaのLists#newArrayListには、次のように初期化できるオーバーロードが用意されています。

```java:GuavaのLists#newArrayListで初期化
List<Strng> list = Lists.newArrayList("H", "e", "l", "l", "o");
// static importすれば、 
// List<String> list = newArrayList("H", "e", "l", "l", "o");
```

このように簡潔に初期要素こみのListのインスタンスを作成できます。
ArrayListのコンストラクタには、このように簡潔にインスタンス化できるものは無いです。コンストラクタは、

* 引数なし
* int型 (初期容量指定)
* Collectionを実装した型 (初期要素指定)

の3個です。3個目のCollectionを実装した型を引数に取るものを使ったとしても、次のように書く必要があります。

```java:
List<String> list = new ArrayList<>(Arrays.asList("H","e","l","l","o"));
```


(ちなみにArrays.asListもListインターフェースを実装したインスタンスを作成しますが、addメソッドなどを呼び出すと、UnsupportedOperationExceptionを投げます。)
(参考：Java7の[ArrayListのAPIリファレンス](http://docs.oracle.com/javase/jp/7/api/java/util/ArrayList.html))

ちなみにC#では次のように、Listを初期化できます。

```csharp:C#のリストの初期化
var list = new List<string> {"H", "e", "l", "l", "o"};
```
Groovyもリストのインスタンス化は、次のような便利な記法が用意されています。

```groovy:Groovyのリストの初期化
def list = ["H", "e", "l", "l", "o"]
```

Javaのリストの初期化は少々冗長です。ダイヤモンドオペレーターで少しは短くなりましたが、GuavaのLists#newArrayListを使うとさらに短くすることが可能ですね。


# その他投稿にあったもの
## c.g.c.base.Charsetsとjava.nio.charset.StandardCharsets

InputStreamReaderクラスなどの初期化に用いるCharset型の定数です。

```java:
new InputStreamReader(new FileInputStream(file),StandardCharsets.UTF_8)
// or
new InputStreamReader(new FileInputStream(file), Charsets.UTF_8)
```

参考:[Where to get “UTF-8” string literal in Java?](http://stackoverflow.com/questions/6698354/where-to-get-utf-8-string-literal-in-java)
参考:[java.nio.charset.StandardCharsets](http://docs.oracle.com/javase/7/docs/api/java/nio/charset/StandardCharsets.html)
参考:[com.google.common.base.Charsets](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Charsets.html)


## c.g.c.base.Objects.hashCode()とjava.util.Objects.hash()

どちらもhashCodeを作る便利メソッドで、内部的にArrays.hashCode(Object[])が呼ばれるようですね。

これはequalsと逆で、Guavaのメソッドの方がObjectのほうと同じメソッド名でjava.utils.Objectsの方が違うメソッド名ですね。そのため、java.utils.Objectsのhashメソッドの方はstaticインポート可能ですね。

参考:[java.util.Objects#hash](http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html#hash(java.lang.Object...))
参考:[com.google.common.base.Objects#hashCode](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Objects.html#hashCode(java.lang.Object...))


## c.g.c.collect.Iterators.emptyIterator()とjava.util.Collections.emptyIterator()

自作コレクションなどに使うのでしょうか？

ちなみに、java.util.Collections.emptyList()やjava.util.CollectionsCollections.emptyMap()もありました。どちらも、add・putしたら、UnsupportedOperationExceptionが発生しました。

参考:[java.util.Collections#emptyIterator](http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#emptyIterator())
参考:[com.google.common.Iterators#emptyIterator](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Iterators.html#emptyIterator())

## プリミティブ型のラッパークラスのcompareメソッド
Guavaはcom.google.common.primitivesという名前空間にBooleans、Ints、Doublesなど、プリミティブ型の便利クラスがあります。

com.google.common.primitives.Booleans.compareのドキュメントには、
Java7以降ならjava.lang.Boolean.compareを使おうとありました。

参考:[com.google.common.primitives.Booleans#compare](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/primitives/Booleans.html#compare(boolean, boolean))
参考:[java.lang.Boolean#compare](http://docs.oracle.com/javase/7/docs/api/java/lang/Boolean.html?is-external=true#compare(boolean, boolean))

# Guavaについての分かりやいページ

* [guava-libraries 公式](https://code.google.com/p/guava-libraries/)
* Qiita(@disc99 さん) [Javaの便利ライブラリ Google Guava](http://qiita.com/disc99/items/c4b98045fc4682cbb620)

* eller's blog [Guavaをざっくり紹介](http://eller86.hatenablog.jp/entry/20111112/1321107160)

* プログラマ的京都生活 [guava](http://d.hatena.ne.jp/mtoyoshi/20100725/1280040233)

* しかじろうがなんか作るよ [Google製Javaライブラリ Guavaを使ってみた。]
(http://shikajiro.github.io/blog/2013/03/03/java-guava/)


# まとめ

やっぱり、Guava便利ですね。
Java7で加わったメソッドも要チェックですね。