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() {
ImmutableMultiset set = ImmutableMultiset.of("A","B","A");
Assert.assertEquals(2,set.count("A"));
Assert.assertEquals(1,set.count("B"));
}
}