Reference
Optional
Optional 可以用來處理 null value 與避免 NullPointerException
public class OptionalTest { @Test public void test() { try { Optional.of(null); Assert.fail("Optional.of shouldn't accept null"); } catch (NullPointerException ex) { } Optional opt = Optional.of("Test"); Assert.assertTrue(opt.isPresent()); Assert.assertEquals("Test", opt.get()); Assert.assertEquals("Test", opt.or("QQ")); Assert.assertEquals("Test", opt.orNull()); Assert.assertEquals(ImmutableSet.of("Test"), opt.asSet()); Optional nullableOptional = Optional.fromNullable(null); Assert.assertFalse(nullableOptional.isPresent()); try { Assert.assertNull(nullableOptional.get()); Assert.fail(); } catch (IllegalStateException ex) { } Assert.assertEquals("QQ", nullableOptional.or("QQ")); Assert.assertNull(nullableOptional.orNull()); Assert.assertEquals(ImmutableSet.of(), nullableOptional.asSet()); Assert.assertEquals(Optional.absent(), nullableOptional); } }
ComparisonChain
ComparisonChain 可以用比較漂亮的程式實作 comparepublic class ComparisonChainTest { @Test public void test() { NumbersObject n1 = new NumbersObject(1,2,3); NumbersObject n2 = new NumbersObject(1,2,4); NumbersObject n3 = new NumbersObject(1,3,4); NumbersObject n4 = new NumbersObject(2,2,4); List<NumbersObject> list = Arrays.asList(n4, n3, n2, n1); Collections.sort(list, (o1, o2) -> ComparisonChain.start() .compare(o1.a,o2.a) .compare(o1.b,o2.b) .compare(o1.c,o2.c) .result()); Assert.assertTrue(n1 == list.get(0)); Assert.assertTrue(n2 == list.get(1)); Assert.assertTrue(n3 == list.get(2)); Assert.assertTrue(n4 == list.get(3)); } final static class NumbersObject { private final int a ; private final int b; private final int c; NumbersObject(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } } }
Ordering
Ordering 其實就是 Comparator, 可以傳給 Collections. 例如: Collections.sort(list, Ordering)usingToString
用 toString 的結果排序@Test public void usingToString() { NumbersObject n1 = new NumbersObject(1, 2, 3); NumbersObject n2 = new NumbersObject(1, 2, 4); NumbersObject n3 = new NumbersObject(-1, 2, -3); NumbersObject n4 = new NumbersObject(-2, 3, 5); List<NumbersObject> numbers = Arrays.asList(n1, n2, n3, n4); Collections.sort(numbers, Ordering.usingToString()); Assert.assertEquals(n3, numbers.get(0)); Assert.assertEquals(n4, numbers.get(1)); Assert.assertEquals(n1, numbers.get(2)); Assert.assertEquals(n2, numbers.get(3)); } private final class NumbersObject { public final Integer a; public final Integer b; public final Integer c; public NumbersObject(Integer a, Integer b, Integer c) { this.a = a; this.b = b; this.c = c; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("a",a) .add("b",b) .add("c",c) .toString(); } }
nullsFirst & nullsLast
排序的時候, null 放在最前面位置(或最後).物件本身是 Comparable, 可以直接拿 nullsFirst 回傳的 Ordering 來排序, 若物件本身不是 Comparable 就要提供排序的方式
@Test public void nullsFirst_NotComparable() { NumbersObject n1 = new NumbersObject(1, 2, 3); NumbersObject n2 = new NumbersObject(1, 2, 4); NumbersObject n3 = new NumbersObject(-1, 2, -3); NumbersObject n4 = new NumbersObject(-2, 3, 5); NumbersObject nullNumber = new NumbersObject(null,null,null); List<NumbersObject> numbers = Arrays.asList(n1, n2, n3, n4, nullNumber); Ordering ordering = Ordering.natural().nullsFirst().onResultOf(new Function<NumbersObject, Integer>() { @Override public Integer apply(NumbersObject numbersObject) { return numbersObject.a; } }); Collections.sort(numbers, ordering); Assert.assertEquals(nullNumber, numbers.get(0)); Assert.assertEquals(n4, numbers.get(1)); Assert.assertEquals(n3, numbers.get(2)); Assert.assertEquals(n1, numbers.get(3)); Assert.assertEquals(n2, numbers.get(4)); } @Test public void nullsFirst_Comparable() { List<Integer> list = Arrays.asList(5, 2, 6, 7, 3, null); Collections.sort(list, Ordering.natural().nullsFirst()); Assert.assertEquals((Integer) null, list.get(0)); Assert.assertEquals((Integer) 2, list.get(1)); Assert.assertEquals((Integer) 3, list.get(2)); Assert.assertEquals((Integer) 5, list.get(3)); Assert.assertEquals((Integer) 6, list.get(4)); Assert.assertEquals((Integer) 7, list.get(5)); } @Test public void nullsLast_Comparable() { List<Integer> list = Arrays.asList(5, 2, 6, 7, 3, null); Collections.sort(list, Ordering.natural().nullsLast()); Assert.assertEquals((Integer) 2, list.get(0)); Assert.assertEquals((Integer) 3, list.get(1)); Assert.assertEquals((Integer) 5, list.get(2)); Assert.assertEquals((Integer) 6, list.get(3)); Assert.assertEquals((Integer) 7, list.get(4)); Assert.assertEquals((Integer) null, list.get(5)); } @Test public void nullsLast_NotComparable() { NumbersObject n1 = new NumbersObject(1, 2, 3); NumbersObject n2 = new NumbersObject(1, 2, 4); NumbersObject n3 = new NumbersObject(-1, 2, -3); NumbersObject n4 = new NumbersObject(-2, 3, 5); NumbersObject nullNumber = new NumbersObject(null,null,null); List<NumbersObject> numbers = Arrays.asList(n1, n2, n3, n4, nullNumber); Ordering ordering = Ordering.natural().nullsLast().onResultOf(new Function<NumbersObject, Integer>() { @Override public Integer apply(NumbersObject numbersObject) { return numbersObject.a; } }); Collections.sort(numbers, ordering); Assert.assertEquals(n4, numbers.get(0)); Assert.assertEquals(n3, numbers.get(1)); Assert.assertEquals(n1, numbers.get(2)); Assert.assertEquals(n2, numbers.get(3)); Assert.assertEquals(nullNumber, numbers.get(4)); } private final class NumbersObject { public final Integer a; public final Integer b; public final Integer c; public NumbersObject(Integer a, Integer b, Integer c) { this.a = a; this.b = b; this.c = c; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("a",a) .add("b",b) .add("c",c) .toString(); } }
compound
可以組合多個 Comparator, 在上一個 Comparator 無法決定時就交給下一個 Comparator 判斷.在排列的屬性有優先順序的時候可以讓程式變簡單.
例如: 先排 a, 再 b, 再 c. null 的話就排前面
@Test public void compound() { NumbersObject n1 = new NumbersObject(1, 2, 3); NumbersObject n2 = new NumbersObject(1, 2, 4); NumbersObject n3 = new NumbersObject(-1, 2, -3); NumbersObject n4 = new NumbersObject(-2, 3, 5); NumbersObject nullNumber = new NumbersObject(null,null,null); List<NumbersObject> numbers = Arrays.asList(n1, n2, n3, n4, nullNumber); Comparator<NumbersObject> byNullFirstA = Ordering.natural().nullsFirst().onResultOf((t) -> t.a); Comparator<NumbersObject> byNullFirstB = Ordering.natural().nullsFirst().onResultOf((t) -> t.b); Comparator<NumbersObject> byNullFirstC = Ordering.natural().nullsFirst().onResultOf((t) -> t.c); Ordering orderByABC = Ordering.compound(Arrays.asList(byNullFirstA, byNullFirstB, byNullFirstC)); Collections.sort(numbers, orderByABC); Assert.assertEquals(nullNumber, numbers.get(0)); Assert.assertEquals(n4, numbers.get(1)); Assert.assertEquals(n3, numbers.get(2)); Assert.assertEquals(n1, numbers.get(3)); Assert.assertEquals(n2, numbers.get(4)); } private final class NumbersObject { public final Integer a; public final Integer b; public final Integer c; public NumbersObject(Integer a, Integer b, Integer c) { this.a = a; this.b = b; this.c = c; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("a",a) .add("b",b) .add("c",c) .toString(); } }
lexicographical
跟 Collections.sort 不同, loxicographical 是用來替很多個 iterable 作排序@Test public void lexicographically() { ImmutableList<String> empty = ImmutableList.of(); ImmutableList<String> a = ImmutableList.of("a"); ImmutableList<String> aa = ImmutableList.of("a", "a"); ImmutableList<String> ab = ImmutableList.of("a", "b"); ImmutableList<String> b = ImmutableList.of("b"); List<ImmutableList<String>> all = Arrays.asList(b,a,ab,aa,empty); Ordering<Iterable<String>> c = Ordering.<String>natural().lexicographical(); Collections.sort(all, c); Assert.assertEquals(empty, all.get(0)); Assert.assertEquals(a, all.get(1)); Assert.assertEquals(aa, all.get(2)); Assert.assertEquals(ab, all.get(3)); Assert.assertEquals(b, all.get(4)); } @Test public void lexicographicallyReverse() { ImmutableList<String> empty = ImmutableList.of(); ImmutableList<String> a = ImmutableList.of("a"); ImmutableList<String> aa = ImmutableList.of("a", "a"); ImmutableList<String> ab = ImmutableList.of("a", "b"); ImmutableList<String> b = ImmutableList.of("b"); List<ImmutableList<String>> all = Arrays.asList(b,a,ab,aa,empty); Ordering<Iterable<String>> c = Ordering.<String>natural().lexicographical().reverse(); Collections.sort(all, c); Assert.assertEquals(empty, all.get(4)); Assert.assertEquals(a, all.get(3)); Assert.assertEquals(aa, all.get(2)); Assert.assertEquals(ab, all.get(1)); Assert.assertEquals(b, all.get(0)); } @Test public void reverseLexicographically() { ImmutableList<String> empty = ImmutableList.of(); ImmutableList<String> a = ImmutableList.of("a"); ImmutableList<String> aa = ImmutableList.of("a", "a"); ImmutableList<String> ab = ImmutableList.of("a", "b"); ImmutableList<String> b = ImmutableList.of("b"); List<ImmutableList<String>> all = Arrays.asList(b,a,ab,aa,empty); Ordering<Iterable<String>> c = Ordering.<String>natural().reverse().lexicographical(); Collections.sort(all, c); System.out.println(all); Assert.assertEquals(empty, all.get(0)); Assert.assertEquals(b, all.get(1)); Assert.assertEquals(a, all.get(2)); Assert.assertEquals(ab, all.get(3)); Assert.assertEquals(aa, all.get(4)); }
onResultOf
就是自訂排序方式, 直行完後會再往前呼叫其他排序法@Test public void onResultOf() { Comparator<Integer> c = Ordering.<Integer>natural().onResultOf((x) -> Optional.ofNullable(x).orElse(4)%5); List<Integer> list = Arrays.asList(5, 11, 4, 1, 2, 5, 7, 9, null); Collections.sort(list, c); System.out.println(list); Assert.assertEquals(5, list.get(0).intValue()); Assert.assertEquals(5, list.get(1).intValue()); Assert.assertEquals(11, list.get(2).intValue()); Assert.assertEquals(1, list.get(3).intValue()); Assert.assertEquals(2, list.get(4).intValue()); Assert.assertEquals(7, list.get(5).intValue()); Assert.assertEquals(4, list.get(6).intValue()); Assert.assertEquals(9, list.get(7).intValue()); Assert.assertEquals(null, list.get(8)); } @Test public void onResultOf_reverse() { Comparator<Integer> c = Ordering.<Integer>natural().reverse().onResultOf((x) -> Optional.ofNullable(x).orElse(4)%5); List<Integer> list = Arrays.asList(5, 11, 4, 1, 2, 5, 7, 9, null); Collections.sort(list, c); System.out.println(list); Assert.assertEquals(5, list.get(8).intValue()); Assert.assertEquals(5, list.get(7).intValue()); Assert.assertEquals(11, list.get(5).intValue()); Assert.assertEquals(1, list.get(6).intValue()); Assert.assertEquals(2, list.get(3).intValue()); Assert.assertEquals(7, list.get(4).intValue()); Assert.assertEquals(4, list.get(0).intValue()); Assert.assertEquals(9, list.get(1).intValue()); Assert.assertEquals(null, list.get(2)); }
greatestOf 與 leastOf
拿排序過資料的最後幾筆與最前幾筆.@Test public void greatestOf() { NumbersObject n1 = new NumbersObject(1, 2, 3); NumbersObject n2 = new NumbersObject(1, 2, 4); NumbersObject n3 = new NumbersObject(-1, 2, -3); NumbersObject n4 = new NumbersObject(-2, 3, 5); NumbersObject nullNumber = new NumbersObject(null,null,null); List<NumbersObject> numbers = Arrays.asList(n1, n2, n3, n4, nullNumber); List<NumbersObject> greatestOf = Ordering.natural().greatestOf(numbers,3); Assert.assertEquals(n4, greatestOf.get(0)); Assert.assertEquals(n3, greatestOf.get(1)); Assert.assertEquals(n1, greatestOf.get(2)); } @Test public void leastOf() { NumbersObject n1 = new NumbersObject(1, 2, 3); NumbersObject n2 = new NumbersObject(2, 2, 4); NumbersObject n3 = new NumbersObject(-1, 2, -3); NumbersObject n4 = new NumbersObject(-2, 3, 5); NumbersObject nullNumber = new NumbersObject(null,null,null); List<NumbersObject> numbers = Arrays.asList(n1, n2, n3, n4, nullNumber); List<NumbersObject> leastOf = Ordering.natural().leastOf(numbers,3); Assert.assertEquals(nullNumber, leastOf.get(0)); Assert.assertEquals(n2, leastOf.get(1)); Assert.assertEquals(n1, leastOf.get(2)); } private final class NumbersObject implements Comparable<NumbersObject> { public final Integer a; public final Integer b; public final Integer c; public NumbersObject(Integer a, Integer b, Integer c) { this.a = a; this.b = b; this.c = c; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("a",a) .add("b",b) .add("c",c) .toString(); } @Override public int compareTo(NumbersObject o) { if (a == null && o.a == null) { return 0; } else if (a == null) { return -1; } else if (o.a == null) { return 1; } else { return Ints.compare(o.a,a); } } }
ImmutableXXX
沒有 ImmutableSet 的時候會用 Collections.unmodifiableSet, 差別是 ImmutableSet 有很多好用的 api 讓程式簡單很多.另外 ImmutableXXX 在能夠避免線性成長的 copy time 時候會盡量避免. 例如 ImmutableList.copyOf(ImmutableSet)
@Test(expected = UnsupportedOperationException.class) public void of() { ImmutableSet.of("a","b").add("a"); } @Test(expected = UnsupportedOperationException.class) public void copyOf() { ImmutableSet.copyOf(Arrays.asList("a","b","c")).add(""); } @Test public void listCopyOfSet() { ImmutableList immutableList = ImmutableList.copyOf(ImmutableSet.of("a","b")); }
Multipleset
像是 set 一樣, 差別是一個同樣的資料可以存多筆. 也可以記錄某種資料總共有幾筆.@RunWith(Parameterized.class) public class MultisetTest { @Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][] { { HashMultiset.create() }, {TreeMultiset.create() }, {LinkedHashMultiset.create() }, {ConcurrentHashMultiset.create()}, }); } private final Multiset<String> testee; public MultisetTest(Multiset<String> testee) { this.testee = testee; } @Test public void test() { testee.addAll(Arrays.asList("A","B","A")); Assert.assertEquals(2, testee.count("A")); Assert.assertEquals(1, testee.count("B")); } } public class ImmutableMultisetTest { @Test public void count() { ImmutableMultisetset = ImmutableMultiset.of("A","B","A"); Assert.assertEquals(2,set.count("A")); Assert.assertEquals(1,set.count("B")); } }